Merge pull request #5814 from hashicorp/provider-fastly-v1

provider/fastly: V1 of the Fastly Provider
This commit is contained in:
Clint 2016-03-24 10:57:32 -05:00
commit c9293cc832
59 changed files with 9082 additions and 0 deletions

11
Godeps/Godeps.json generated
View File

@ -203,6 +203,10 @@
"ImportPath": "github.com/Ensighten/udnssdk", "ImportPath": "github.com/Ensighten/udnssdk",
"Rev": "0290933f5e8afd933f2823fce32bf2847e6ea603" "Rev": "0290933f5e8afd933f2823fce32bf2847e6ea603"
}, },
{
"ImportPath": "github.com/ajg/form",
"Rev": "c9e1c3ae1f869d211cdaa085d23c6af2f5f83866"
},
{ {
"ImportPath": "github.com/apparentlymart/go-cidr/cidr", "ImportPath": "github.com/apparentlymart/go-cidr/cidr",
"Rev": "a3ebdb999b831ecb6ab8a226e31b07b2b9061c47" "Rev": "a3ebdb999b831ecb6ab8a226e31b07b2b9061c47"
@ -1140,6 +1144,11 @@
"ImportPath": "github.com/satori/go.uuid", "ImportPath": "github.com/satori/go.uuid",
"Rev": "d41af8bb6a7704f00bc3b7cba9355ae6a5a80048" "Rev": "d41af8bb6a7704f00bc3b7cba9355ae6a5a80048"
}, },
{
{
"ImportPath": "github.com/sethvargo/go-fastly",
"Rev": "382fee1e5e1adf3cc112fadf4f0a8a98e269ea3c"
},
{ {
"ImportPath": "github.com/soniah/dnsmadeeasy", "ImportPath": "github.com/soniah/dnsmadeeasy",
"Comment": "v1.1-2-g5578a8c", "Comment": "v1.1-2-g5578a8c",
@ -1378,3 +1387,5 @@
} }
] ]
} }

View File

@ -0,0 +1,12 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/fastly"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: fastly.Provider,
})
}

View File

@ -0,0 +1 @@
package main

View File

@ -0,0 +1,31 @@
package fastly
import (
"fmt"
gofastly "github.com/sethvargo/go-fastly"
)
type Config struct {
ApiKey string
}
type FastlyClient struct {
conn *gofastly.Client
}
func (c *Config) Client() (interface{}, error) {
var client FastlyClient
if c.ApiKey == "" {
return nil, fmt.Errorf("[Err] No API key for Fastly")
}
fconn, err := gofastly.NewClient(c.ApiKey)
if err != nil {
return nil, err
}
client.conn = fconn
return &client, nil
}

View File

@ -0,0 +1,34 @@
package fastly
import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
// Provider returns a terraform.ResourceProvider.
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"api_key": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{
"FASTLY_API_KEY",
}, nil),
Description: "Fastly API Key from https://app.fastly.com/#account",
},
},
ResourcesMap: map[string]*schema.Resource{
"fastly_service_v1": resourceServiceV1(),
},
ConfigureFunc: providerConfigure,
}
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
config := Config{
ApiKey: d.Get("api_key").(string),
}
return config.Client()
}

View File

@ -0,0 +1,35 @@
package fastly
import (
"os"
"testing"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider
func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"fastly": testAccProvider,
}
}
func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestProvider_impl(t *testing.T) {
var _ terraform.ResourceProvider = Provider()
}
func testAccPreCheck(t *testing.T) {
if v := os.Getenv("FASTLY_API_KEY"); v == "" {
t.Fatal("FASTLY_API_KEY must be set for acceptance tests")
}
}

View File

@ -0,0 +1,604 @@
package fastly
import (
"errors"
"fmt"
"log"
"time"
"github.com/hashicorp/terraform/helper/schema"
gofastly "github.com/sethvargo/go-fastly"
)
var fastlyNoServiceFoundErr = errors.New("No matching Fastly Service found")
func resourceServiceV1() *schema.Resource {
return &schema.Resource{
Create: resourceServiceV1Create,
Read: resourceServiceV1Read,
Update: resourceServiceV1Update,
Delete: resourceServiceV1Delete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Unique name for this Service",
},
// Active Version represents the currently activated version in Fastly. In
// Terraform, we abstract this number away from the users and manage
// creating and activating. It's used internally, but also exported for
// users to see.
"active_version": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"domain": &schema.Schema{
Type: schema.TypeSet,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "The domain that this Service will respond to",
},
"comment": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
},
},
"default_ttl": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 3600,
Description: "The default Time-to-live (TTL) for the version",
},
"default_host": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "The default hostname for the version",
},
"backend": &schema.Schema{
Type: schema.TypeSet,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
// required fields
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "A name for this Backend",
},
"address": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "An IPv4, hostname, or IPv6 address for the Backend",
},
// Optional fields, defaults where they exist
"auto_loadbalance": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "Should this Backend be load balanced",
},
"between_bytes_timeout": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 10000,
Description: "How long to wait between bytes in milliseconds",
},
"connect_timeout": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 1000,
Description: "How long to wait for a timeout in milliseconds",
},
"error_threshold": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "Number of errors to allow before the Backend is marked as down",
},
"first_byte_timeout": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 15000,
Description: "How long to wait for the first bytes in milliseconds",
},
"max_conn": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 200,
Description: "Maximum number of connections for this Backend",
},
"port": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 80,
Description: "The port number Backend responds on. Default 80",
},
"ssl_check_cert": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "Be strict on checking SSL certs",
},
// UseSSL is something we want to support in the future, but
// requires SSL setup we don't yet have
// TODO: Provide all SSL fields from https://docs.fastly.com/api/config#backend
// "use_ssl": &schema.Schema{
// Type: schema.TypeBool,
// Optional: true,
// Default: false,
// Description: "Whether or not to use SSL to reach the Backend",
// },
"weight": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 100,
Description: "How long to wait for the first bytes in milliseconds",
},
},
},
},
"force_destroy": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
},
}
}
func resourceServiceV1Create(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*FastlyClient).conn
service, err := conn.CreateService(&gofastly.CreateServiceInput{
Name: d.Get("name").(string),
Comment: "Managed by Terraform",
})
if err != nil {
return err
}
d.SetId(service.ID)
return resourceServiceV1Update(d, meta)
}
func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*FastlyClient).conn
// Update Name. No new verions is required for this
if d.HasChange("name") {
_, err := conn.UpdateService(&gofastly.UpdateServiceInput{
ID: d.Id(),
Name: d.Get("name").(string),
})
if err != nil {
return err
}
}
// Once activated, Versions are locked and become immutable. This is true for
// versions that are no longer active. For Domains, Backends, DefaultHost and
// DefaultTTL, a new Version must be created first, and updates posted to that
// Version. Loop these attributes and determine if we need to create a new version first
var needsChange bool
for _, v := range []string{"domain", "backend", "default_host", "default_ttl"} {
if d.HasChange(v) {
needsChange = true
}
}
if needsChange {
latestVersion := d.Get("active_version").(string)
if latestVersion == "" {
// If the service was just created, there is an empty Version 1 available
// that is unlocked and can be updated
latestVersion = "1"
} else {
// Clone the latest version, giving us an unlocked version we can modify
log.Printf("[DEBUG] Creating clone of version (%s) for updates", latestVersion)
newVersion, err := conn.CloneVersion(&gofastly.CloneVersionInput{
Service: d.Id(),
Version: latestVersion,
})
if err != nil {
return err
}
// The new version number is named "Number", but it's actually a string
latestVersion = newVersion.Number
// New versions are not immediately found in the API, or are not
// immediately mutable, so we need to sleep a few and let Fastly ready
// itself. Typically, 7 seconds is enough
log.Printf("[DEBUG] Sleeping 7 seconds to allow Fastly Version to be available")
time.Sleep(7 * time.Second)
}
// update general settings
if d.HasChange("default_host") || d.HasChange("default_ttl") {
opts := gofastly.UpdateSettingsInput{
Service: d.Id(),
Version: latestVersion,
// default_ttl has the same default value of 3600 that is provided by
// the Fastly API, so it's safe to include here
DefaultTTL: uint(d.Get("default_ttl").(int)),
}
if attr, ok := d.GetOk("default_host"); ok {
opts.DefaultHost = attr.(string)
}
log.Printf("[DEBUG] Update Settings opts: %#v", opts)
_, err := conn.UpdateSettings(&opts)
if err != nil {
return err
}
}
// Find differences in domains
if d.HasChange("domain") {
// Note: we don't utilize the PUT endpoint to update a Domain, we simply
// destroy it and create a new one. This is how Terraform works with nested
// sub resources, we only get the full diff not a partial set item diff.
// Because this is done on a new version of the configuration, this is
// considered safe
od, nd := d.GetChange("domain")
if od == nil {
od = new(schema.Set)
}
if nd == nil {
nd = new(schema.Set)
}
ods := od.(*schema.Set)
nds := nd.(*schema.Set)
remove := ods.Difference(nds).List()
add := nds.Difference(ods).List()
// Delete removed domains
for _, dRaw := range remove {
df := dRaw.(map[string]interface{})
opts := gofastly.DeleteDomainInput{
Service: d.Id(),
Version: latestVersion,
Name: df["name"].(string),
}
log.Printf("[DEBUG] Fastly Domain Removal opts: %#v", opts)
err := conn.DeleteDomain(&opts)
if err != nil {
return err
}
}
// POST new Domains
for _, dRaw := range add {
df := dRaw.(map[string]interface{})
opts := gofastly.CreateDomainInput{
Service: d.Id(),
Version: latestVersion,
Name: df["name"].(string),
}
if v, ok := df["comment"]; ok {
opts.Comment = v.(string)
}
log.Printf("[DEBUG] Fastly Domain Addition opts: %#v", opts)
_, err := conn.CreateDomain(&opts)
if err != nil {
return err
}
}
}
// find difference in backends
if d.HasChange("backend") {
// POST new Backends
// Note: we don't utilize the PUT endpoint to update a Backend, we simply
// destroy it and create a new one. This is how Terraform works with nested
// sub resources, we only get the full diff not a partial set item diff.
// Because this is done on a new version of the configuration, this is
// considered safe
ob, nb := d.GetChange("backend")
if ob == nil {
ob = new(schema.Set)
}
if nb == nil {
nb = new(schema.Set)
}
obs := ob.(*schema.Set)
nbs := nb.(*schema.Set)
removeBackends := obs.Difference(nbs).List()
addBackends := nbs.Difference(obs).List()
// DELETE old Backends
for _, bRaw := range removeBackends {
bf := bRaw.(map[string]interface{})
opts := gofastly.DeleteBackendInput{
Service: d.Id(),
Version: latestVersion,
Name: bf["name"].(string),
}
log.Printf("[DEBUG] Fastly Backend Removal opts: %#v", opts)
err := conn.DeleteBackend(&opts)
if err != nil {
return err
}
}
for _, dRaw := range addBackends {
df := dRaw.(map[string]interface{})
opts := gofastly.CreateBackendInput{
Service: d.Id(),
Version: latestVersion,
Name: df["name"].(string),
Address: df["address"].(string),
AutoLoadbalance: df["auto_loadbalance"].(bool),
SSLCheckCert: df["ssl_check_cert"].(bool),
Port: uint(df["port"].(int)),
BetweenBytesTimeout: uint(df["between_bytes_timeout"].(int)),
ConnectTimeout: uint(df["connect_timeout"].(int)),
ErrorThreshold: uint(df["error_threshold"].(int)),
FirstByteTimeout: uint(df["first_byte_timeout"].(int)),
MaxConn: uint(df["max_conn"].(int)),
Weight: uint(df["weight"].(int)),
}
log.Printf("[DEBUG] Create Backend Opts: %#v", opts)
_, err := conn.CreateBackend(&opts)
if err != nil {
return err
}
}
}
// validate version
log.Printf("[DEBUG] Validating Fastly Service (%s), Version (%s)", d.Id(), latestVersion)
valid, msg, err := conn.ValidateVersion(&gofastly.ValidateVersionInput{
Service: d.Id(),
Version: latestVersion,
})
if err != nil {
return fmt.Errorf("[ERR] Error checking validation: %s", err)
}
if !valid {
return fmt.Errorf("[ERR] Invalid configuration for Fastly Service (%s): %s", d.Id(), msg)
}
log.Printf("[DEBUG] Activating Fastly Service (%s), Version (%s)", d.Id(), latestVersion)
_, err = conn.ActivateVersion(&gofastly.ActivateVersionInput{
Service: d.Id(),
Version: latestVersion,
})
if err != nil {
return fmt.Errorf("[ERR] Error activating version (%s): %s", latestVersion, err)
}
// Only if the version is valid and activated do we set the active_version.
// This prevents us from getting stuck in cloning an invalid version
d.Set("active_version", latestVersion)
}
return resourceServiceV1Read(d, meta)
}
func resourceServiceV1Read(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*FastlyClient).conn
// Find the Service. Discard the service because we need the ServiceDetails,
// not just a Service record
_, err := findService(d.Id(), meta)
if err != nil {
switch err {
case fastlyNoServiceFoundErr:
log.Printf("[WARN] %s for ID (%s)", err, d.Id())
d.SetId("")
return nil
default:
return err
}
}
s, err := conn.GetServiceDetails(&gofastly.GetServiceInput{
ID: d.Id(),
})
if err != nil {
return err
}
d.Set("name", s.Name)
d.Set("active_version", s.ActiveVersion.Number)
// If CreateService succeeds, but initial updates to the Service fail, we'll
// have an empty ActiveService version (no version is active, so we can't
// query for information on it)
if s.ActiveVersion.Number != "" {
settingsOpts := gofastly.GetSettingsInput{
Service: d.Id(),
Version: s.ActiveVersion.Number,
}
if settings, err := conn.GetSettings(&settingsOpts); err == nil {
d.Set("default_host", settings.DefaultHost)
d.Set("default_ttl", settings.DefaultTTL)
} else {
return fmt.Errorf("[ERR] Error looking up Version settings for (%s), version (%s): %s", d.Id(), s.ActiveVersion.Number, err)
}
// TODO: update go-fastly to support an ActiveVersion struct, which contains
// domain and backend info in the response. Here we do 2 additional queries
// to find out that info
domainList, err := conn.ListDomains(&gofastly.ListDomainsInput{
Service: d.Id(),
Version: s.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up Domains for (%s), version (%s): %s", d.Id(), s.ActiveVersion.Number, err)
}
// Refresh Domains
dl := flattenDomains(domainList)
if err := d.Set("domain", dl); err != nil {
log.Printf("[WARN] Error setting Domains for (%s): %s", d.Id(), err)
}
// Refresh Backends
backendList, err := conn.ListBackends(&gofastly.ListBackendsInput{
Service: d.Id(),
Version: s.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up Backends for (%s), version (%s): %s", d.Id(), s.ActiveVersion.Number, err)
}
bl := flattenBackends(backendList)
if err := d.Set("backend", bl); err != nil {
log.Printf("[WARN] Error setting Backends for (%s): %s", d.Id(), err)
}
} else {
log.Printf("[DEBUG] Active Version for Service (%s) is empty, no state to refresh", d.Id())
}
return nil
}
func resourceServiceV1Delete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*FastlyClient).conn
// Fastly will fail to delete any service with an Active Version.
// If `force_destroy` is given, we deactivate the active version and then send
// the DELETE call
if d.Get("force_destroy").(bool) {
s, err := conn.GetServiceDetails(&gofastly.GetServiceInput{
ID: d.Id(),
})
if err != nil {
return err
}
if s.ActiveVersion.Number != "" {
_, err := conn.DeactivateVersion(&gofastly.DeactivateVersionInput{
Service: d.Id(),
Version: s.ActiveVersion.Number,
})
if err != nil {
return err
}
}
}
err := conn.DeleteService(&gofastly.DeleteServiceInput{
ID: d.Id(),
})
if err != nil {
return err
}
_, err = findService(d.Id(), meta)
if err != nil {
switch err {
// we expect no records to be found here
case fastlyNoServiceFoundErr:
d.SetId("")
return nil
default:
return err
}
}
// findService above returned something and nil error, but shouldn't have
return fmt.Errorf("[WARN] Tried deleting Service (%s), but was still found", d.Id())
}
func flattenDomains(list []*gofastly.Domain) []map[string]interface{} {
dl := make([]map[string]interface{}, 0, len(list))
for _, d := range list {
dl = append(dl, map[string]interface{}{
"name": d.Name,
"comment": d.Comment,
})
}
return dl
}
func flattenBackends(backendList []*gofastly.Backend) []map[string]interface{} {
var bl []map[string]interface{}
for _, b := range backendList {
// Convert Backend to a map for saving to state.
nb := map[string]interface{}{
"name": b.Name,
"address": b.Address,
"auto_loadbalance": b.AutoLoadbalance,
"between_bytes_timeout": int(b.BetweenBytesTimeout),
"connect_timeout": int(b.ConnectTimeout),
"error_threshold": int(b.ErrorThreshold),
"first_byte_timeout": int(b.FirstByteTimeout),
"max_conn": int(b.MaxConn),
"port": int(b.Port),
"ssl_check_cert": b.SSLCheckCert,
"weight": int(b.Weight),
}
bl = append(bl, nb)
}
return bl
}
// findService finds a Fastly Service via the ListServices endpoint, returning
// the Service if found.
//
// Fastly API does not include any "deleted_at" type parameter to indicate
// that a Service has been deleted. GET requests to a deleted Service will
// return 200 OK and have the full output of the Service for an unknown time
// (days, in my testing). In order to determine if a Service is deleted, we
// need to hit /service and loop the returned Services, searching for the one
// in question. This endpoint only returns active or "alive" services. If the
// Service is not included, then it's "gone"
//
// Returns a fastlyNoServiceFoundErr error if the Service is not found in the
// ListServices response.
func findService(id string, meta interface{}) (*gofastly.Service, error) {
conn := meta.(*FastlyClient).conn
l, err := conn.ListServices(&gofastly.ListServicesInput{})
if err != nil {
return nil, fmt.Errorf("[WARN] Error listing servcies when deleting Fastly Service (%s): %s", id, err)
}
for _, s := range l {
if s.ID == id {
log.Printf("[DEBUG] Found Service (%s)", id)
return s, nil
}
}
return nil, fastlyNoServiceFoundErr
}

View File

@ -0,0 +1,458 @@
package fastly
import (
"fmt"
"reflect"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
gofastly "github.com/sethvargo/go-fastly"
)
func TestResourceFastlyFlattenDomains(t *testing.T) {
cases := []struct {
remote []*gofastly.Domain
local []map[string]interface{}
}{
{
remote: []*gofastly.Domain{
&gofastly.Domain{
Name: "test.notexample.com",
Comment: "not comment",
},
},
local: []map[string]interface{}{
map[string]interface{}{
"name": "test.notexample.com",
"comment": "not comment",
},
},
},
{
remote: []*gofastly.Domain{
&gofastly.Domain{
Name: "test.notexample.com",
},
},
local: []map[string]interface{}{
map[string]interface{}{
"name": "test.notexample.com",
"comment": "",
},
},
},
}
for _, c := range cases {
out := flattenDomains(c.remote)
if !reflect.DeepEqual(out, c.local) {
t.Fatalf("Error matching:\nexpected: %#v\ngot: %#v", c.local, out)
}
}
}
func TestResourceFastlyFlattenBackend(t *testing.T) {
cases := []struct {
remote []*gofastly.Backend
local []map[string]interface{}
}{
{
remote: []*gofastly.Backend{
&gofastly.Backend{
Name: "test.notexample.com",
Address: "www.notexample.com",
Port: uint(80),
AutoLoadbalance: true,
BetweenBytesTimeout: uint(10000),
ConnectTimeout: uint(1000),
ErrorThreshold: uint(0),
FirstByteTimeout: uint(15000),
MaxConn: uint(200),
SSLCheckCert: true,
Weight: uint(100),
},
},
local: []map[string]interface{}{
map[string]interface{}{
"name": "test.notexample.com",
"address": "www.notexample.com",
"port": 80,
"auto_loadbalance": true,
"between_bytes_timeout": 10000,
"connect_timeout": 1000,
"error_threshold": 0,
"first_byte_timeout": 15000,
"max_conn": 200,
"ssl_check_cert": true,
"weight": 100,
},
},
},
}
for _, c := range cases {
out := flattenBackends(c.remote)
if !reflect.DeepEqual(out, c.local) {
t.Fatalf("Error matching:\nexpected: %#v\ngot: %#v", c.local, out)
}
}
}
func TestAccFastlyServiceV1_updateDomain(t *testing.T) {
var service gofastly.ServiceDetail
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
nameUpdate := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
domainName1 := fmt.Sprintf("%s.notadomain.com", acctest.RandString(10))
domainName2 := fmt.Sprintf("%s.notadomain.com", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckServiceV1Destroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccServiceV1Config(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1Attributes(&service, name, []string{domainName1}),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "name", name),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "active_version", "1"),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "domain.#", "1"),
),
},
resource.TestStep{
Config: testAccServiceV1Config_domainUpdate(nameUpdate, domainName1, domainName2),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1Attributes(&service, nameUpdate, []string{domainName1, domainName2}),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "name", nameUpdate),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "active_version", "2"),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "domain.#", "2"),
),
},
},
})
}
func TestAccFastlyServiceV1_updateBackend(t *testing.T) {
var service gofastly.ServiceDetail
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
backendName := fmt.Sprintf("%s.aws.amazon.com", acctest.RandString(3))
backendName2 := fmt.Sprintf("%s.aws.amazon.com", acctest.RandString(3))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckServiceV1Destroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccServiceV1Config_backend(name, backendName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1Attributes_backends(&service, name, []string{backendName}),
),
},
resource.TestStep{
Config: testAccServiceV1Config_backend_update(name, backendName, backendName2),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1Attributes_backends(&service, name, []string{backendName, backendName2}),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "active_version", "2"),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "backend.#", "2"),
),
},
},
})
}
func TestAccFastlyServiceV1_basic(t *testing.T) {
var service gofastly.ServiceDetail
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
domainName := fmt.Sprintf("%s.notadomain.com", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckServiceV1Destroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccServiceV1Config(name, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1Attributes(&service, name, []string{domainName}),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "name", name),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "active_version", "1"),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "domain.#", "1"),
),
},
},
})
}
// ServiceV1_disappears  test that a non-empty plan is returned when a Fastly
// Service is destroyed outside of Terraform, and can no longer be found,
// correctly clearing the ID field and generating a new plan
func TestAccFastlyServiceV1_disappears(t *testing.T) {
var service gofastly.ServiceDetail
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
domainName := fmt.Sprintf("%s.notadomain.com", acctest.RandString(10))
testDestroy := func(*terraform.State) error {
// reach out and DELETE the service
conn := testAccProvider.Meta().(*FastlyClient).conn
// deactivate active version to destoy
_, err := conn.DeactivateVersion(&gofastly.DeactivateVersionInput{
Service: service.ID,
Version: service.ActiveVersion.Number,
})
if err != nil {
return err
}
// delete service
err = conn.DeleteService(&gofastly.DeleteServiceInput{
ID: service.ID,
})
if err != nil {
return err
}
return nil
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckServiceV1Destroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccServiceV1Config(name, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testDestroy,
),
ExpectNonEmptyPlan: true,
},
},
})
}
func testAccCheckServiceV1Exists(n string, service *gofastly.ServiceDetail) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No Service ID is set")
}
conn := testAccProvider.Meta().(*FastlyClient).conn
latest, err := conn.GetServiceDetails(&gofastly.GetServiceInput{
ID: rs.Primary.ID,
})
if err != nil {
return err
}
*service = *latest
return nil
}
}
func testAccCheckFastlyServiceV1Attributes(service *gofastly.ServiceDetail, name string, domains []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if service.Name != name {
return fmt.Errorf("Bad name, expected (%s), got (%s)", name, service.Name)
}
conn := testAccProvider.Meta().(*FastlyClient).conn
domainList, err := conn.ListDomains(&gofastly.ListDomainsInput{
Service: service.ID,
Version: service.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up Domains for (%s), version (%s): %s", service.Name, service.ActiveVersion.Number, err)
}
expected := len(domains)
for _, d := range domainList {
for _, e := range domains {
if d.Name == e {
expected--
}
}
}
if expected > 0 {
return fmt.Errorf("Domain count mismatch, expected: %#v, got: %#v", domains, domainList)
}
return nil
}
}
func testAccCheckFastlyServiceV1Attributes_backends(service *gofastly.ServiceDetail, name string, backends []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if service.Name != name {
return fmt.Errorf("Bad name, expected (%s), got (%s)", name, service.Name)
}
conn := testAccProvider.Meta().(*FastlyClient).conn
backendList, err := conn.ListBackends(&gofastly.ListBackendsInput{
Service: service.ID,
Version: service.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up Backends for (%s), version (%s): %s", service.Name, service.ActiveVersion.Number, err)
}
expected := len(backendList)
for _, b := range backendList {
for _, e := range backends {
if b.Address == e {
expected--
}
}
}
if expected > 0 {
return fmt.Errorf("Backend count mismatch, expected: %#v, got: %#v", backends, backendList)
}
return nil
}
}
func testAccCheckServiceV1Destroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "fastly_service_v1" {
continue
}
conn := testAccProvider.Meta().(*FastlyClient).conn
l, err := conn.ListServices(&gofastly.ListServicesInput{})
if err != nil {
return fmt.Errorf("[WARN] Error listing servcies when deleting Fastly Service (%s): %s", rs.Primary.ID, err)
}
for _, s := range l {
if s.ID == rs.Primary.ID {
// service still found
return fmt.Errorf("[WARN] Tried deleting Service (%s), but was still found", rs.Primary.ID)
}
}
}
return nil
}
func testAccServiceV1Config(name, domain string) string {
return fmt.Sprintf(`
resource "fastly_service_v1" "foo" {
name = "%s"
domain {
name = "%s"
comment = "tf-testing-domain"
}
backend {
address = "aws.amazon.com"
name = "amazon docs"
}
force_destroy = true
}`, name, domain)
}
func testAccServiceV1Config_domainUpdate(name, domain1, domain2 string) string {
return fmt.Sprintf(`
resource "fastly_service_v1" "foo" {
name = "%s"
domain {
name = "%s"
comment = "tf-testing-domain"
}
domain {
name = "%s"
comment = "tf-testing-other-domain"
}
backend {
address = "aws.amazon.com"
name = "amazon docs"
}
force_destroy = true
}`, name, domain1, domain2)
}
func testAccServiceV1Config_backend(name, backend string) string {
return fmt.Sprintf(`
resource "fastly_service_v1" "foo" {
name = "%s"
domain {
name = "test.notadomain.com"
comment = "tf-testing-domain"
}
backend {
address = "%s"
name = "tf -test backend"
}
force_destroy = true
}`, name, backend)
}
func testAccServiceV1Config_backend_update(name, backend, backend2 string) string {
return fmt.Sprintf(`
resource "fastly_service_v1" "foo" {
name = "%s"
default_ttl = 3400
domain {
name = "test.notadomain.com"
comment = "tf-testing-domain"
}
backend {
address = "%s"
name = "tf-test-backend"
}
backend {
address = "%s"
name = "tf-test-backend-other"
}
force_destroy = true
}`, name, backend, backend2)
}

24
vendor/github.com/ajg/form/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,24 @@
## Copyright 2014 Alvaro J. Genial. All rights reserved.
## Use of this source code is governed by a BSD-style
## license that can be found in the LICENSE file.
language: go
go:
- tip
- 1.3
# - 1.2
# Note: 1.2 is disabled because it seems to require that cover
# be installed from code.google.com/p/go.tools/cmd/cover
before_install:
- go get -v golang.org/x/tools/cmd/cover
- go get -v golang.org/x/tools/cmd/vet
- go get -v github.com/golang/lint/golint
- export PATH=$PATH:/home/travis/gopath/bin
script:
- go build -v ./...
- go test -v -cover ./...
- go vet ./...
- golint .

27
vendor/github.com/ajg/form/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2014 Alvaro J. Genial. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

205
vendor/github.com/ajg/form/README.md generated vendored Normal file
View File

@ -0,0 +1,205 @@
form
====
A Form Encoding & Decoding Package for Go, written by [Alvaro J. Genial](http://alva.ro).
[![Build Status](https://travis-ci.org/ajg/form.png?branch=master)](https://travis-ci.org/ajg/form)
[![GoDoc](https://godoc.org/github.com/ajg/form?status.png)](https://godoc.org/github.com/ajg/form)
Synopsis
--------
This library is designed to allow seamless, high-fidelity encoding and decoding of arbitrary data in `application/x-www-form-urlencoded` format and as [`url.Values`](http://golang.org/pkg/net/url/#Values). It is intended to be useful primarily in dealing with web forms and URI query strings, both of which natively employ said format.
Unsurprisingly, `form` is modeled after other Go [`encoding`](http://golang.org/pkg/encoding/) packages, in particular [`encoding/json`](http://golang.org/pkg/encoding/json/), and follows the same conventions (see below for more.) It aims to automatically handle any kind of concrete Go [data value](#values) (i.e., not functions, channels, etc.) while providing mechanisms for custom behavior.
Status
------
The implementation is in usable shape and is fairly well tested with its accompanying test suite. The API is unlikely to change much, but still may. Lastly, the code has not yet undergone a security review to ensure it is free of vulnerabilities. Please file an issue or send a pull request for fixes & improvements.
Dependencies
------------
The only requirement is [Go 1.2](http://golang.org/doc/go1.2) or later.
Usage
-----
```go
import "github.com/ajg/form"
```
Given a type like the following...
```go
type User struct {
Name string `form:"name"`
Email string `form:"email"`
Joined time.Time `form:"joined,omitempty"`
Posts []int `form:"posts"`
Preferences map[string]string `form:"prefs"`
Avatar []byte `form:"avatar"`
PasswordHash int64 `form:"-"`
}
```
...it is easy to encode data of that type...
```go
func PostUser(url string, u User) error {
var c http.Client
_, err := c.PostForm(url, form.EncodeToValues(u))
return err
}
```
...as well as decode it...
```go
func Handler(w http.ResponseWriter, r *http.Request) {
var u User
d := form.NewDecoder(r.Body)
if err := d.Decode(&u); err != nil {
http.Error(w, "Form could not be decoded", http.StatusBadRequest)
return
}
fmt.Fprintf(w, "Decoded: %#v", u)
}
```
...without having to do any grunt work.
Field Tags
----------
Like other encoding packages, `form` supports the following options for fields:
- `` `form:"-"` ``: Causes the field to be ignored during encoding and decoding.
- `` `form:"<name>"` ``: Overrides the field's name; useful especially when dealing with external identifiers in camelCase, as are commonly found on the web.
- `` `form:",omitempty"` ``: Elides the field during encoding if it is empty (typically meaning equal to the type's zero value.)
- `` `form:"<name>,omitempty"` ``: The way to combine the two options above.
Values
------
### Simple Values
Values of the following types are all considered simple:
- `bool`
- `int`, `int8`, `int16`, `int32`, `int64`, `rune`
- `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `byte`
- `float32`, `float64`
- `complex64`, `complex128`
- `string`
- `[]byte` (see note)
- [`time.Time`](http://golang.org/pkg/time/#Time)
- [`url.URL`](http://golang.org/pkg/net/url/#URL)
- An alias of any of the above
- A pointer to any of the above
### Composite Values
A composite value is one that can contain other values. Values of the following kinds...
- Maps
- Slices; except `[]byte` (see note)
- Structs; except [`time.Time`](http://golang.org/pkg/time/#Time) and [`url.URL`](http://golang.org/pkg/net/url/#URL)
- Arrays
- An alias of any of the above
- A pointer to any of the above
...are considered composites in general, unless they implement custom marshaling/unmarshaling. Composite values are encoded as a flat mapping of paths to values, where the paths are constructed by joining the parent and child paths with a period (`.`).
(Note: a byte slice is treated as a `string` by default because it's more efficient, but can also be decoded as a slice—i.e., with indexes.)
### Untyped Values
While encouraged, it is not necessary to define a type (e.g. a `struct`) in order to use `form`, since it is able to encode and decode untyped data generically using the following rules:
- Simple values will be treated as a `string`.
- Composite values will be treated as a `map[string]interface{}`, itself able to contain nested values (both scalar and compound) ad infinitum.
- However, if there is a value (of any supported type) already present in a map for a given key, then it will be used when possible, rather than being replaced with a generic value as specified above; this makes it possible to handle partially typed, dynamic or schema-less values.
### Unsupported Values
Values of the following kinds aren't supported and, if present, must be ignored.
- Channel
- Function
- Unsafe pointer
- An alias of any of the above
- A pointer to any of the above
Custom Marshaling
-----------------
There is a default (generally lossless) marshaling & unmarshaling scheme for any concrete data value in Go, which is good enough in most cases. However, it is possible to override it and use a custom scheme. For instance, a "binary" field could be marshaled more efficiently using [base64](http://golang.org/pkg/encoding/base64/) to prevent it from being percent-escaped during serialization to `application/x-www-form-urlencoded` format.
Because `form` provides support for [`encoding.TextMarshaler`](http://golang.org/pkg/encoding/#TextMarshaler) and [`encoding.TextUnmarshaler`](http://golang.org/pkg/encoding/#TextUnmarshaler) it is easy to do that; for instance, like this:
```go
import "encoding"
type Binary []byte
var (
_ encoding.TextMarshaler = &Binary{}
_ encoding.TextUnmarshaler = &Binary{}
)
func (b Binary) MarshalText() ([]byte, error) {
return []byte(base64.URLEncoding.EncodeToString([]byte(b))), nil
}
func (b *Binary) UnmarshalText(text []byte) error {
bs, err := base64.URLEncoding.DecodeString(string(text))
if err == nil {
*b = Binary(bs)
}
return err
}
```
Now any value with type `Binary` will automatically be encoded using the [URL](http://golang.org/pkg/encoding/base64/#URLEncoding) variant of base64. It is left as an exercise to the reader to improve upon this scheme by eliminating the need for padding (which, besides being superfluous, uses `=`, a character that will end up percent-escaped.)
Keys
----
In theory any value can be a key as long as it has a string representation. However, periods have special meaning to `form`, and thus, under the hood (i.e. in encoded form) they are transparently escaped using a preceding backslash (`\`). Backslashes within keys, themselves, are also escaped in this manner (e.g. as `\\`) in order to permit representing `\.` itself (as `\\\.`).
(Note: it is normally unnecessary to deal with this issue unless keys are being constructed manually—e.g. literally embedded in HTML or in a URI.)
Limitations
-----------
- Circular (self-referential) values are untested.
Future Work
-----------
The following items would be nice to have in the future—though they are not being worked on yet:
- An option to treat all values as if they had been tagged with `omitempty`.
- An option to automatically treat all field names in `camelCase` or `underscore_case`.
- Built-in support for the types in [`math/big`](http://golang.org/pkg/math/big/).
- Built-in support for the types in [`image/color`](http://golang.org/pkg/image/color/).
- Improve encoding/decoding by reading/writing directly from/to the `io.Reader`/`io.Writer` when possible, rather than going through an intermediate representation (i.e. `node`) which requires more memory.
(Feel free to implement any of these and then send a pull request.)
Related Work
------------
- Package [gorilla/schema](https://github.com/gorilla/schema), which only implements decoding.
- Package [google/go-querystring](https://github.com/google/go-querystring), which only implements encoding.
License
-------
This library is distributed under a BSD-style [LICENSE](./LICENSE).

330
vendor/github.com/ajg/form/decode.go generated vendored Normal file
View File

@ -0,0 +1,330 @@
// Copyright 2014 Alvaro J. Genial. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package form
import (
"fmt"
"io"
"io/ioutil"
"net/url"
"reflect"
"strconv"
"time"
)
// NewDecoder returns a new form decoder.
func NewDecoder(r io.Reader) *decoder {
return &decoder{r}
}
// decoder decodes data from a form (application/x-www-form-urlencoded).
type decoder struct {
r io.Reader
}
// Decode reads in and decodes form-encoded data into dst.
func (d decoder) Decode(dst interface{}) error {
bs, err := ioutil.ReadAll(d.r)
if err != nil {
return err
}
vs, err := url.ParseQuery(string(bs))
if err != nil {
return err
}
v := reflect.ValueOf(dst)
return decodeNode(v, parseValues(vs, canIndexOrdinally(v)))
}
// DecodeString decodes src into dst.
func DecodeString(dst interface{}, src string) error {
vs, err := url.ParseQuery(src)
if err != nil {
return err
}
v := reflect.ValueOf(dst)
return decodeNode(v, parseValues(vs, canIndexOrdinally(v)))
}
// DecodeValues decodes vs into dst.
func DecodeValues(dst interface{}, vs url.Values) error {
v := reflect.ValueOf(dst)
return decodeNode(v, parseValues(vs, canIndexOrdinally(v)))
}
func decodeNode(v reflect.Value, n node) (err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
}
}()
if v.Kind() == reflect.Slice {
return fmt.Errorf("could not decode directly into slice; use pointer to slice")
}
decodeValue(v, n)
return nil
}
func decodeValue(v reflect.Value, x interface{}) {
t := v.Type()
k := v.Kind()
if k == reflect.Ptr && v.IsNil() {
v.Set(reflect.New(t.Elem()))
}
if unmarshalValue(v, x) {
return
}
empty := isEmpty(x)
switch k {
case reflect.Ptr:
decodeValue(v.Elem(), x)
return
case reflect.Interface:
if !v.IsNil() {
decodeValue(v.Elem(), x)
return
} else if empty {
return // Allow nil interfaces only if empty.
} else {
panic("form: cannot decode non-empty value into into nil interface")
}
}
if empty {
v.Set(reflect.Zero(t)) // Treat the empty string as the zero value.
return
}
switch k {
case reflect.Struct:
if t.ConvertibleTo(timeType) {
decodeTime(v, x)
} else if t.ConvertibleTo(urlType) {
decodeURL(v, x)
} else {
decodeStruct(v, x)
}
case reflect.Slice:
decodeSlice(v, x)
case reflect.Array:
decodeArray(v, x)
case reflect.Map:
decodeMap(v, x)
case reflect.Invalid, reflect.Uintptr, reflect.UnsafePointer, reflect.Chan, reflect.Func:
panic(t.String() + " has unsupported kind " + k.String())
default:
decodeBasic(v, x)
}
}
func decodeStruct(v reflect.Value, x interface{}) {
t := v.Type()
for k, c := range getNode(x) {
if f, ok := findField(v, k); !ok && k == "" {
panic(getString(x) + " cannot be decoded as " + t.String())
} else if !ok {
panic(k + " doesn't exist in " + t.String())
} else if !f.CanSet() {
panic(k + " cannot be set in " + t.String())
} else {
decodeValue(f, c)
}
}
}
func decodeMap(v reflect.Value, x interface{}) {
t := v.Type()
if v.IsNil() {
v.Set(reflect.MakeMap(t))
}
for k, c := range getNode(x) {
i := reflect.New(t.Key()).Elem()
decodeValue(i, k)
w := v.MapIndex(i)
if w.IsValid() { // We have an actual element value to decode into.
if w.Kind() == reflect.Interface {
w = w.Elem()
}
w = reflect.New(w.Type()).Elem()
} else if t.Elem().Kind() != reflect.Interface { // The map's element type is concrete.
w = reflect.New(t.Elem()).Elem()
} else {
// The best we can do here is to decode as either a string (for scalars) or a map[string]interface {} (for the rest).
// We could try to guess the type based on the string (e.g. true/false => bool) but that'll get ugly fast,
// especially if we have to guess the kind (slice vs. array vs. map) and index type (e.g. string, int, etc.)
switch c.(type) {
case node:
w = reflect.MakeMap(stringMapType)
case string:
w = reflect.New(stringType).Elem()
default:
panic("value is neither node nor string")
}
}
decodeValue(w, c)
v.SetMapIndex(i, w)
}
}
func decodeArray(v reflect.Value, x interface{}) {
t := v.Type()
for k, c := range getNode(x) {
i, err := strconv.Atoi(k)
if err != nil {
panic(k + " is not a valid index for type " + t.String())
}
if l := v.Len(); i >= l {
panic("index is above array size")
}
decodeValue(v.Index(i), c)
}
}
func decodeSlice(v reflect.Value, x interface{}) {
t := v.Type()
if t.Elem().Kind() == reflect.Uint8 {
// Allow, but don't require, byte slices to be encoded as a single string.
if s, ok := x.(string); ok {
v.SetBytes([]byte(s))
return
}
}
// NOTE: Implicit indexing is currently done at the parseValues level,
// so if if an implicitKey reaches here it will always replace the last.
implicit := 0
for k, c := range getNode(x) {
var i int
if k == implicitKey {
i = implicit
implicit++
} else {
explicit, err := strconv.Atoi(k)
if err != nil {
panic(k + " is not a valid index for type " + t.String())
}
i = explicit
implicit = explicit + 1
}
// "Extend" the slice if it's too short.
if l := v.Len(); i >= l {
delta := i - l + 1
v.Set(reflect.AppendSlice(v, reflect.MakeSlice(t, delta, delta)))
}
decodeValue(v.Index(i), c)
}
}
func decodeBasic(v reflect.Value, x interface{}) {
t := v.Type()
switch k, s := t.Kind(), getString(x); k {
case reflect.Bool:
if b, e := strconv.ParseBool(s); e == nil {
v.SetBool(b)
} else {
panic("could not parse bool from " + strconv.Quote(s))
}
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
if i, e := strconv.ParseInt(s, 10, 64); e == nil {
v.SetInt(i)
} else {
panic("could not parse int from " + strconv.Quote(s))
}
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64:
if u, e := strconv.ParseUint(s, 10, 64); e == nil {
v.SetUint(u)
} else {
panic("could not parse uint from " + strconv.Quote(s))
}
case reflect.Float32,
reflect.Float64:
if f, e := strconv.ParseFloat(s, 64); e == nil {
v.SetFloat(f)
} else {
panic("could not parse float from " + strconv.Quote(s))
}
case reflect.Complex64,
reflect.Complex128:
var c complex128
if n, err := fmt.Sscanf(s, "%g", &c); n == 1 && err == nil {
v.SetComplex(c)
} else {
panic("could not parse complex from " + strconv.Quote(s))
}
case reflect.String:
v.SetString(s)
default:
panic(t.String() + " has unsupported kind " + k.String())
}
}
func decodeTime(v reflect.Value, x interface{}) {
t := v.Type()
s := getString(x)
// TODO: Find a more efficient way to do this.
for _, f := range allowedTimeFormats {
if p, err := time.Parse(f, s); err == nil {
v.Set(reflect.ValueOf(p).Convert(v.Type()))
return
}
}
panic("cannot decode string `" + s + "` as " + t.String())
}
func decodeURL(v reflect.Value, x interface{}) {
t := v.Type()
s := getString(x)
if u, err := url.Parse(s); err == nil {
v.Set(reflect.ValueOf(*u).Convert(v.Type()))
return
}
panic("cannot decode string `" + s + "` as " + t.String())
}
var allowedTimeFormats = []string{
"2006-01-02T15:04:05.999999999Z07:00",
"2006-01-02T15:04:05.999999999Z07",
"2006-01-02T15:04:05.999999999Z",
"2006-01-02T15:04:05.999999999",
"2006-01-02T15:04:05Z07:00",
"2006-01-02T15:04:05Z07",
"2006-01-02T15:04:05Z",
"2006-01-02T15:04:05",
"2006-01-02T15:04Z",
"2006-01-02T15:04",
"2006-01-02T15Z",
"2006-01-02T15",
"2006-01-02",
"2006-01",
"2006",
"15:04:05.999999999Z07:00",
"15:04:05.999999999Z07",
"15:04:05.999999999Z",
"15:04:05.999999999",
"15:04:05Z07:00",
"15:04:05Z07",
"15:04:05Z",
"15:04:05",
"15:04Z",
"15:04",
"15Z",
"15",
}

351
vendor/github.com/ajg/form/encode.go generated vendored Normal file
View File

@ -0,0 +1,351 @@
// Copyright 2014 Alvaro J. Genial. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package form
import (
"encoding"
"errors"
"fmt"
"io"
"net/url"
"reflect"
"strconv"
"strings"
"time"
)
// NewEncoder returns a new form encoder.
func NewEncoder(w io.Writer) *encoder {
return &encoder{w}
}
// encoder provides a way to encode to a Writer.
type encoder struct {
w io.Writer
}
// Encode encodes dst as form and writes it out using the encoder's Writer.
func (e encoder) Encode(dst interface{}) error {
v := reflect.ValueOf(dst)
n, err := encodeToNode(v)
if err != nil {
return err
}
s := n.Values().Encode()
l, err := io.WriteString(e.w, s)
switch {
case err != nil:
return err
case l != len(s):
return errors.New("could not write data completely")
}
return nil
}
// EncodeToString encodes dst as a form and returns it as a string.
func EncodeToString(dst interface{}) (string, error) {
v := reflect.ValueOf(dst)
n, err := encodeToNode(v)
if err != nil {
return "", err
}
return n.Values().Encode(), nil
}
// EncodeToValues encodes dst as a form and returns it as Values.
func EncodeToValues(dst interface{}) (url.Values, error) {
v := reflect.ValueOf(dst)
n, err := encodeToNode(v)
if err != nil {
return nil, err
}
return n.Values(), nil
}
func encodeToNode(v reflect.Value) (n node, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
}
}()
return getNode(encodeValue(v)), nil
}
func encodeValue(v reflect.Value) interface{} {
t := v.Type()
k := v.Kind()
if s, ok := marshalValue(v); ok {
return s
} else if isEmptyValue(v) {
return "" // Treat the zero value as the empty string.
}
switch k {
case reflect.Ptr, reflect.Interface:
return encodeValue(v.Elem())
case reflect.Struct:
if t.ConvertibleTo(timeType) {
return encodeTime(v)
} else if t.ConvertibleTo(urlType) {
return encodeURL(v)
}
return encodeStruct(v)
case reflect.Slice:
return encodeSlice(v)
case reflect.Array:
return encodeArray(v)
case reflect.Map:
return encodeMap(v)
case reflect.Invalid, reflect.Uintptr, reflect.UnsafePointer, reflect.Chan, reflect.Func:
panic(t.String() + " has unsupported kind " + t.Kind().String())
default:
return encodeBasic(v)
}
}
func encodeStruct(v reflect.Value) interface{} {
t := v.Type()
n := node{}
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
k, oe := fieldInfo(f)
if k == "-" {
continue
} else if fv := v.Field(i); oe && isEmptyValue(fv) {
delete(n, k)
} else {
n[k] = encodeValue(fv)
}
}
return n
}
func encodeMap(v reflect.Value) interface{} {
n := node{}
for _, i := range v.MapKeys() {
k := getString(encodeValue(i))
n[k] = encodeValue(v.MapIndex(i))
}
return n
}
func encodeArray(v reflect.Value) interface{} {
n := node{}
for i := 0; i < v.Len(); i++ {
n[strconv.Itoa(i)] = encodeValue(v.Index(i))
}
return n
}
func encodeSlice(v reflect.Value) interface{} {
t := v.Type()
if t.Elem().Kind() == reflect.Uint8 {
return string(v.Bytes()) // Encode byte slices as a single string by default.
}
n := node{}
for i := 0; i < v.Len(); i++ {
n[strconv.Itoa(i)] = encodeValue(v.Index(i))
}
return n
}
func encodeTime(v reflect.Value) string {
t := v.Convert(timeType).Interface().(time.Time)
if t.Year() == 0 && (t.Month() == 0 || t.Month() == 1) && (t.Day() == 0 || t.Day() == 1) {
return t.Format("15:04:05.999999999Z07:00")
} else if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 && t.Nanosecond() == 0 {
return t.Format("2006-01-02")
}
return t.Format("2006-01-02T15:04:05.999999999Z07:00")
}
func encodeURL(v reflect.Value) string {
u := v.Convert(urlType).Interface().(url.URL)
return u.String()
}
func encodeBasic(v reflect.Value) string {
t := v.Type()
switch k := t.Kind(); k {
case reflect.Bool:
return strconv.FormatBool(v.Bool())
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
return strconv.FormatInt(v.Int(), 10)
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64:
return strconv.FormatUint(v.Uint(), 10)
case reflect.Float32:
return strconv.FormatFloat(v.Float(), 'g', -1, 32)
case reflect.Float64:
return strconv.FormatFloat(v.Float(), 'g', -1, 64)
case reflect.Complex64, reflect.Complex128:
s := fmt.Sprintf("%g", v.Complex())
return strings.TrimSuffix(strings.TrimPrefix(s, "("), ")")
case reflect.String:
return v.String()
}
panic(t.String() + " has unsupported kind " + t.Kind().String())
}
func isEmptyValue(v reflect.Value) bool {
switch t := v.Type(); v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Complex64, reflect.Complex128:
return v.Complex() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
case reflect.Struct:
if t.ConvertibleTo(timeType) {
return v.Convert(timeType).Interface().(time.Time).IsZero()
}
return reflect.DeepEqual(v, reflect.Zero(t))
}
return false
}
// canIndexOrdinally returns whether a value contains an ordered sequence of elements.
func canIndexOrdinally(v reflect.Value) bool {
if !v.IsValid() {
return false
}
switch t := v.Type(); t.Kind() {
case reflect.Ptr, reflect.Interface:
return canIndexOrdinally(v.Elem())
case reflect.Slice, reflect.Array:
return true
}
return false
}
func fieldInfo(f reflect.StructField) (k string, oe bool) {
if f.PkgPath != "" { // Skip private fields.
return omittedKey, oe
}
k = f.Name
tag := f.Tag.Get("form")
if tag == "" {
return k, oe
}
ps := strings.SplitN(tag, ",", 2)
if ps[0] != "" {
k = ps[0]
}
if len(ps) == 2 {
oe = ps[1] == "omitempty"
}
return k, oe
}
func findField(v reflect.Value, n string) (reflect.Value, bool) {
t := v.Type()
l := v.NumField()
// First try named fields.
for i := 0; i < l; i++ {
f := t.Field(i)
k, _ := fieldInfo(f)
if k == omittedKey {
continue
} else if n == k {
return v.Field(i), true
}
}
// Then try anonymous (embedded) fields.
for i := 0; i < l; i++ {
f := t.Field(i)
k, _ := fieldInfo(f)
if k == omittedKey || !f.Anonymous { // || k != "" ?
continue
}
fv := v.Field(i)
fk := fv.Kind()
for fk == reflect.Ptr || fk == reflect.Interface {
fv = fv.Elem()
fk = fv.Kind()
}
if fk != reflect.Struct {
continue
}
if ev, ok := findField(fv, n); ok {
return ev, true
}
}
return reflect.Value{}, false
}
var (
stringType = reflect.TypeOf(string(""))
stringMapType = reflect.TypeOf(map[string]interface{}{})
timeType = reflect.TypeOf(time.Time{})
timePtrType = reflect.TypeOf(&time.Time{})
urlType = reflect.TypeOf(url.URL{})
)
func skipTextMarshalling(t reflect.Type) bool {
/*// Skip time.Time because its text unmarshaling is overly rigid:
return t == timeType || t == timePtrType*/
// Skip time.Time & convertibles because its text unmarshaling is overly rigid:
return t.ConvertibleTo(timeType) || t.ConvertibleTo(timePtrType)
}
func unmarshalValue(v reflect.Value, x interface{}) bool {
if skipTextMarshalling(v.Type()) {
return false
}
tu, ok := v.Interface().(encoding.TextUnmarshaler)
if !ok && !v.CanAddr() {
return false
} else if !ok {
return unmarshalValue(v.Addr(), x)
}
s := getString(x)
if err := tu.UnmarshalText([]byte(s)); err != nil {
panic(err)
}
return true
}
func marshalValue(v reflect.Value) (string, bool) {
if skipTextMarshalling(v.Type()) {
return "", false
}
tm, ok := v.Interface().(encoding.TextMarshaler)
if !ok && !v.CanAddr() {
return "", false
} else if !ok {
return marshalValue(v.Addr())
}
bs, err := tm.MarshalText()
if err != nil {
panic(err)
}
return string(bs), true
}

11
vendor/github.com/ajg/form/form.go generated vendored Normal file
View File

@ -0,0 +1,11 @@
// Copyright 2014 Alvaro J. Genial. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package form implements encoding and decoding of application/x-www-form-urlencoded data.
package form
const (
implicitKey = "_"
omittedKey = "-"
)

148
vendor/github.com/ajg/form/node.go generated vendored Normal file
View File

@ -0,0 +1,148 @@
// Copyright 2014 Alvaro J. Genial. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package form
import (
"net/url"
"strconv"
"strings"
)
type node map[string]interface{}
func (n node) Values() url.Values {
vs := url.Values{}
n.merge("", &vs)
return vs
}
func (n node) merge(p string, vs *url.Values) {
for k, x := range n {
switch y := x.(type) {
case string:
vs.Add(p+escape(k), y)
case node:
y.merge(p+escape(k)+".", vs)
default:
panic("value is neither string nor node")
}
}
}
// TODO: Add tests for implicit indexing.
func parseValues(vs url.Values, canIndexFirstLevelOrdinally bool) node {
// NOTE: Because of the flattening of potentially multiple strings to one key, implicit indexing works:
// i. At the first level; e.g. Foo.Bar=A&Foo.Bar=B becomes 0.Foo.Bar=A&1.Foo.Bar=B
// ii. At the last level; e.g. Foo.Bar._=A&Foo.Bar._=B becomes Foo.Bar.0=A&Foo.Bar.1=B
// TODO: At in-between levels; e.g. Foo._.Bar=A&Foo._.Bar=B becomes Foo.0.Bar=A&Foo.1.Bar=B
// (This last one requires that there only be one placeholder in order for it to be unambiguous.)
m := map[string]string{}
for k, ss := range vs {
indexLastLevelOrdinally := strings.HasSuffix(k, "."+implicitKey)
for i, s := range ss {
if canIndexFirstLevelOrdinally {
k = strconv.Itoa(i) + "." + k
} else if indexLastLevelOrdinally {
k = strings.TrimSuffix(k, implicitKey) + strconv.Itoa(i)
}
m[k] = s
}
}
n := node{}
for k, s := range m {
n = n.split(k, s)
}
return n
}
func splitPath(path string) (k, rest string) {
esc := false
for i, r := range path {
switch {
case !esc && r == '\\':
esc = true
case !esc && r == '.':
return unescape(path[:i]), path[i+1:]
default:
esc = false
}
}
return unescape(path), ""
}
func (n node) split(path, s string) node {
k, rest := splitPath(path)
if rest == "" {
return add(n, k, s)
}
if _, ok := n[k]; !ok {
n[k] = node{}
}
c := getNode(n[k])
n[k] = c.split(rest, s)
return n
}
func add(n node, k, s string) node {
if n == nil {
return node{k: s}
}
if _, ok := n[k]; ok {
panic("key " + k + " already set")
}
n[k] = s
return n
}
func isEmpty(x interface{}) bool {
switch y := x.(type) {
case string:
return y == ""
case node:
if s, ok := y[""].(string); ok {
return s == ""
}
return false
}
panic("value is neither string nor node")
}
func getNode(x interface{}) node {
switch y := x.(type) {
case string:
return node{"": y}
case node:
return y
}
panic("value is neither string nor node")
}
func getString(x interface{}) string {
switch y := x.(type) {
case string:
return y
case node:
if s, ok := y[""].(string); ok {
return s
}
return ""
}
panic("value is neither string nor node")
}
func escape(s string) string {
return strings.Replace(strings.Replace(s, `\`, `\\`, -1), `.`, `\.`, -1)
}
func unescape(s string) string {
return strings.Replace(strings.Replace(s, `\.`, `.`, -1), `\\`, `\`, -1)
}

18
vendor/github.com/ajg/form/pre-commit.sh generated vendored Normal file
View File

@ -0,0 +1,18 @@
#!/bin/bash -eu
# TODO: Only colorize messages given a suitable terminal.
# FIXME: Handle case in which no stash entry is created due to no changes.
printf "\e[30m=== PRE-COMMIT STARTING ===\e[m\n"
git stash save --quiet --keep-index --include-untracked
if go build -v ./... && go test -v -cover ./... && go vet ./... && golint . && travis-lint; then
result=$?
printf "\e[32m=== PRE-COMMIT SUCCEEDED ===\e[m\n"
else
result=$?
printf "\e[31m=== PRE-COMMIT FAILED ===\e[m\n"
fi
git stash pop --quiet
exit $result

28
vendor/github.com/sethvargo/go-fastly/.gitignore generated vendored Normal file
View File

@ -0,0 +1,28 @@
### Go ###
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
bin/
pkg/

19
vendor/github.com/sethvargo/go-fastly/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,19 @@
sudo: false
language: go
go:
- 1.4.2
- 1.5.2
branches:
only:
- master
script:
- make updatedeps
- make test
env:
# FASTLY_API_KEY
- secure: "eiYcogJFF+lK/6coFXaOOm0bDHxaK1qqZ0GinMmPXmQ6nonf56omMVxNyOsV+6jz/fdJCA7gfGv600raTAOVNxD23E/p2j6yxPSI5O6itxp0jxJm7p6MOHwkmsXFZGfLxaqVN2CHs+W3sSc4cwzCkCqlik4XLXihHvzYpjBk1AZK6QUMWqdTcDYDWMfk5CW1O6wUpmYiFwlnENwDopGQlSs1+PyEiDEbEMYu1yVUq+f83IJ176arM4XL8NS2GN1QMBKyALA+6jpT/OrFtW5tkheE+WOQ6+/ZnDCtY0i1RA8BBuyACYuf+WEAkmWfJGGk7+Ou6q2JFzIBsd6ZS3EsM4bs4P1FyhPBwK5zyFty2w7+PwVm6wrZ0NfUh6BKsfCF9MweypsKq+F+4GOcpjdCYPKZKGRjQ4iKOZVVzaVGLRanz1EHiXUcLT+DDr0kFbvrLCLqCPvujBfqeUDqVZMpsUqir9HWqVKutczAnYzFaoeeSVap14J/sd6kcgZo2bNMSRQvMoPCOvicdW8RLIV8Hyx2l0Cv596ZfinWBk2Dcmn6APLkbrBpvhv6/SUtBKHMijjFc5VvoxO3ZP6vUCueDaZVNWkX1xk+VA5PD0T/IcilLy3+nBedz+3lmiW7dnQPuWnlPBFPWvYZvW2KaDOazv5rZK+pKIq32BIyhP/n/AU="

201
vendor/github.com/sethvargo/go-fastly/LICENSE generated vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015 Seth Vargo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

21
vendor/github.com/sethvargo/go-fastly/Makefile generated vendored Normal file
View File

@ -0,0 +1,21 @@
TEST?=./...
default: test
# test runs the test suite and vets the code
test: generate
go list $(TEST) | xargs -n1 go test -timeout=30s -parallel=8 $(TESTARGS)
# updatedeps installs all the dependencies the library needs to run and build
updatedeps:
go list ./... \
| xargs go list -f '{{ join .Deps "\n" }}{{ printf "\n" }}{{ join .TestImports "\n" }}' \
| grep -v github.com/sethvargo/go-fastly \
| xargs go get -f -u -v
# generate runs `go generate` to build the dynamically generated source files
generate:
find . -type f -name '.DS_Store' -delete
go generate ./...
.PHONY: default bin dev dist test testrace updatedeps generate

128
vendor/github.com/sethvargo/go-fastly/README.md generated vendored Normal file
View File

@ -0,0 +1,128 @@
Go Fastly
=========
[![Build Status](http://img.shields.io/travis/sethvargo/go-fastly.svg?style=flat-square)][travis]
[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs]
[travis]: http://travis-ci.org/sethvargo/go-fastly
[godocs]: http://godoc.org/github.com/sethvargo/go-fastly
Go Fastly is a Golang API client for interacting with most facets of the
[Fastly API](https://docs.fastly.com/api).
Installation
------------
This is a client library, so there is nothing to install.
Usage
-----
Download the library into your `$GOPATH`:
$ go get github.com/sethvargo/go-fastly
Import the library into your tool:
```go
import "github.com/sethvargo/go-fastly"
```
Examples
--------
Fastly's API is designed to work in the following manner:
1. Create (or clone) a new configuration version for the service
2. Make any changes to the version
3. Validate the version
4. Activate the version
This flow using the Golang client looks like this:
```go
// Create a client object. The client has no state, so it can be persisted
// and re-used. It is also safe to use concurrently due to its lack of state.
// There is also a DefaultClient() method that reads an environment variable.
// Please see the documentation for more information and details.
client, err := fastly.NewClient("YOUR_FASTLY_API_KEY")
if err != nil {
log.Fatal(err)
}
// You can find the service ID in the Fastly web console.
var serviceID = "SU1Z0isxPaozGVKXdv0eY"
// Get the latest active version
latest, err := client.LatestVersion(&fastly.LatestVersionInput{
Service: serviceID,
})
if err != nil {
log.Fatal(err)
}
// Clone the latest version so we can make changes without affecting the
// active configuration.
version, err := client.CloneVersion(&fastly.CloneVersionInput{
Service: serviceID,
Version: latest.Number,
})
if err != nil {
log.Fatal(err)
}
// Now you can make any changes to the new version. In this example, we will add
// a new domain.
domain, err := client.CreateDomain(&fastly.CreateDomainInput{
Service: serviceID,
Version: version.Number,
Name: "example.com",
})
if err != nil {
log.Fatal(err)
}
// Output: "example.com"
fmt.Println(domain.Name)
// Now we can validate that our version is valid.
valid, err := client.ValidateVersion(&fastly.ValidateVersionInput{
Service: serviceID,
Version: version.Number,
})
if err != nil {
log.Fatal(err)
}
if !valid {
log.Fatal("not valid version")
}
// Finally, activate this new version.
activeVersion, err := client.ActivateVersion(&fastly.ActivateVersionInput{
Service: serviceID,
Version: version.Number,
})
if err != nil {
log.Fatal(err)
}
// Output: true
fmt.Printf("%b", activeVersion.Locked)
```
More information can be found in the
[Fastly Godoc](https://godoc.org/github.com/sethvargo/go-fastly).
License
-------
```
Copyright 2015 Seth Vargo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

266
vendor/github.com/sethvargo/go-fastly/backend.go generated vendored Normal file
View File

@ -0,0 +1,266 @@
package fastly
import (
"fmt"
"sort"
)
// Backend represents a backend response from the Fastly API.
type Backend struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
Port uint `mapstructure:"port"`
ConnectTimeout uint `mapstructure:"connect_timeout"`
MaxConn uint `mapstructure:"max_conn"`
ErrorThreshold uint `mapstructure:"error_threshold"`
FirstByteTimeout uint `mapstructure:"first_byte_timeout"`
BetweenBytesTimeout uint `mapstructure:"between_bytes_timeout"`
AutoLoadbalance bool `mapstructure:"auto_loadbalance"`
Weight uint `mapstructure:"weight"`
RequestCondition string `mapstructure:"request_condition"`
HealthCheck string `mapstructure:"healthcheck"`
UseSSL bool `mapstructure:"use_ssl"`
SSLCheckCert bool `mapstructure:"ssl_check_cert"`
SSLHostname string `mapstructure:"ssl_hostname"`
SSLCertHostname string `mapstructure:"ssl_cert_hostname"`
SSLSNIHostname string `mapstructure:"ssl_sni_hostname"`
MinTLSVersion string `mapstructure:"min_tls_version"`
MaxTLSVersion string `mapstructure:"max_tls_version"`
SSLCiphers []string `mapstructure:"ssl_ciphers"`
}
// backendsByName is a sortable list of backends.
type backendsByName []*Backend
// Len, Swap, and Less implement the sortable interface.
func (s backendsByName) Len() int { return len(s) }
func (s backendsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s backendsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListBackendsInput is used as input to the ListBackends function.
type ListBackendsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListBackends returns the list of backends for the configuration version.
func (c *Client) ListBackends(i *ListBackendsInput) ([]*Backend, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/backend", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*Backend
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(backendsByName(bs))
return bs, nil
}
// CreateBackendInput is used as input to the CreateBackend function.
type CreateBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
ConnectTimeout uint `form:"connect_timeout,omitempty"`
MaxConn uint `form:"max_conn,omitempty"`
ErrorThreshold uint `form:"error_threshold,omitempty"`
FirstByteTimeout uint `form:"first_byte_timeout,omitempty"`
BetweenBytesTimeout uint `form:"between_bytes_timeout,omitempty"`
AutoLoadbalance bool `form:"auto_loadbalance,omitempty"`
Weight uint `form:"weight,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
HealthCheck string `form:"healthcheck,omitempty"`
UseSSL bool `form:"use_ssl,omitempty"`
SSLCheckCert bool `form:"ssl_check_cert,omitempty"`
SSLHostname string `form:"ssl_hostname,omitempty"`
SSLCertHostname string `form:"ssl_cert_hostname,omitempty"`
SSLSNIHostname string `form:"ssl_sni_hostname,omitempty"`
MinTLSVersion string `form:"min_tls_version,omitempty"`
MaxTLSVersion string `form:"max_tls_version,omitempty"`
SSLCiphers []string `form:"ssl_ciphers,omitempty"`
}
// CreateBackend creates a new Fastly backend.
func (c *Client) CreateBackend(i *CreateBackendInput) (*Backend, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/backend", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Backend
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetBackendInput is used as input to the GetBackend function.
type GetBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the backend to fetch.
Name string
}
// GetBackend gets the backend configuration with the given parameters.
func (c *Client) GetBackend(i *GetBackendInput) (*Backend, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/backend/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *Backend
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateBackendInput is used as input to the UpdateBackend function.
type UpdateBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the backend to update.
Name string
NewName string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
ConnectTimeout uint `form:"connect_timeout,omitempty"`
MaxConn uint `form:"max_conn,omitempty"`
ErrorThreshold uint `form:"error_threshold,omitempty"`
FirstByteTimeout uint `form:"first_byte_timeout,omitempty"`
BetweenBytesTimeout uint `form:"between_bytes_timeout,omitempty"`
AutoLoadbalance bool `form:"auto_loadbalance,omitempty"`
Weight uint `form:"weight,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
HealthCheck string `form:"healthcheck,omitempty"`
UseSSL bool `form:"use_ssl,omitempty"`
SSLCheckCert bool `form:"ssl_check_cert,omitempty"`
SSLHostname string `form:"ssl_hostname,omitempty"`
SSLCertHostname string `form:"ssl_cert_hostname,omitempty"`
SSLSNIHostname string `form:"ssl_sni_hostname,omitempty"`
MinTLSVersion string `form:"min_tls_version,omitempty"`
MaxTLSVersion string `form:"max_tls_version,omitempty"`
SSLCiphers []string `form:"ssl_ciphers,omitempty"`
}
// UpdateBackend updates a specific backend.
func (c *Client) UpdateBackend(i *UpdateBackendInput) (*Backend, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/backend/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Backend
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteBackendInput is the input parameter to DeleteBackend.
type DeleteBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the backend to delete (required).
Name string
}
// DeleteBackend deletes the given backend version.
func (c *Client) DeleteBackend(i *DeleteBackendInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/backend/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

81
vendor/github.com/sethvargo/go-fastly/billing.go generated vendored Normal file
View File

@ -0,0 +1,81 @@
package fastly
import (
"fmt"
"time"
)
// Billing is the top-level representation of a billing response from the Fastly
// API.
type Billing struct {
InvoiceID string `mapstructure:"invoice_id"`
StartTime *time.Time `mapstructure:"start_time"`
EndTime *time.Time `mapstructure:"end_time"`
Status *BillingStatus `mapstructure:"status"`
Total *BillingTotal `mapstructure:"total"`
}
// BillingStatus is a representation of the status of the bill from the Fastly
// API.
type BillingStatus struct {
InvoiceID string `mapstructure:"invoice_id"`
Status string `mapstructure:"status"`
SentAt *time.Time `mapstructure:"sent_at"`
}
// BillingTotal is a repsentation of the status of the usage for this bill from
// the Fastly API.
type BillingTotal struct {
PlanName string `mapstructure:"plan_name"`
PlanCode string `mapstructure:"plan_code"`
PlanMinimum string `mapstructure:"plan_minimum"`
Bandwidth float64 `mapstructure:"bandwidth"`
BandwidthCost float64 `mapstructure:"bandwidth_cost"`
Requests uint64 `mapstructure:"requests"`
RequestsCost float64 `mapstructure:"requests_cost"`
IncurredCost float64 `mapstructure:"incurred_cost"`
Overage float64 `mapstructure:"overage"`
Extras []*BillingExtra `mapstructure:"extras"`
ExtrasCost float64 `mapstructure:"extras_cost"`
CostBeforeDiscount float64 `mapstructure:"cost_before_discount"`
Discount float64 `mapstructure:"discount"`
Cost float64 `mapstructure:"cost"`
Terms string `mapstructure:"terms"`
}
// BillingExtra is a representation of extras (such as SSL addons) from the
// Fastly API.
type BillingExtra struct {
Name string `mapstructure:"name"`
Setup float64 `mapstructure:"setup"`
Recurring float64 `mapstructure:"recurring"`
}
// GetBillingInput is used as input to the GetBilling function.
type GetBillingInput struct {
Year uint16
Month uint8
}
// GetBilling returns the billing information for the current account.
func (c *Client) GetBilling(i *GetBillingInput) (*Billing, error) {
if i.Year == 0 {
return nil, ErrMissingYear
}
if i.Month == 0 {
return nil, ErrMissingMonth
}
path := fmt.Sprintf("/billing/year/%d/month/%02d", i.Year, i.Month)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *Billing
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}

237
vendor/github.com/sethvargo/go-fastly/cache_setting.go generated vendored Normal file
View File

@ -0,0 +1,237 @@
package fastly
import (
"fmt"
"sort"
)
const (
// CacheSettingActionCache sets the cache to cache.
CacheSettingActionCache CacheSettingAction = "cache"
// CacheSettingActionPass sets the cache to pass through.
CacheSettingActionPass CacheSettingAction = "pass"
// CacheSettingActionRestart sets the cache to restart the request.
CacheSettingActionRestart CacheSettingAction = "restart"
)
// CacheSettingAction is the type of cache action.
type CacheSettingAction string
// CacheSetting represents a response from Fastly's API for cache settings.
type CacheSetting struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Action CacheSettingAction `mapstructure:"action"`
TTL uint `mapstructure:"ttl"`
StaleTTL uint `mapstructure:"stale_ttl"`
CacheCondition string `mapstructure:"cache_condition"`
}
// cacheSettingsByName is a sortable list of cache settings.
type cacheSettingsByName []*CacheSetting
// Len, Swap, and Less implement the sortable interface.
func (s cacheSettingsByName) Len() int { return len(s) }
func (s cacheSettingsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s cacheSettingsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListCacheSettingsInput is used as input to the ListCacheSettings function.
type ListCacheSettingsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListCacheSettings returns the list of cache settings for the configuration
// version.
func (c *Client) ListCacheSettings(i *ListCacheSettingsInput) ([]*CacheSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/cache_settings", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var cs []*CacheSetting
if err := decodeJSON(&cs, resp.Body); err != nil {
return nil, err
}
sort.Stable(cacheSettingsByName(cs))
return cs, nil
}
// CreateCacheSettingInput is used as input to the CreateCacheSetting function.
type CreateCacheSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Action CacheSettingAction `form:"action,omitempty"`
TTL uint `form:"ttl,omitempty"`
StaleTTL uint `form:"stale_ttl,omitempty"`
CacheCondition string `form:"cache_condition,omitempty"`
}
// CreateCacheSetting creates a new Fastly cache setting.
func (c *Client) CreateCacheSetting(i *CreateCacheSettingInput) (*CacheSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/cache_settings", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var cs *CacheSetting
if err := decodeJSON(&cs, resp.Body); err != nil {
return nil, err
}
return cs, nil
}
// GetCacheSettingInput is used as input to the GetCacheSetting function.
type GetCacheSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the cache setting to fetch.
Name string
}
// GetCacheSetting gets the cache setting configuration with the given
// parameters.
func (c *Client) GetCacheSetting(i *GetCacheSettingInput) (*CacheSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/cache_settings/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var cs *CacheSetting
if err := decodeJSON(&cs, resp.Body); err != nil {
return nil, err
}
return cs, nil
}
// UpdateCacheSettingInput is used as input to the UpdateCacheSetting function.
type UpdateCacheSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the cache setting to update.
Name string
NewName string `form:"name,omitempty"`
Action CacheSettingAction `form:"action,omitempty"`
TTL uint `form:"ttl,omitempty"`
StateTTL uint `form:"stale_ttl,omitempty"`
CacheCondition string `form:"cache_condition,omitempty"`
}
// UpdateCacheSetting updates a specific cache setting.
func (c *Client) UpdateCacheSetting(i *UpdateCacheSettingInput) (*CacheSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/cache_settings/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var cs *CacheSetting
if err := decodeJSON(&cs, resp.Body); err != nil {
return nil, err
}
return cs, nil
}
// DeleteCacheSettingInput is the input parameter to DeleteCacheSetting.
type DeleteCacheSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the cache setting to delete (required).
Name string
}
// DeleteCacheSetting deletes the given cache setting version.
func (c *Client) DeleteCacheSetting(i *DeleteCacheSettingInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/cache_settings/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

212
vendor/github.com/sethvargo/go-fastly/client.go generated vendored Normal file
View File

@ -0,0 +1,212 @@
package fastly
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"runtime"
"strings"
"github.com/ajg/form"
"github.com/hashicorp/go-cleanhttp"
"github.com/mitchellh/mapstructure"
)
// APIKeyEnvVar is the name of the environment variable where the Fastly API
// key should be read from.
const APIKeyEnvVar = "FASTLY_API_KEY"
// APIKeyHeader is the name of the header that contains the Fastly API key.
const APIKeyHeader = "Fastly-Key"
// DefaultEndpoint is the default endpoint for Fastly. Since Fastly does not
// support an on-premise solution, this is likely to always be the default.
const DefaultEndpoint = "https://api.fastly.com"
// ProjectURL is the url for this library.
var ProjectURL = "github.com/sethvargo/go-fastly"
// ProjectVersion is the version of this library.
var ProjectVersion = "0.1"
// UserAgent is the user agent for this particular client.
var UserAgent = fmt.Sprintf("FastlyGo/%s (+%s; %s)",
ProjectVersion, ProjectURL, runtime.Version())
// Client is the main entrypoint to the Fastly golang API library.
type Client struct {
// Address is the address of Fastly's API endpoint.
Address string
// HTTPClient is the HTTP client to use. If one is not provided, a default
// client will be used.
HTTPClient *http.Client
// apiKey is the Fastly API key to authenticate requests.
apiKey string
// url is the parsed URL from Address
url *url.URL
}
// DefaultClient instantiates a new Fastly API client. This function requires
// the environment variable `FASTLY_API_KEY` is set and contains a valid API key
// to authenticate with Fastly.
func DefaultClient() *Client {
client, err := NewClient(os.Getenv(APIKeyEnvVar))
if err != nil {
panic(err)
}
return client
}
// NewClient creates a new API client with the given key. Because Fastly allows
// some requests without an API key, this function will not error if the API
// token is not supplied. Attempts to make a request that requires an API key
// will return a 403 response.
func NewClient(key string) (*Client, error) {
client := &Client{apiKey: key}
return client.init()
}
func (c *Client) init() (*Client, error) {
if len(c.Address) == 0 {
c.Address = DefaultEndpoint
}
u, err := url.Parse(c.Address)
if err != nil {
return nil, err
}
c.url = u
if c.HTTPClient == nil {
c.HTTPClient = cleanhttp.DefaultClient()
}
return c, nil
}
// Get issues an HTTP GET request.
func (c *Client) Get(p string, ro *RequestOptions) (*http.Response, error) {
return c.Request("GET", p, ro)
}
// Head issues an HTTP HEAD request.
func (c *Client) Head(p string, ro *RequestOptions) (*http.Response, error) {
return c.Request("HEAD", p, ro)
}
// Post issues an HTTP POST request.
func (c *Client) Post(p string, ro *RequestOptions) (*http.Response, error) {
return c.Request("POST", p, ro)
}
// PostForm issues an HTTP POST request with the given interface form-encoded.
func (c *Client) PostForm(p string, i interface{}, ro *RequestOptions) (*http.Response, error) {
return c.RequestForm("POST", p, i, ro)
}
// Put issues an HTTP PUT request.
func (c *Client) Put(p string, ro *RequestOptions) (*http.Response, error) {
return c.Request("PUT", p, ro)
}
// PutForm issues an HTTP PUT request with the given interface form-encoded.
func (c *Client) PutForm(p string, i interface{}, ro *RequestOptions) (*http.Response, error) {
return c.RequestForm("PUT", p, i, ro)
}
// Delete issues an HTTP DELETE request.
func (c *Client) Delete(p string, ro *RequestOptions) (*http.Response, error) {
return c.Request("DELETE", p, ro)
}
// Request makes an HTTP request against the HTTPClient using the given verb,
// Path, and request options.
func (c *Client) Request(verb, p string, ro *RequestOptions) (*http.Response, error) {
req, err := c.RawRequest(verb, p, ro)
if err != nil {
return nil, err
}
resp, err := checkResp(c.HTTPClient.Do(req))
if err != nil {
return resp, err
}
return resp, nil
}
// RequestForm makes an HTTP request with the given interface being encoded as
// form data.
func (c *Client) RequestForm(verb, p string, i interface{}, ro *RequestOptions) (*http.Response, error) {
values, err := form.EncodeToValues(i)
if err != nil {
return nil, err
}
if ro == nil {
ro = new(RequestOptions)
}
if ro.Headers == nil {
ro.Headers = make(map[string]string)
}
ro.Headers["Content-Type"] = "application/x-www-form-urlencoded"
// There is a super-jank implementation in the form library where fields with
// a "dot" are replaced with "/.". That is then URL encoded and Fastly just
// dies. We fix that here.
body := strings.Replace(values.Encode(), "%5C.", ".", -1)
ro.Body = strings.NewReader(body)
ro.BodyLength = int64(len(body))
return c.Request(verb, p, ro)
}
// checkResp wraps an HTTP request from the default client and verifies that the
// request was successful. A non-200 request returns an error formatted to
// included any validation problems or otherwise.
func checkResp(resp *http.Response, err error) (*http.Response, error) {
// If the err is already there, there was an error higher up the chain, so
// just return that.
if err != nil {
return resp, err
}
switch resp.StatusCode {
case 200, 201, 202, 204, 205, 206:
return resp, nil
default:
return resp, NewHTTPError(resp)
}
}
// decodeJSON is used to decode an HTTP response body into an interface as JSON.
func decodeJSON(out interface{}, body io.ReadCloser) error {
defer body.Close()
var parsed interface{}
dec := json.NewDecoder(body)
if err := dec.Decode(&parsed); err != nil {
return err
}
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
DecodeHook: mapstructure.ComposeDecodeHookFunc(
mapToHTTPHeaderHookFunc(),
stringToTimeHookFunc(),
),
WeaklyTypedInput: true,
Result: out,
})
if err != nil {
return err
}
return decoder.Decode(parsed)
}

217
vendor/github.com/sethvargo/go-fastly/condition.go generated vendored Normal file
View File

@ -0,0 +1,217 @@
package fastly
import (
"fmt"
"sort"
)
// Condition represents a condition response from the Fastly API.
type Condition struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Statement string `mapstructure:"statement"`
Type string `mapstructure:"type"`
Priority int `mapstructure:"priority"`
}
// conditionsByName is a sortable list of conditions.
type conditionsByName []*Condition
// Len, Swap, and Less implement the sortable interface.
func (s conditionsByName) Len() int { return len(s) }
func (s conditionsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s conditionsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListConditionsInput is used as input to the ListConditions function.
type ListConditionsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListConditions returns the list of conditions for the configuration version.
func (c *Client) ListConditions(i *ListConditionsInput) ([]*Condition, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/condition", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var cs []*Condition
if err := decodeJSON(&cs, resp.Body); err != nil {
return nil, err
}
sort.Stable(conditionsByName(cs))
return cs, nil
}
// CreateConditionInput is used as input to the CreateCondition function.
type CreateConditionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Statement string `form:"statement,omitempty"`
Type string `form:"type,omitempty"`
Priority int `form:"priority,omitempty"`
}
// CreateCondition creates a new Fastly condition.
func (c *Client) CreateCondition(i *CreateConditionInput) (*Condition, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/condition", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var co *Condition
if err := decodeJSON(&co, resp.Body); err != nil {
return nil, err
}
return co, nil
}
// GetConditionInput is used as input to the GetCondition function.
type GetConditionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the condition to fetch.
Name string
}
// GetCondition gets the condition configuration with the given parameters.
func (c *Client) GetCondition(i *GetConditionInput) (*Condition, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/condition/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var co *Condition
if err := decodeJSON(&co, resp.Body); err != nil {
return nil, err
}
return co, nil
}
// UpdateConditionInput is used as input to the UpdateCondition function.
type UpdateConditionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the condition to update.
Name string
Statement string `form:"statement,omitempty"`
Type string `form:"type,omitempty"`
Priority int `form:"priority,omitempty"`
}
// UpdateCondition updates a specific condition.
func (c *Client) UpdateCondition(i *UpdateConditionInput) (*Condition, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/condition/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var co *Condition
if err := decodeJSON(&co, resp.Body); err != nil {
return nil, err
}
return co, nil
}
// DeleteConditionInput is the input parameter to DeleteCondition.
type DeleteConditionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the condition to delete (required).
Name string
}
// DeleteCondition deletes the given condition version.
func (c *Client) DeleteCondition(i *DeleteConditionInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/condition/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

49
vendor/github.com/sethvargo/go-fastly/content.go generated vendored Normal file
View File

@ -0,0 +1,49 @@
package fastly
import "net/http"
// EdgeCheck represents an edge check response from the Fastly API.
type EdgeCheck struct {
Hash string `mapstructure:"hash"`
Server string `mapstructure:"server"`
ResponseTime float64 `mapstructure:"response_time"`
Request *EdgeCheckRequest `mapstructure:"request"`
Response *EdgeCheckResponse `mapstructure:"response"`
}
// EdgeCheckRequest is the request part of an EdgeCheck response.
type EdgeCheckRequest struct {
URL string `mapstructure:"url"`
Method string `mapstructure:"method"`
Headers *http.Header `mapstructure:"headers"`
}
// EdgeCheckResponse is the response part of an EdgeCheck response.
type EdgeCheckResponse struct {
Status uint `mapstructure:"status"`
Headers *http.Header `mapstructure:"headers"`
}
// EdgeCheckInput is used as input to the EdgeCheck function.
type EdgeCheckInput struct {
URL string `form:"url,omitempty"`
}
// EdgeCheck queries the edge cache for all of Fastly's servers for the given
// URL.
func (c *Client) EdgeCheck(i *EdgeCheckInput) ([]*EdgeCheck, error) {
resp, err := c.Get("/content/edge_check", &RequestOptions{
Params: map[string]string{
"url": i.URL,
},
})
if err != nil {
return nil, err
}
var e []*EdgeCheck
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}

64
vendor/github.com/sethvargo/go-fastly/decode_hooks.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package fastly
import (
"fmt"
"net/http"
"reflect"
"time"
"github.com/mitchellh/mapstructure"
)
// mapToHTTPHeaderHookFunc returns a function that converts maps into an
// http.Header value.
func mapToHTTPHeaderHookFunc() mapstructure.DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{}) (interface{}, error) {
if f.Kind() != reflect.Map {
return data, nil
}
if t != reflect.TypeOf(new(http.Header)) {
return data, nil
}
typed, ok := data.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("cannot convert %T to http.Header", data)
}
n := map[string][]string{}
for k, v := range typed {
switch v.(type) {
case string:
n[k] = []string{v.(string)}
case []string:
n[k] = v.([]string)
default:
return nil, fmt.Errorf("cannot convert %T to http.Header", v)
}
}
return n, nil
}
}
// stringToTimeHookFunc returns a function that converts strings to a time.Time
// value.
func stringToTimeHookFunc() mapstructure.DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{}) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}
if t != reflect.TypeOf(time.Now()) {
return data, nil
}
// Convert it by parsing
return time.Parse(time.RFC3339, data.(string))
}
}

206
vendor/github.com/sethvargo/go-fastly/dictionary.go generated vendored Normal file
View File

@ -0,0 +1,206 @@
package fastly
import (
"fmt"
"sort"
)
// Dictionary represents a dictionary response from the Fastly API.
type Dictionary struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
ID string `mapstructure:"id"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
}
// dictionariesByName is a sortable list of dictionaries.
type dictionariesByName []*Dictionary
// Len, Swap, and Less implement the sortable interface.
func (s dictionariesByName) Len() int { return len(s) }
func (s dictionariesByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s dictionariesByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListDictionariesInput is used as input to the ListDictionaries function.
type ListDictionariesInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListDictionaries returns the list of dictionaries for the configuration version.
func (c *Client) ListDictionaries(i *ListDictionariesInput) ([]*Dictionary, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/dictionary", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*Dictionary
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(dictionariesByName(bs))
return bs, nil
}
// CreateDictionaryInput is used as input to the CreateDictionary function.
type CreateDictionaryInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
}
// CreateDictionary creates a new Fastly dictionary.
func (c *Client) CreateDictionary(i *CreateDictionaryInput) (*Dictionary, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/dictionary", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Dictionary
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetDictionaryInput is used as input to the GetDictionary function.
type GetDictionaryInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the dictionary to fetch.
Name string
}
// GetDictionary gets the dictionary configuration with the given parameters.
func (c *Client) GetDictionary(i *GetDictionaryInput) (*Dictionary, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/dictionary/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *Dictionary
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateDictionaryInput is used as input to the UpdateDictionary function.
type UpdateDictionaryInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the dictionary to update.
Name string
NewName string `form:"name,omitempty"`
}
// UpdateDictionary updates a specific dictionary.
func (c *Client) UpdateDictionary(i *UpdateDictionaryInput) (*Dictionary, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/dictionary/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Dictionary
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteDictionaryInput is the input parameter to DeleteDictionary.
type DeleteDictionaryInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the dictionary to delete (required).
Name string
}
// DeleteDictionary deletes the given dictionary version.
func (c *Client) DeleteDictionary(i *DeleteDictionaryInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/dictionary/%s", i.Service, i.Version, i.Name)
_, err := c.Delete(path, nil)
if err != nil {
return err
}
// Unlike other endpoints, the dictionary endpoint does not return a status
// response - it just returns a 200 OK.
return nil
}

View File

@ -0,0 +1,207 @@
package fastly
import (
"fmt"
"sort"
)
// DictionaryItem represents a dictionary item response from the Fastly API.
type DictionaryItem struct {
ServiceID string `mapstructure:"service_id"`
DictionaryID string `mapstructure:"dictionary_id"`
ItemKey string `mapstructure:"item_key"`
ItemValue string `mapstructure:"item_value"`
}
// dictionaryItemsByKey is a sortable list of dictionary items.
type dictionaryItemsByKey []*DictionaryItem
// Len, Swap, and Less implement the sortable interface.
func (s dictionaryItemsByKey) Len() int { return len(s) }
func (s dictionaryItemsByKey) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s dictionaryItemsByKey) Less(i, j int) bool {
return s[i].ItemKey < s[j].ItemKey
}
// ListDictionaryItemsInput is used as input to the ListDictionaryItems function.
type ListDictionaryItemsInput struct {
// Service is the ID of the service (required).
Service string
// Dictionary is the ID of the dictionary to retrieve items for (required).
Dictionary string
}
// ListDictionaryItems returns the list of dictionary items for the
// configuration version.
func (c *Client) ListDictionaryItems(i *ListDictionaryItemsInput) ([]*DictionaryItem, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Dictionary == "" {
return nil, ErrMissingDictionary
}
path := fmt.Sprintf("/service/%s/dictionary/%s/items", i.Service, i.Dictionary)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*DictionaryItem
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(dictionaryItemsByKey(bs))
return bs, nil
}
// CreateDictionaryItemInput is used as input to the CreateDictionaryItem function.
type CreateDictionaryItemInput struct {
// Service is the ID of the service. Dictionary is the ID of the dictionary.
// Both fields are required.
Service string
Dictionary string
ItemKey string `form:"item_key,omitempty"`
ItemValue string `form:"item_value,omitempty"`
}
// CreateDictionaryItem creates a new Fastly dictionary item.
func (c *Client) CreateDictionaryItem(i *CreateDictionaryItemInput) (*DictionaryItem, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Dictionary == "" {
return nil, ErrMissingDictionary
}
path := fmt.Sprintf("/service/%s/dictionary/%s/item", i.Service, i.Dictionary)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *DictionaryItem
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetDictionaryItemInput is used as input to the GetDictionaryItem function.
type GetDictionaryItemInput struct {
// Service is the ID of the service. Dictionary is the ID of the dictionary.
// Both fields are required.
Service string
Dictionary string
// ItemKey is the name of the dictionary item to fetch.
ItemKey string
}
// GetDictionaryItem gets the dictionary item with the given parameters.
func (c *Client) GetDictionaryItem(i *GetDictionaryItemInput) (*DictionaryItem, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Dictionary == "" {
return nil, ErrMissingDictionary
}
if i.ItemKey == "" {
return nil, ErrMissingItemKey
}
path := fmt.Sprintf("/service/%s/dictionary/%s/item/%s", i.Service, i.Dictionary, i.ItemKey)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *DictionaryItem
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateDictionaryItemInput is used as input to the UpdateDictionaryItem function.
type UpdateDictionaryItemInput struct {
// Service is the ID of the service. Dictionary is the ID of the dictionary.
// Both fields are required.
Service string
Dictionary string
// ItemKey is the name of the dictionary item to fetch.
ItemKey string
ItemValue string `form:"item_value,omitempty"`
}
// UpdateDictionaryItem updates a specific dictionary item.
func (c *Client) UpdateDictionaryItem(i *UpdateDictionaryItemInput) (*DictionaryItem, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Dictionary == "" {
return nil, ErrMissingDictionary
}
if i.ItemKey == "" {
return nil, ErrMissingItemKey
}
path := fmt.Sprintf("/service/%s/dictionary/%s/item/%s", i.Service, i.Dictionary, i.ItemKey)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *DictionaryItem
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteDictionaryItemInput is the input parameter to DeleteDictionaryItem.
type DeleteDictionaryItemInput struct {
// Service is the ID of the service. Dictionary is the ID of the dictionary.
// Both fields are required.
Service string
Dictionary string
// ItemKey is the name of the dictionary item to delete.
ItemKey string
}
// DeleteDictionaryItem deletes the given dictionary item.
func (c *Client) DeleteDictionaryItem(i *DeleteDictionaryItemInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Dictionary == "" {
return ErrMissingDictionary
}
if i.ItemKey == "" {
return ErrMissingItemKey
}
path := fmt.Sprintf("/service/%s/dictionary/%s/item/%s", i.Service, i.Dictionary, i.ItemKey)
_, err := c.Delete(path, nil)
if err != nil {
return err
}
// Unlike other endpoints, the dictionary endpoint does not return a status
// response - it just returns a 200 OK.
return nil
}

57
vendor/github.com/sethvargo/go-fastly/diff.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
package fastly
import "fmt"
// Diff represents a diff of two versions as a response from the Fastly API.
type Diff struct {
Format string `mapstructure:"format"`
From string `mapstructure:"from"`
To string `mapstructure:"to"`
Diff string `mapstructure:"diff"`
}
// GetDiffInput is used as input to the GetDiff function.
type GetDiffInput struct {
// Service is the ID of the service (required).
Service string
// From is the version to diff from. This can either be a string indicating a
// positive number (e.g. "1") or a negative number from "-1" down ("-1" is the
// latest version).
From string
// To is the version to diff up to. The same rules for From apply.
To string
// Format is an optional field to specify the format with which the diff will
// be returned. Acceptable values are "text" (default), "html", or
// "html_simple".
Format string
}
// GetDiff returns the diff of the given versions.
func (c *Client) GetDiff(i *GetDiffInput) (*Diff, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.From == "" {
return nil, ErrMissingFrom
}
if i.To == "" {
return nil, ErrMissingTo
}
path := fmt.Sprintf("service/%s/diff/from/%s/to/%s", i.Service, i.From, i.To)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var d *Diff
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}

238
vendor/github.com/sethvargo/go-fastly/director.go generated vendored Normal file
View File

@ -0,0 +1,238 @@
package fastly
import (
"fmt"
"sort"
)
const (
// DirectorTypeRandom is a director that does random direction.
DirectorTypeRandom DirectorType = 1
// DirectorTypeRoundRobin is a director that does round-robin direction.
DirectorTypeRoundRobin DirectorType = 2
// DirectorTypeHash is a director that does hash direction.
DirectorTypeHash DirectorType = 3
// DirectorTypeClient is a director that does client direction.
DirectorTypeClient DirectorType = 4
)
// DirectorType is a type of director.
type DirectorType uint8
// Director represents a director response from the Fastly API.
type Director struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Comment string `mapstructure:"comment"`
Quorum uint `mapstructure:"quorum"`
Type DirectorType `mapstructure:"type"`
Retries uint `mapstructure:"retries"`
Capacity uint `mapstructure:"capacity"`
}
// directorsByName is a sortable list of directors.
type directorsByName []*Director
// Len, Swap, and Less implement the sortable interface.
func (s directorsByName) Len() int { return len(s) }
func (s directorsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s directorsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListDirectorsInput is used as input to the ListDirectors function.
type ListDirectorsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListDirectors returns the list of directors for the configuration version.
func (c *Client) ListDirectors(i *ListDirectorsInput) ([]*Director, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/director", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ds []*Director
if err := decodeJSON(&ds, resp.Body); err != nil {
return nil, err
}
sort.Stable(directorsByName(ds))
return ds, nil
}
// CreateDirectorInput is used as input to the CreateDirector function.
type CreateDirectorInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Comment string `form:"comment,omitempty"`
Quorum uint `form:"quorum,omitempty"`
Type DirectorType `form:"type,omitempty"`
Retries uint `form:"retries,omitempty"`
}
// CreateDirector creates a new Fastly director.
func (c *Client) CreateDirector(i *CreateDirectorInput) (*Director, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/director", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var d *Director
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}
// GetDirectorInput is used as input to the GetDirector function.
type GetDirectorInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the director to fetch.
Name string
}
// GetDirector gets the director configuration with the given parameters.
func (c *Client) GetDirector(i *GetDirectorInput) (*Director, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/director/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var d *Director
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}
// UpdateDirectorInput is used as input to the UpdateDirector function.
type UpdateDirectorInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the director to update.
Name string
Comment string `form:"comment,omitempty"`
Quorum uint `form:"quorum,omitempty"`
Type DirectorType `form:"type,omitempty"`
Retries uint `form:"retries,omitempty"`
}
// UpdateDirector updates a specific director.
func (c *Client) UpdateDirector(i *UpdateDirectorInput) (*Director, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/director/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var d *Director
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}
// DeleteDirectorInput is the input parameter to DeleteDirector.
type DeleteDirectorInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the director to delete (required).
Name string
}
// DeleteDirector deletes the given director version.
func (c *Client) DeleteDirector(i *DeleteDirectorInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/director/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

View File

@ -0,0 +1,161 @@
package fastly
import (
"fmt"
"time"
)
// DirectorBackend is the relationship between a director and a backend in the
// Fastly API.
type DirectorBackend struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Director string `mapstructure:"director_name"`
Backend string `mapstructure:"backend_name"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// CreateDirectorBackendInput is used as input to the CreateDirectorBackend
// function.
type CreateDirectorBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Director is the name of the director (required).
Director string
// Backend is the name of the backend (required).
Backend string
}
// CreateDirectorBackend creates a new Fastly backend.
func (c *Client) CreateDirectorBackend(i *CreateDirectorBackendInput) (*DirectorBackend, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Director == "" {
return nil, ErrMissingDirector
}
if i.Backend == "" {
return nil, ErrMissingBackend
}
path := fmt.Sprintf("/service/%s/version/%s/director/%s/backend/%s",
i.Service, i.Version, i.Director, i.Backend)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *DirectorBackend
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetDirectorBackendInput is used as input to the GetDirectorBackend function.
type GetDirectorBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Director is the name of the director (required).
Director string
// Backend is the name of the backend (required).
Backend string
}
// GetDirectorBackend gets the backend configuration with the given parameters.
func (c *Client) GetDirectorBackend(i *GetDirectorBackendInput) (*DirectorBackend, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Director == "" {
return nil, ErrMissingDirector
}
if i.Backend == "" {
return nil, ErrMissingBackend
}
path := fmt.Sprintf("/service/%s/version/%s/director/%s/backend/%s",
i.Service, i.Version, i.Director, i.Backend)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *DirectorBackend
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteDirectorBackendInput is the input parameter to DeleteDirectorBackend.
type DeleteDirectorBackendInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Director is the name of the director (required).
Director string
// Backend is the name of the backend (required).
Backend string
}
// DeleteDirectorBackend deletes the given backend version.
func (c *Client) DeleteDirectorBackend(i *DeleteDirectorBackendInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Director == "" {
return ErrMissingDirector
}
if i.Backend == "" {
return ErrMissingBackend
}
path := fmt.Sprintf("/service/%s/version/%s/director/%s/backend/%s",
i.Service, i.Version, i.Director, i.Backend)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

211
vendor/github.com/sethvargo/go-fastly/domain.go generated vendored Normal file
View File

@ -0,0 +1,211 @@
package fastly
import (
"fmt"
"sort"
)
// Domain represents the the domain name Fastly will serve content for.
type Domain struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Comment string `mapstructure:"comment"`
Locked bool `mapstructure:"locked"`
}
// domainsByName is a sortable list of backends.
type domainsByName []*Domain
// Len, Swap, and Less implement the sortable interface.
func (s domainsByName) Len() int { return len(s) }
func (s domainsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s domainsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListDomainsInput is used as input to the ListDomains function.
type ListDomainsInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// ListDomains returns the list of domains for this account.
func (c *Client) ListDomains(i *ListDomainsInput) ([]*Domain, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/domain", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ds []*Domain
if err := decodeJSON(&ds, resp.Body); err != nil {
return nil, err
}
sort.Stable(domainsByName(ds))
return ds, nil
}
// CreateDomainInput is used as input to the CreateDomain function.
type CreateDomainInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the domain that the service will respond to (required).
Name string `form:"name"`
// Comment is a personal, freeform descriptive note.
Comment string `form:"comment,omitempty"`
}
// CreateDomain creates a new domain with the given information.
func (c *Client) CreateDomain(i *CreateDomainInput) (*Domain, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/domain", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var d *Domain
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}
// GetDomainInput is used as input to the GetDomain function.
type GetDomainInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the domain to fetch.
Name string `form:"name"`
}
// GetDomain retrieves information about the given domain name.
func (c *Client) GetDomain(i *GetDomainInput) (*Domain, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/domain/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var d *Domain
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}
// UpdateDomainInput is used as input to the UpdateDomain function.
type UpdateDomainInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the domain that the service will respond to (required).
Name string
// NewName is the updated name of the domain
NewName string `form:"name"`
// Comment is a personal, freeform descriptive note.
Comment string `form:"comment,omitempty"`
}
// UpdateDomain updates a single domain for the current service. The only allowed
// parameters are `Name` and `Comment`.
func (c *Client) UpdateDomain(i *UpdateDomainInput) (*Domain, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/domain/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var d *Domain
if err := decodeJSON(&d, resp.Body); err != nil {
return nil, err
}
return d, nil
}
// DeleteDomainInput is used as input to the DeleteDomain function.
type DeleteDomainInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the domain that the service will respond to (required).
Name string `form:"name"`
}
// DeleteDomain removes a single domain by the given name.
func (c *Client) DeleteDomain(i *DeleteDomainInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/domain/%s", i.Service, i.Version, i.Name)
_, err := c.Delete(path, nil)
if err != nil {
return err
}
return nil
}

116
vendor/github.com/sethvargo/go-fastly/errors.go generated vendored Normal file
View File

@ -0,0 +1,116 @@
package fastly
import (
"bytes"
"errors"
"fmt"
"net/http"
)
// ErrMissingService is an error that is returned when an input struct requires
// a "Service" key, but one was not set.
var ErrMissingService = errors.New("Missing required field 'Service'")
// ErrMissingVersion is an error that is returned when an input struct requires
// a "Version" key, but one was not set.
var ErrMissingVersion = errors.New("Missing required field 'Version'")
// ErrMissingName is an error that is returned when an input struct requires a
// "Name" key, but one was not set.
var ErrMissingName = errors.New("Missing required field 'Name'")
// ErrMissingKey is an error that is returned when an input struct requires a
// "Name" key, but one was not set.
var ErrMissingKey = errors.New("Missing required field 'Key'")
// ErrMissingURL is an error that is returned when an input struct requires a
// "Name" key, but one was not set.
var ErrMissingURL = errors.New("Missing required field 'URL'")
// ErrMissingID is an error that is returned when an input struct requires an
// "ID" key, but one was not set.
var ErrMissingID = errors.New("Missing required field 'ID'")
// ErrMissingDictionary is an error that is returned when an input struct
// requires a "Dictionary" key, but one was not set.
var ErrMissingDictionary = errors.New("Missing required field 'Dictionary'")
// ErrMissingItemKey is an error that is returned when an input struct
// requires a "ItemKey" key, but one was not set.
var ErrMissingItemKey = errors.New("Missing required field 'ItemKey'")
// ErrMissingFrom is an error that is returned when an input struct
// requires a "From" key, but one was not set.
var ErrMissingFrom = errors.New("Missing required field 'From'")
// ErrMissingTo is an error that is returned when an input struct
// requires a "To" key, but one was not set.
var ErrMissingTo = errors.New("Missing required field 'To'")
// ErrMissingDirector is an error that is returned when an input struct
// requires a "From" key, but one was not set.
var ErrMissingDirector = errors.New("Missing required field 'Director'")
// ErrMissingBackend is an error that is returned when an input struct
// requires a "Backend" key, but one was not set.
var ErrMissingBackend = errors.New("Missing required field 'Backend'")
// ErrMissingYear is an error that is returned when an input struct
// requires a "Year" key, but one was not set.
var ErrMissingYear = errors.New("Missing required field 'Year'")
// ErrMissingMonth is an error that is returned when an input struct
// requires a "Month" key, but one was not set.
var ErrMissingMonth = errors.New("Missing required field 'Month'")
// Ensure HTTPError is, in fact, an error.
var _ error = (*HTTPError)(nil)
// HTTPError is a custom error type that wraps an HTTP status code with some
// helper functions.
type HTTPError struct {
// StatusCode is the HTTP status code (2xx-5xx).
StatusCode int
// Message and Detail are information returned by the Fastly API.
Message string `mapstructure:"msg"`
Detail string `mapstructure:"detail"`
}
// NewHTTPError creates a new HTTP error from the given code.
func NewHTTPError(resp *http.Response) *HTTPError {
var e *HTTPError
if resp.Body != nil {
decodeJSON(&e, resp.Body)
}
e.StatusCode = resp.StatusCode
return e
}
// Error implements the error interface and returns the string representing the
// error text that includes the status code and the corresponding status text.
func (e *HTTPError) Error() string {
var r bytes.Buffer
fmt.Fprintf(&r, "%d - %s", e.StatusCode, http.StatusText(e.StatusCode))
if e.Message != "" {
fmt.Fprintf(&r, "\nMessage: %s", e.Message)
}
if e.Detail != "" {
fmt.Fprintf(&r, "\nDetail: %s", e.Detail)
}
return r.String()
}
// String implements the stringer interface and returns the string representing
// the string text that includes the status code and corresponding status text.
func (e *HTTPError) String() string {
return e.Error()
}
// IsNotFound returns true if the HTTP error code is a 404, false otherwise.
func (e *HTTPError) IsNotFound() bool {
return e.StatusCode == 404
}

41
vendor/github.com/sethvargo/go-fastly/fastly.go generated vendored Normal file
View File

@ -0,0 +1,41 @@
package fastly
import (
"bytes"
"encoding"
)
type statusResp struct {
Status string
Msg string
}
func (t *statusResp) Ok() bool {
return t.Status == "ok"
}
// Ensure Compatibool implements the proper interfaces.
var (
_ encoding.TextMarshaler = new(Compatibool)
_ encoding.TextUnmarshaler = new(Compatibool)
)
// Compatibool is a boolean value that marshalls to 0/1 instead of true/false
// for compatability with Fastly's API.
type Compatibool bool
// MarshalText implements the encoding.TextMarshaler interface.
func (b Compatibool) MarshalText() ([]byte, error) {
if b {
return []byte("1"), nil
}
return []byte("0"), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (b Compatibool) UnmarshalText(t []byte) error {
if bytes.Equal(t, []byte("1")) {
b = Compatibool(true)
}
return nil
}

243
vendor/github.com/sethvargo/go-fastly/ftp.go generated vendored Normal file
View File

@ -0,0 +1,243 @@
package fastly
import (
"fmt"
"sort"
"time"
)
// FTP represents an FTP logging response from the Fastly API.
type FTP struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
Port uint `mapstructure:"port"`
Username string `mapstructure:"user"`
Password string `mapstructure:"password"`
Directory string `mapstructure:"directory"`
Period uint `mapstructure:"period"`
GzipLevel uint8 `mapstructure:"gzip_level"`
Format string `mapstructure:"format"`
ResponseCondition string `mapstructure:"response_condition"`
TimestampFormat string `mapstructure:"timestamp_format"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// ftpsByName is a sortable list of ftps.
type ftpsByName []*FTP
// Len, Swap, and Less implement the sortable interface.
func (s ftpsByName) Len() int { return len(s) }
func (s ftpsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ftpsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListFTPsInput is used as input to the ListFTPs function.
type ListFTPsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListFTPs returns the list of ftps for the configuration version.
func (c *Client) ListFTPs(i *ListFTPsInput) ([]*FTP, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/ftp", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ftps []*FTP
if err := decodeJSON(&ftps, resp.Body); err != nil {
return nil, err
}
sort.Stable(ftpsByName(ftps))
return ftps, nil
}
// CreateFTPInput is used as input to the CreateFTP function.
type CreateFTPInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
Username string `form:"user,omitempty"`
Password string `form:"password,omitempty"`
Directory string `form:"directory,omitempty"`
Period uint `form:"period,omitempty"`
GzipLevel uint8 `form:"gzip_level,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
TimestampFormat string `form:"timestamp_format,omitempty"`
}
// CreateFTP creates a new Fastly FTP.
func (c *Client) CreateFTP(i *CreateFTPInput) (*FTP, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/ftp", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var ftp *FTP
if err := decodeJSON(&ftp, resp.Body); err != nil {
return nil, err
}
return ftp, nil
}
// GetFTPInput is used as input to the GetFTP function.
type GetFTPInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the FTP to fetch.
Name string
}
// GetFTP gets the FTP configuration with the given parameters.
func (c *Client) GetFTP(i *GetFTPInput) (*FTP, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/ftp/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *FTP
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateFTPInput is used as input to the UpdateFTP function.
type UpdateFTPInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the FTP to update.
Name string
NewName string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
Username string `form:"user,omitempty"`
Password string `form:"password,omitempty"`
Directory string `form:"directory,omitempty"`
Period uint `form:"period,omitempty"`
GzipLevel uint8 `form:"gzip_level,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
TimestampFormat string `form:"timestamp_format,omitempty"`
}
// UpdateFTP updates a specific FTP.
func (c *Client) UpdateFTP(i *UpdateFTPInput) (*FTP, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/ftp/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *FTP
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteFTPInput is the input parameter to DeleteFTP.
type DeleteFTPInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the FTP to delete (required).
Name string
}
// DeleteFTP deletes the given FTP version.
func (c *Client) DeleteFTP(i *DeleteFTPInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/ftp/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

285
vendor/github.com/sethvargo/go-fastly/header.go generated vendored Normal file
View File

@ -0,0 +1,285 @@
package fastly
import (
"fmt"
"sort"
)
const (
// HeaderActionSet is a header action that sets or resets a header.
HeaderActionSet HeaderAction = "set"
// HeaderActionAppend is a header action that appends to an existing header.
HeaderActionAppend HeaderAction = "append"
// HeaderActionDelete is a header action that deletes a header.
HeaderActionDelete HeaderAction = "delete"
// HeaderActionRegex is a header action that performs a single regex
// replacement on a header.
HeaderActionRegex HeaderAction = "regex"
// HeaderActionRegexRepeat is a header action that performs a global regex
// replacement on a header.
HeaderActionRegexRepeat HeaderAction = "regex_repeat"
)
// HeaderAction is a type of header action.
type HeaderAction string
const (
// HeaderTypeRequest is a header type that performs on the request before
// lookups.
HeaderTypeRequest HeaderType = "request"
// HeaderTypeFetch is a header type that performs on the request to the origin
// server.
HeaderTypeFetch HeaderType = "fetch"
// HeaderTypeCache is a header type that performs on the response before it's
// store in the cache.
HeaderTypeCache HeaderType = "cache"
// HeaderTypeResponse is a header type that performs on the response before
// delivering to the client.
HeaderTypeResponse HeaderType = "response"
)
// HeaderType is a type of header.
type HeaderType string
// Header represents a header response from the Fastly API.
type Header struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Action HeaderAction `mapstructure:"action"`
IgnoreIfSet bool `mapstructure:"ignore_if_set"`
Type HeaderType `mapstructure:"type"`
Destination string `mapstructure:"dst"`
Source string `mapstructure:"src"`
Regex string `mapstructure:"regex"`
Substitution string `mapstructure:"substitution"`
Priority uint `mapstructure:"priority"`
RequestCondition string `mapstructure:"request_condition"`
CacheCondition string `mapstructure:"cache_condition"`
ResponseCondition string `mapstructure:"response_condition"`
}
// headersByName is a sortable list of headers.
type headersByName []*Header
// Len, Swap, and Less implement the sortable interface.
func (s headersByName) Len() int { return len(s) }
func (s headersByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s headersByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListHeadersInput is used as input to the ListHeaders function.
type ListHeadersInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListHeaders returns the list of headers for the configuration version.
func (c *Client) ListHeaders(i *ListHeadersInput) ([]*Header, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/header", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*Header
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(headersByName(bs))
return bs, nil
}
// CreateHeaderInput is used as input to the CreateHeader function.
type CreateHeaderInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Action HeaderAction `form:"action,omitempty"`
IgnoreIfSet bool `form:"ignore_if_set,omitempty"`
Type HeaderType `form:"type,omitempty"`
Destination string `form:"dst,omitempty"`
Source string `form:"src,omitempty"`
Regex string `form:"regex,omitempty"`
Substitution string `form:"substitution,omitempty"`
Priority uint `form:"priority,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
CacheCondition string `form:"cache_condition,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// CreateHeader creates a new Fastly header.
func (c *Client) CreateHeader(i *CreateHeaderInput) (*Header, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/header", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Header
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetHeaderInput is used as input to the GetHeader function.
type GetHeaderInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the header to fetch.
Name string
}
// GetHeader gets the header configuration with the given parameters.
func (c *Client) GetHeader(i *GetHeaderInput) (*Header, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/header/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *Header
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateHeaderInput is used as input to the UpdateHeader function.
type UpdateHeaderInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the header to update.
Name string
NewName string `form:"name,omitempty"`
Action HeaderAction `form:"action,omitempty"`
IgnoreIfSet bool `form:"ignore_if_set,omitempty"`
Type HeaderType `form:"type,omitempty"`
Destination string `form:"dst,omitempty"`
Source string `form:"src,omitempty"`
Regex string `form:"regex,omitempty"`
Substitution string `form:"substitution,omitempty"`
Priority uint `form:"priority,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
CacheCondition string `form:"cache_condition,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// UpdateHeader updates a specific header.
func (c *Client) UpdateHeader(i *UpdateHeaderInput) (*Header, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/header/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Header
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteHeaderInput is the input parameter to DeleteHeader.
type DeleteHeaderInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the header to delete (required).
Name string
}
// DeleteHeader deletes the given header version.
func (c *Client) DeleteHeader(i *DeleteHeaderInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/header/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

240
vendor/github.com/sethvargo/go-fastly/health_check.go generated vendored Normal file
View File

@ -0,0 +1,240 @@
package fastly
import (
"fmt"
"sort"
)
// HealthCheck represents a health check response from the Fastly API.
type HealthCheck struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Method string `mapstructure:"method"`
Host string `mapstructure:"host"`
Path string `mapstructure:"path"`
HTTPVersion string `mapstructure:"http_version"`
Timeout uint `mapstructure:"timeout"`
CheckInterval uint `mapstructure:"check_interval"`
ExpectedResponse uint `mapstructure:"expected_response"`
Window uint `mapstructure:"window"`
Threshold uint `mapstructure:"threshold"`
Initial uint `mapstructure:"initial"`
}
// healthChecksByName is a sortable list of health checks.
type healthChecksByName []*HealthCheck
// Len, Swap, and Less implement the sortable interface.
func (s healthChecksByName) Len() int { return len(s) }
func (s healthChecksByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s healthChecksByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListHealthChecksInput is used as input to the ListHealthChecks function.
type ListHealthChecksInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListHealthChecks returns the list of health checks for the configuration
// version.
func (c *Client) ListHealthChecks(i *ListHealthChecksInput) ([]*HealthCheck, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/healthcheck", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var hcs []*HealthCheck
if err := decodeJSON(&hcs, resp.Body); err != nil {
return nil, err
}
sort.Stable(healthChecksByName(hcs))
return hcs, nil
}
// CreateHealthCheckInput is used as input to the CreateHealthCheck function.
type CreateHealthCheckInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Method string `form:"method,omitempty"`
Host string `form:"host,omitempty"`
Path string `form:"path,omitempty"`
HTTPVersion string `form:"http_version,omitempty"`
Timeout uint `form:"timeout,omitempty"`
CheckInterval uint `form:"check_interval,omitempty"`
ExpectedResponse uint `form:"expected_response,omitempty"`
Window uint `form:"window,omitempty"`
Threshold uint `form:"threshold,omitempty"`
Initial uint `form:"initial,omitempty"`
}
// CreateHealthCheck creates a new Fastly health check.
func (c *Client) CreateHealthCheck(i *CreateHealthCheckInput) (*HealthCheck, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/healthcheck", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var h *HealthCheck
if err := decodeJSON(&h, resp.Body); err != nil {
return nil, err
}
return h, nil
}
// GetHealthCheckInput is used as input to the GetHealthCheck function.
type GetHealthCheckInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the health check to fetch.
Name string
}
// GetHealthCheck gets the health check configuration with the given parameters.
func (c *Client) GetHealthCheck(i *GetHealthCheckInput) (*HealthCheck, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/healthcheck/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var h *HealthCheck
if err := decodeJSON(&h, resp.Body); err != nil {
return nil, err
}
return h, nil
}
// UpdateHealthCheckInput is used as input to the UpdateHealthCheck function.
type UpdateHealthCheckInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the health check to update.
Name string
NewName string `form:"name,omitempty"`
Method string `form:"method,omitempty"`
Host string `form:"host,omitempty"`
Path string `form:"path,omitempty"`
HTTPVersion string `form:"http_version,omitempty"`
Timeout uint `form:"timeout,omitempty"`
CheckInterval uint `form:"check_interval,omitempty"`
ExpectedResponse uint `form:"expected_response,omitempty"`
Window uint `form:"window,omitempty"`
Threshold uint `form:"threshold,omitempty"`
Initial uint `form:"initial,omitempty"`
}
// UpdateHealthCheck updates a specific health check.
func (c *Client) UpdateHealthCheck(i *UpdateHealthCheckInput) (*HealthCheck, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/healthcheck/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var h *HealthCheck
if err := decodeJSON(&h, resp.Body); err != nil {
return nil, err
}
return h, nil
}
// DeleteHealthCheckInput is the input parameter to DeleteHealthCheck.
type DeleteHealthCheckInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the health check to delete (required).
Name string
}
// DeleteHealthCheck deletes the given health check.
func (c *Client) DeleteHealthCheck(i *DeleteHealthCheckInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/healthcheck/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

18
vendor/github.com/sethvargo/go-fastly/ip.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
package fastly
// IPAddrs is a sortable list of IP addresses returned by the Fastly API.
type IPAddrs []string
// IPs returns the list of public IP addresses for Fastly's network.
func (c *Client) IPs() (IPAddrs, error) {
resp, err := c.Get("/public-ip-list", nil)
if err != nil {
return nil, err
}
var m map[string][]string
if err := decodeJSON(&m, resp.Body); err != nil {
return nil, err
}
return IPAddrs(m["addresses"]), nil
}

228
vendor/github.com/sethvargo/go-fastly/logentries.go generated vendored Normal file
View File

@ -0,0 +1,228 @@
package fastly
import (
"fmt"
"sort"
"time"
)
// Logentries represents a logentries response from the Fastly API.
type Logentries struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Port uint `mapstructure:"port"`
UseTLS bool `mapstructure:"use_tls"`
Token string `mapstructure:"token"`
Format string `mapstructure:"format"`
ResponseCondition string `mapstructure:"response_condition"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// logentriesByName is a sortable list of logentries.
type logentriesByName []*Logentries
// Len, Swap, and Less implement the sortable interface.
func (s logentriesByName) Len() int { return len(s) }
func (s logentriesByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s logentriesByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListLogentriesInput is used as input to the ListLogentries function.
type ListLogentriesInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListLogentries returns the list of logentries for the configuration version.
func (c *Client) ListLogentries(i *ListLogentriesInput) ([]*Logentries, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/logentries", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ls []*Logentries
if err := decodeJSON(&ls, resp.Body); err != nil {
return nil, err
}
sort.Stable(logentriesByName(ls))
return ls, nil
}
// CreateLogentriesInput is used as input to the CreateLogentries function.
type CreateLogentriesInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Port uint `form:"port,omitempty"`
UseTLS Compatibool `form:"use_tls,omitempty"`
Token string `form:"token,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// CreateLogentries creates a new Fastly logentries.
func (c *Client) CreateLogentries(i *CreateLogentriesInput) (*Logentries, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/logentries", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var l *Logentries
if err := decodeJSON(&l, resp.Body); err != nil {
return nil, err
}
return l, nil
}
// GetLogentriesInput is used as input to the GetLogentries function.
type GetLogentriesInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the logentries to fetch.
Name string
}
// GetLogentries gets the logentries configuration with the given parameters.
func (c *Client) GetLogentries(i *GetLogentriesInput) (*Logentries, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/logentries/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var l *Logentries
if err := decodeJSON(&l, resp.Body); err != nil {
return nil, err
}
return l, nil
}
// UpdateLogentriesInput is used as input to the UpdateLogentries function.
type UpdateLogentriesInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the logentries to update.
Name string
NewName string `form:"name,omitempty"`
Port uint `form:"port,omitempty"`
UseTLS Compatibool `form:"use_tls,omitempty"`
Token string `form:"token,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// UpdateLogentries updates a specific logentries.
func (c *Client) UpdateLogentries(i *UpdateLogentriesInput) (*Logentries, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/logentries/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var l *Logentries
if err := decodeJSON(&l, resp.Body); err != nil {
return nil, err
}
return l, nil
}
// DeleteLogentriesInput is the input parameter to DeleteLogentries.
type DeleteLogentriesInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the logentries to delete (required).
Name string
}
// DeleteLogentries deletes the given logentries version.
func (c *Client) DeleteLogentries(i *DeleteLogentriesInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/logentries/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

231
vendor/github.com/sethvargo/go-fastly/papertrail.go generated vendored Normal file
View File

@ -0,0 +1,231 @@
package fastly
import (
"fmt"
"sort"
"time"
)
// Papertrail represents a papertrail response from the Fastly API.
type Papertrail struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
Port uint `mapstructure:"port"`
Format string `mapstructure:"format"`
ResponseCondition string `mapstructure:"response_condition"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// papertrailsByName is a sortable list of papertrails.
type papertrailsByName []*Papertrail
// Len, Swap, and Less implement the sortable interface.
func (s papertrailsByName) Len() int { return len(s) }
func (s papertrailsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s papertrailsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListPapertrailsInput is used as input to the ListPapertrails function.
type ListPapertrailsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListPapertrails returns the list of papertrails for the configuration version.
func (c *Client) ListPapertrails(i *ListPapertrailsInput) ([]*Papertrail, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/papertrail", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ps []*Papertrail
if err := decodeJSON(&ps, resp.Body); err != nil {
return nil, err
}
sort.Stable(papertrailsByName(ps))
return ps, nil
}
// CreatePapertrailInput is used as input to the CreatePapertrail function.
type CreatePapertrailInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
CreatedAt *time.Time `form:"created_at,omitempty"`
UpdatedAt *time.Time `form:"updated_at,omitempty"`
DeletedAt *time.Time `form:"deleted_at,omitempty"`
}
// CreatePapertrail creates a new Fastly papertrail.
func (c *Client) CreatePapertrail(i *CreatePapertrailInput) (*Papertrail, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/papertrail", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var p *Papertrail
if err := decodeJSON(&p, resp.Body); err != nil {
return nil, err
}
return p, nil
}
// GetPapertrailInput is used as input to the GetPapertrail function.
type GetPapertrailInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the papertrail to fetch.
Name string
}
// GetPapertrail gets the papertrail configuration with the given parameters.
func (c *Client) GetPapertrail(i *GetPapertrailInput) (*Papertrail, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/papertrail/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var p *Papertrail
if err := decodeJSON(&p, resp.Body); err != nil {
return nil, err
}
return p, nil
}
// UpdatePapertrailInput is used as input to the UpdatePapertrail function.
type UpdatePapertrailInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the papertrail to update.
Name string
NewName string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
CreatedAt *time.Time `form:"created_at,omitempty"`
UpdatedAt *time.Time `form:"updated_at,omitempty"`
DeletedAt *time.Time `form:"deleted_at,omitempty"`
}
// UpdatePapertrail updates a specific papertrail.
func (c *Client) UpdatePapertrail(i *UpdatePapertrailInput) (*Papertrail, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/papertrail/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var p *Papertrail
if err := decodeJSON(&p, resp.Body); err != nil {
return nil, err
}
return p, nil
}
// DeletePapertrailInput is the input parameter to DeletePapertrail.
type DeletePapertrailInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the papertrail to delete (required).
Name string
}
// DeletePapertrail deletes the given papertrail version.
func (c *Client) DeletePapertrail(i *DeletePapertrailInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/papertrail/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

130
vendor/github.com/sethvargo/go-fastly/purge.go generated vendored Normal file
View File

@ -0,0 +1,130 @@
package fastly
import "fmt"
// Purge is a response from a purge request.
type Purge struct {
// Status is the status of the purge, usually "ok".
Status string `mapstructure:"status"`
// ID is the unique ID of the purge request.
ID string `mapstructure:"id"`
}
// PurgeInput is used as input to the Purge function.
type PurgeInput struct {
// URL is the URL to purge (required).
URL string
// Soft performs a soft purge.
Soft bool
}
// Purge instantly purges an individual URL.
func (c *Client) Purge(i *PurgeInput) (*Purge, error) {
if i.URL == "" {
return nil, ErrMissingURL
}
req, err := c.RawRequest("PURGE", i.URL, nil)
if err != nil {
return nil, err
}
if i.Soft {
req.Header.Set("Fastly-Soft-Purge", "1")
}
resp, err := checkResp(c.HTTPClient.Do(req))
if err != nil {
return nil, err
}
var r *Purge
if err := decodeJSON(&r, resp.Body); err != nil {
return nil, err
}
return r, nil
}
// PurgeKeyInput is used as input to the Purge function.
type PurgeKeyInput struct {
// Service is the ID of the service (required).
Service string
// Key is the key to purge (required).
Key string
// Soft performs a soft purge.
Soft bool
}
// PurgeKey instantly purges a particular service of items tagged with a key.
func (c *Client) PurgeKey(i *PurgeKeyInput) (*Purge, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Key == "" {
return nil, ErrMissingKey
}
path := fmt.Sprintf("/service/%s/purge/%s", i.Service, i.Key)
req, err := c.RawRequest("POST", path, nil)
if err != nil {
return nil, err
}
if i.Soft {
req.Header.Set("Fastly-Soft-Purge", "1")
}
resp, err := checkResp(c.HTTPClient.Do(req))
if err != nil {
return nil, err
}
var r *Purge
if err := decodeJSON(&r, resp.Body); err != nil {
return nil, err
}
return r, nil
}
// PurgeAllInput is used as input to the Purge function.
type PurgeAllInput struct {
// Service is the ID of the service (required).
Service string
// Soft performs a soft purge.
Soft bool
}
// PurgeAll instantly purges everything from a service.
func (c *Client) PurgeAll(i *PurgeAllInput) (*Purge, error) {
if i.Service == "" {
return nil, ErrMissingService
}
path := fmt.Sprintf("/service/%s/purge_all", i.Service)
req, err := c.RawRequest("POST", path, nil)
if err != nil {
return nil, err
}
if i.Soft {
req.Header.Set("Fastly-Soft-Purge", "1")
}
resp, err := checkResp(c.HTTPClient.Do(req))
if err != nil {
return nil, err
}
var r *Purge
if err := decodeJSON(&r, resp.Body); err != nil {
return nil, err
}
return r, nil
}

68
vendor/github.com/sethvargo/go-fastly/request.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
package fastly
import (
"io"
"net/http"
"net/url"
"path"
)
// RequestOptions is the list of options to pass to the request.
type RequestOptions struct {
// Params is a map of key-value pairs that will be added to the Request.
Params map[string]string
// Headers is a map of key-value pairs that will be added to the Request.
Headers map[string]string
// Body is an io.Reader object that will be streamed or uploaded with the
// Request. BodyLength is the final size of the Body.
Body io.Reader
BodyLength int64
}
// RawRequest accepts a verb, URL, and RequestOptions struct and returns the
// constructed http.Request and any errors that occurred
func (c *Client) RawRequest(verb, p string, ro *RequestOptions) (*http.Request, error) {
// Ensure we have request options.
if ro == nil {
ro = new(RequestOptions)
}
// Append the path to the URL.
u := *c.url
u.Path = path.Join(c.url.Path, p)
// Add the token and other params.
var params = make(url.Values)
for k, v := range ro.Params {
params.Add(k, v)
}
u.RawQuery = params.Encode()
// Create the request object.
request, err := http.NewRequest(verb, u.String(), ro.Body)
if err != nil {
return nil, err
}
// Set the API key.
if len(c.apiKey) > 0 {
request.Header.Set(APIKeyHeader, c.apiKey)
}
// Set the User-Agent.
request.Header.Set("User-Agent", UserAgent)
// Add any custom headers.
for k, v := range ro.Headers {
request.Header.Add(k, v)
}
// Add Content-Length if we have it.
if ro.BodyLength > 0 {
request.ContentLength = ro.BodyLength
}
return request, nil
}

View File

@ -0,0 +1,279 @@
package fastly
import (
"fmt"
"sort"
)
const (
// RequestSettingActionLookup sets request handling to lookup via the cache.
RequestSettingActionLookup RequestSettingAction = "lookup"
// RequestSettingActionPass sets request handling to pass the cache.
RequestSettingActionPass RequestSettingAction = "pass"
)
// RequestSettingAction is a type of request setting action.
type RequestSettingAction string
const (
// RequestSettingXFFClear clears any X-Forwarded-For headers.
RequestSettingXFFClear RequestSettingXFF = "clear"
// RequestSettingXFFLeave leaves any X-Forwarded-For headers untouched.
RequestSettingXFFLeave RequestSettingXFF = "leave"
// RequestSettingXFFAppend adds Fastly X-Forwarded-For headers.
RequestSettingXFFAppend RequestSettingXFF = "append"
// RequestSettingXFFAppendAll appends all Fastly X-Forwarded-For headers.
RequestSettingXFFAppendAll RequestSettingXFF = "append_all"
// RequestSettingXFFOverwrite clears any X-Forwarded-For headers and replaces
// with Fastly ones.
RequestSettingXFFOverwrite RequestSettingXFF = "overwrite"
)
// RequestSettingXFF is a type of X-Forwarded-For value to set.
type RequestSettingXFF string
// RequestSetting represents a request setting response from the Fastly API.
type RequestSetting struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
ForceMiss bool `mapstructure:"force_miss"`
ForceSSL bool `mapstructure:"force_ssl"`
Action RequestSettingAction `mapstructure:"action"`
BypassBusyWait bool `mapstructure:"bypass_busy_wait"`
MaxStaleAge uint `mapstructure:"max_stale_age"`
HashKeys string `mapstructure:"hash_keys"`
XForwardedFor RequestSettingXFF `mapstructure:"xff"`
TimerSupport bool `mapstructure:"timer_support"`
GeoHeaders bool `mapstructure:"geo_headers"`
DefaultHost string `mapstructure:"default_host"`
RequestCondition string `mapstructure:"request_condition"`
}
// requestSettingsByName is a sortable list of request settings.
type requestSettingsByName []*RequestSetting
// Len, Swap, and Less implement the sortable interface.
func (s requestSettingsByName) Len() int { return len(s) }
func (s requestSettingsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s requestSettingsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListRequestSettingsInput is used as input to the ListRequestSettings
// function.
type ListRequestSettingsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListRequestSettings returns the list of request settings for the
// configuration version.
func (c *Client) ListRequestSettings(i *ListRequestSettingsInput) ([]*RequestSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/request_settings", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*RequestSetting
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(requestSettingsByName(bs))
return bs, nil
}
// CreateRequestSettingInput is used as input to the CreateRequestSetting
// function.
type CreateRequestSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
ForceMiss Compatibool `form:"force_miss,omitempty"`
ForceSSL Compatibool `form:"force_ssl,omitempty"`
Action RequestSettingAction `form:"action,omitempty"`
BypassBusyWait Compatibool `form:"bypass_busy_wait,omitempty"`
MaxStaleAge uint `form:"max_stale_age,omitempty"`
HashKeys string `form:"hash_keys,omitempty"`
XForwardedFor RequestSettingXFF `form:"xff,omitempty"`
TimerSupport Compatibool `form:"timer_support,omitempty"`
GeoHeaders Compatibool `form:"geo_headers,omitempty"`
DefaultHost string `form:"default_host,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
}
// CreateRequestSetting creates a new Fastly request settings.
func (c *Client) CreateRequestSetting(i *CreateRequestSettingInput) (*RequestSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/request_settings", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *RequestSetting
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetRequestSettingInput is used as input to the GetRequestSetting function.
type GetRequestSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the request settings to fetch.
Name string
}
// GetRequestSetting gets the request settings configuration with the given
// parameters.
func (c *Client) GetRequestSetting(i *GetRequestSettingInput) (*RequestSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/request_settings/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *RequestSetting
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateRequestSettingInput is used as input to the UpdateRequestSetting
// function.
type UpdateRequestSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the request settings to update.
Name string
NewName string `form:"name,omitempty"`
ForceMiss Compatibool `form:"force_miss,omitempty"`
ForceSSL Compatibool `form:"force_ssl,omitempty"`
Action RequestSettingAction `form:"action,omitempty"`
BypassBusyWait Compatibool `form:"bypass_busy_wait,omitempty"`
MaxStaleAge uint `form:"max_stale_age,omitempty"`
HashKeys string `form:"hash_keys,omitempty"`
XForwardedFor RequestSettingXFF `form:"xff,omitempty"`
TimerSupport Compatibool `form:"timer_support,omitempty"`
GeoHeaders Compatibool `form:"geo_headers,omitempty"`
DefaultHost string `form:"default_host,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
}
// UpdateRequestSetting updates a specific request settings.
func (c *Client) UpdateRequestSetting(i *UpdateRequestSettingInput) (*RequestSetting, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/request_settings/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *RequestSetting
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteRequestSettingInput is the input parameter to DeleteRequestSetting.
type DeleteRequestSettingInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the request settings to delete (required).
Name string
}
// DeleteRequestSetting deletes the given request settings version.
func (c *Client) DeleteRequestSetting(i *DeleteRequestSettingInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/request_settings/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

View File

@ -0,0 +1,232 @@
package fastly
import (
"fmt"
"sort"
)
// ResponseObject represents a response object response from the Fastly API.
type ResponseObject struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Status uint `mapstructure:"status"`
Response string `mapstructure:"response"`
Content string `mapstructure:"content"`
ContentType string `mapstructure:"content_type"`
RequestCondition string `mapstructure:"request_condition"`
CacheCondition string `mapstructure:"cache_condition"`
}
// responseObjectsByName is a sortable list of response objects.
type responseObjectsByName []*ResponseObject
// Len, Swap, and Less implement the sortable interface.
func (s responseObjectsByName) Len() int { return len(s) }
func (s responseObjectsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s responseObjectsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListResponseObjectsInput is used as input to the ListResponseObjects
// function.
type ListResponseObjectsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListResponseObjects returns the list of response objects for the
// configuration version.
func (c *Client) ListResponseObjects(i *ListResponseObjectsInput) ([]*ResponseObject, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/response_object", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*ResponseObject
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(responseObjectsByName(bs))
return bs, nil
}
// CreateResponseObjectInput is used as input to the CreateResponseObject
// function.
type CreateResponseObjectInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Status uint `form:"status,omitempty"`
Response string `form:"response,omitempty"`
Content string `form:"content,omitempty"`
ContentType string `form:"content_type,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
CacheCondition string `form:"cache_condition,omitempty"`
}
// CreateResponseObject creates a new Fastly response object.
func (c *Client) CreateResponseObject(i *CreateResponseObjectInput) (*ResponseObject, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/response_object", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *ResponseObject
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetResponseObjectInput is used as input to the GetResponseObject function.
type GetResponseObjectInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the response object to fetch.
Name string
}
// GetResponseObject gets the response object configuration with the given
// parameters.
func (c *Client) GetResponseObject(i *GetResponseObjectInput) (*ResponseObject, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/response_object/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *ResponseObject
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateResponseObjectInput is used as input to the UpdateResponseObject
// function.
type UpdateResponseObjectInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the response object to update.
Name string
NewName string `form:"name,omitempty"`
Status uint `form:"status,omitempty"`
Response string `form:"response,omitempty"`
Content string `form:"content,omitempty"`
ContentType string `form:"content_type,omitempty"`
RequestCondition string `form:"request_condition,omitempty"`
CacheCondition string `form:"cache_condition,omitempty"`
}
// UpdateResponseObject updates a specific response object.
func (c *Client) UpdateResponseObject(i *UpdateResponseObjectInput) (*ResponseObject, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/response_object/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *ResponseObject
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteResponseObjectInput is the input parameter to DeleteResponseObject.
type DeleteResponseObjectInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the response object to delete (required).
Name string
}
// DeleteResponseObject deletes the given response object version.
func (c *Client) DeleteResponseObject(i *DeleteResponseObjectInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/response_object/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

240
vendor/github.com/sethvargo/go-fastly/s3.go generated vendored Normal file
View File

@ -0,0 +1,240 @@
package fastly
import (
"fmt"
"sort"
"time"
)
// S3 represents a S3 response from the Fastly API.
type S3 struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
BucketName string `mapstructure:"bucket_name"`
AccessKey string `mapstructure:"access_key"`
SecretKey string `mapstructure:"secret_key"`
Path string `mapstructure:"path"`
Period uint `mapstructure:"period"`
GzipLevel uint `mapstructure:"gzip_level"`
Format string `mapstructure:"format"`
ResponseCondition string `mapstructure:"response_condition"`
TimestampFormat string `mapstructure:"timestamp_format"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// s3sByName is a sortable list of S3s.
type s3sByName []*S3
// Len, Swap, and Less implement the sortable interface.
func (s s3sByName) Len() int { return len(s) }
func (s s3sByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s s3sByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListS3sInput is used as input to the ListS3s function.
type ListS3sInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListS3s returns the list of S3s for the configuration version.
func (c *Client) ListS3s(i *ListS3sInput) ([]*S3, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/s3", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var s3s []*S3
if err := decodeJSON(&s3s, resp.Body); err != nil {
return nil, err
}
sort.Stable(s3sByName(s3s))
return s3s, nil
}
// CreateS3Input is used as input to the CreateS3 function.
type CreateS3Input struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
BucketName string `form:"bucket_name,omitempty"`
AccessKey string `form:"access_key,omitempty"`
SecretKey string `form:"secret_key,omitempty"`
Path string `form:"path,omitempty"`
Period uint `form:"period,omitempty"`
GzipLevel uint `form:"gzip_level,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
TimestampFormat string `form:"timestamp_format,omitempty"`
}
// CreateS3 creates a new Fastly S3.
func (c *Client) CreateS3(i *CreateS3Input) (*S3, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/s3", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var s3 *S3
if err := decodeJSON(&s3, resp.Body); err != nil {
return nil, err
}
return s3, nil
}
// GetS3Input is used as input to the GetS3 function.
type GetS3Input struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the S3 to fetch.
Name string
}
// GetS3 gets the S3 configuration with the given parameters.
func (c *Client) GetS3(i *GetS3Input) (*S3, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/s3/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var s3 *S3
if err := decodeJSON(&s3, resp.Body); err != nil {
return nil, err
}
return s3, nil
}
// UpdateS3Input is used as input to the UpdateS3 function.
type UpdateS3Input struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the S3 to update.
Name string
NewName string `form:"name,omitempty"`
BucketName string `form:"bucket_name,omitempty"`
AccessKey string `form:"access_key,omitempty"`
SecretKey string `form:"secret_key,omitempty"`
Path string `form:"path,omitempty"`
Period uint `form:"period,omitempty"`
GzipLevel uint `form:"gzip_level,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
TimestampFormat string `form:"timestamp_format,omitempty"`
}
// UpdateS3 updates a specific S3.
func (c *Client) UpdateS3(i *UpdateS3Input) (*S3, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/s3/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var s3 *S3
if err := decodeJSON(&s3, resp.Body); err != nil {
return nil, err
}
return s3, nil
}
// DeleteS3Input is the input parameter to DeleteS3.
type DeleteS3Input struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the S3 to delete (required).
Name string
}
// DeleteS3 deletes the given S3 version.
func (c *Client) DeleteS3(i *DeleteS3Input) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/s3/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

205
vendor/github.com/sethvargo/go-fastly/service.go generated vendored Normal file
View File

@ -0,0 +1,205 @@
package fastly
import (
"fmt"
"sort"
)
// Service represents a single service for the Fastly account.
type Service struct {
ID string `mapstructure:"id"`
Name string `mapstructure:"name"`
Comment string `mapstructure:"comment"`
CustomerID string `mapstructure:"customer_id"`
ActiveVersion uint `mapstructure:"version"`
Versions []*Version `mapstructure:"versions"`
}
type ServiceDetail struct {
ID string `mapstructure:"id"`
Name string `mapstructure:"name"`
Comment string `mapstructure:"comment"`
CustomerID string `mapstructure:"customer_id"`
ActiveVersion Version `mapstructure:"active_version"`
Version Version `mapstructure:"version"`
Versions []*Version `mapstructure:"versions"`
}
// servicesByName is a sortable list of services.
type servicesByName []*Service
// Len, Swap, and Less implement the sortable interface.
func (s servicesByName) Len() int { return len(s) }
func (s servicesByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s servicesByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListServicesInput is used as input to the ListServices function.
type ListServicesInput struct{}
// ListServices returns the full list of services for the current account.
func (c *Client) ListServices(i *ListServicesInput) ([]*Service, error) {
resp, err := c.Get("/service", nil)
if err != nil {
return nil, err
}
var s []*Service
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
sort.Stable(servicesByName(s))
return s, nil
}
// CreateServiceInput is used as input to the CreateService function.
type CreateServiceInput struct {
Name string `form:"name,omitempty"`
Comment string `form:"comment,omitempty"`
}
// CreateService creates a new service with the given information.
func (c *Client) CreateService(i *CreateServiceInput) (*Service, error) {
resp, err := c.PostForm("/service", i, nil)
if err != nil {
return nil, err
}
var s *Service
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// GetServiceInput is used as input to the GetService function.
type GetServiceInput struct {
ID string
}
// GetService retrieves the service information for the service with the given
// id. If no service exists for the given id, the API returns a 400 response
// (not a 404).
func (c *Client) GetService(i *GetServiceInput) (*Service, error) {
if i.ID == "" {
return nil, ErrMissingID
}
path := fmt.Sprintf("/service/%s", i.ID)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var s *Service
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// GetService retrieves the details for the service with the given id. If no
// service exists for the given id, the API returns a 400 response (not a 404).
func (c *Client) GetServiceDetails(i *GetServiceInput) (*ServiceDetail, error) {
if i.ID == "" {
return nil, ErrMissingID
}
path := fmt.Sprintf("/service/%s/details", i.ID)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var s *ServiceDetail
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// UpdateServiceInput is used as input to the UpdateService function.
type UpdateServiceInput struct {
ID string
Name string `form:"name,omitempty"`
Comment string `form:"comment,omitempty"`
}
// UpdateService updates the service with the given input.
func (c *Client) UpdateService(i *UpdateServiceInput) (*Service, error) {
if i.ID == "" {
return nil, ErrMissingID
}
path := fmt.Sprintf("/service/%s", i.ID)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var s *Service
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// DeleteServiceInput is used as input to the DeleteService function.
type DeleteServiceInput struct {
ID string
}
// DeleteService updates the service with the given input.
func (c *Client) DeleteService(i *DeleteServiceInput) error {
if i.ID == "" {
return ErrMissingID
}
path := fmt.Sprintf("/service/%s", i.ID)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}
// SearchServiceInput is used as input to the SearchService function.
type SearchServiceInput struct {
Name string
}
// SearchService gets a specific service by name. If no service exists by that
// name, the API returns a 400 response (not a 404).
func (c *Client) SearchService(i *SearchServiceInput) (*Service, error) {
if i.Name == "" {
return nil, ErrMissingName
}
resp, err := c.Get("/service/search", &RequestOptions{
Params: map[string]string{
"name": i.Name,
},
})
if err != nil {
return nil, err
}
var s *Service
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}

77
vendor/github.com/sethvargo/go-fastly/settings.go generated vendored Normal file
View File

@ -0,0 +1,77 @@
package fastly
import "fmt"
// Settings represents a backend response from the Fastly API.
type Settings struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
DefaultTTL uint `mapstructure:"general.default_ttl"`
DefaultHost string `mapstructure:"general.default_host"`
}
// GetSettingsInput is used as input to the GetSettings function.
type GetSettingsInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// GetSettings gets the backend configuration with the given parameters.
func (c *Client) GetSettings(i *GetSettingsInput) (*Settings, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/settings", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *Settings
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateSettingsInput is used as input to the UpdateSettings function.
type UpdateSettingsInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
DefaultTTL uint `form:"general.default_ttl,omitempty"`
DefaultHost string `form:"general.default_host,omitempty"`
}
// UpdateSettings updates a specific backend.
func (c *Client) UpdateSettings(i *UpdateSettingsInput) (*Settings, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/settings", i.Service, i.Version)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Settings
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}

225
vendor/github.com/sethvargo/go-fastly/sumologic.go generated vendored Normal file
View File

@ -0,0 +1,225 @@
package fastly
import (
"fmt"
"sort"
"time"
)
// Sumologic represents a sumologic response from the Fastly API.
type Sumologic struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
URL string `mapstructure:"url"`
Format string `mapstructure:"format"`
ResponseCondition string `mapstructure:"response_condition"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// sumologicsByName is a sortable list of sumologics.
type sumologicsByName []*Sumologic
// Len, Swap, and Less implement the sortable interface.
func (s sumologicsByName) Len() int { return len(s) }
func (s sumologicsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sumologicsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListSumologicsInput is used as input to the ListSumologics function.
type ListSumologicsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListSumologics returns the list of sumologics for the configuration version.
func (c *Client) ListSumologics(i *ListSumologicsInput) ([]*Sumologic, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/sumologic", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ss []*Sumologic
if err := decodeJSON(&ss, resp.Body); err != nil {
return nil, err
}
sort.Stable(sumologicsByName(ss))
return ss, nil
}
// CreateSumologicInput is used as input to the CreateSumologic function.
type CreateSumologicInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
URL string `form:"url,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// CreateSumologic creates a new Fastly sumologic.
func (c *Client) CreateSumologic(i *CreateSumologicInput) (*Sumologic, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/sumologic", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var s *Sumologic
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// GetSumologicInput is used as input to the GetSumologic function.
type GetSumologicInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the sumologic to fetch.
Name string
}
// GetSumologic gets the sumologic configuration with the given parameters.
func (c *Client) GetSumologic(i *GetSumologicInput) (*Sumologic, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/sumologic/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var s *Sumologic
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// UpdateSumologicInput is used as input to the UpdateSumologic function.
type UpdateSumologicInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the sumologic to update.
Name string
NewName string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
URL string `form:"url,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// UpdateSumologic updates a specific sumologic.
func (c *Client) UpdateSumologic(i *UpdateSumologicInput) (*Sumologic, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/sumologic/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var s *Sumologic
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// DeleteSumologicInput is the input parameter to DeleteSumologic.
type DeleteSumologicInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the sumologic to delete (required).
Name string
}
// DeleteSumologic deletes the given sumologic version.
func (c *Client) DeleteSumologic(i *DeleteSumologicInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/sumologic/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

234
vendor/github.com/sethvargo/go-fastly/syslog.go generated vendored Normal file
View File

@ -0,0 +1,234 @@
package fastly
import (
"fmt"
"sort"
"time"
)
// Syslog represents a syslog response from the Fastly API.
type Syslog struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Address string `mapstructure:"address"`
Port uint `mapstructure:"port"`
UseTLS bool `mapstructure:"use_tls"`
TLSCACert string `mapstructure:"tls_ca_cert"`
Token string `mapstructure:"token"`
Format string `mapstructure:"format"`
ResponseCondition string `mapstructure:"response_condition"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
}
// syslogsByName is a sortable list of syslogs.
type syslogsByName []*Syslog
// Len, Swap, and Less implement the sortable interface.
func (s syslogsByName) Len() int { return len(s) }
func (s syslogsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s syslogsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListSyslogsInput is used as input to the ListSyslogs function.
type ListSyslogsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListSyslogs returns the list of syslogs for the configuration version.
func (c *Client) ListSyslogs(i *ListSyslogsInput) ([]*Syslog, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/syslog", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var ss []*Syslog
if err := decodeJSON(&ss, resp.Body); err != nil {
return nil, err
}
sort.Stable(syslogsByName(ss))
return ss, nil
}
// CreateSyslogInput is used as input to the CreateSyslog function.
type CreateSyslogInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
UseTLS Compatibool `form:"use_tls,omitempty"`
TLSCACert string `form:"tls_ca_cert,omitempty"`
Token string `form:"token,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// CreateSyslog creates a new Fastly syslog.
func (c *Client) CreateSyslog(i *CreateSyslogInput) (*Syslog, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/logging/syslog", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var s *Syslog
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// GetSyslogInput is used as input to the GetSyslog function.
type GetSyslogInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the syslog to fetch.
Name string
}
// GetSyslog gets the syslog configuration with the given parameters.
func (c *Client) GetSyslog(i *GetSyslogInput) (*Syslog, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/syslog/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var s *Syslog
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// UpdateSyslogInput is used as input to the UpdateSyslog function.
type UpdateSyslogInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the syslog to update.
Name string
NewName string `form:"name,omitempty"`
Address string `form:"address,omitempty"`
Port uint `form:"port,omitempty"`
UseTLS Compatibool `form:"use_tls,omitempty"`
TLSCACert string `form:"tls_ca_cert,omitempty"`
Token string `form:"token,omitempty"`
Format string `form:"format,omitempty"`
ResponseCondition string `form:"response_condition,omitempty"`
}
// UpdateSyslog updates a specific syslog.
func (c *Client) UpdateSyslog(i *UpdateSyslogInput) (*Syslog, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/syslog/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var s *Syslog
if err := decodeJSON(&s, resp.Body); err != nil {
return nil, err
}
return s, nil
}
// DeleteSyslogInput is the input parameter to DeleteSyslog.
type DeleteSyslogInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the syslog to delete (required).
Name string
}
// DeleteSyslog deletes the given syslog version.
func (c *Client) DeleteSyslog(i *DeleteSyslogInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/logging/syslog/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

282
vendor/github.com/sethvargo/go-fastly/vcl.go generated vendored Normal file
View File

@ -0,0 +1,282 @@
package fastly
import (
"fmt"
"sort"
)
// VCL represents a response about VCL from the Fastly API.
type VCL struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Main bool `mapstructure:"main"`
Content string `mapstructure:"content"`
}
// vclsByName is a sortable list of VCLs.
type vclsByName []*VCL
// Len, Swap, and Less implement the sortable interface.
func (s vclsByName) Len() int { return len(s) }
func (s vclsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s vclsByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListVCLsInput is used as input to the ListVCLs function.
type ListVCLsInput struct {
// Service is the ID of the service (required).
Service string
// Version is the specific configuration version (required).
Version string
}
// ListVCLs returns the list of VCLs for the configuration version.
func (c *Client) ListVCLs(i *ListVCLsInput) ([]*VCL, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/vcl", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var vcls []*VCL
if err := decodeJSON(&vcls, resp.Body); err != nil {
return nil, err
}
sort.Stable(vclsByName(vcls))
return vcls, nil
}
// GetVCLInput is used as input to the GetVCL function.
type GetVCLInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the VCL to fetch.
Name string
}
// GetVCL gets the VCL configuration with the given parameters.
func (c *Client) GetVCL(i *GetVCLInput) (*VCL, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/vcl/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var vcl *VCL
if err := decodeJSON(&vcl, resp.Body); err != nil {
return nil, err
}
return vcl, nil
}
// GetGeneratedVCLInput is used as input to the GetGeneratedVCL function.
type GetGeneratedVCLInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// GetGeneratedVCL gets the VCL configuration with the given parameters.
func (c *Client) GetGeneratedVCL(i *GetGeneratedVCLInput) (*VCL, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/generated_vcl", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var vcl *VCL
if err := decodeJSON(&vcl, resp.Body); err != nil {
return nil, err
}
return vcl, nil
}
// CreateVCLInput is used as input to the CreateVCL function.
type CreateVCLInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Content string `form:"content,omitempty"`
}
// CreateVCL creates a new Fastly VCL.
func (c *Client) CreateVCL(i *CreateVCLInput) (*VCL, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/vcl", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var vcl *VCL
if err := decodeJSON(&vcl, resp.Body); err != nil {
return nil, err
}
return vcl, nil
}
// UpdateVCLInput is used as input to the UpdateVCL function.
type UpdateVCLInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the VCL to update (required).
Name string
NewName string `form:"name,omitempty"`
Content string `form:"content,omitempty"`
}
// UpdateVCL creates a new Fastly VCL.
func (c *Client) UpdateVCL(i *UpdateVCLInput) (*VCL, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/vcl/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var vcl *VCL
if err := decodeJSON(&vcl, resp.Body); err != nil {
return nil, err
}
return vcl, nil
}
// ActivateVCLInput is used as input to the ActivateVCL function.
type ActivateVCLInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the VCL to mark as main (required).
Name string
}
// ActivateVCL creates a new Fastly VCL.
func (c *Client) ActivateVCL(i *ActivateVCLInput) (*VCL, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/vcl/%s/main", i.Service, i.Version, i.Name)
resp, err := c.Put(path, nil)
if err != nil {
return nil, err
}
var vcl *VCL
if err := decodeJSON(&vcl, resp.Body); err != nil {
return nil, err
}
return vcl, nil
}
// DeleteVCLInput is the input parameter to DeleteVCL.
type DeleteVCLInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the VCL to delete (required).
Name string
}
// DeleteVCL deletes the given VCL version.
func (c *Client) DeleteVCL(i *DeleteVCLInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/vcl/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

335
vendor/github.com/sethvargo/go-fastly/version.go generated vendored Normal file
View File

@ -0,0 +1,335 @@
package fastly
import (
"fmt"
"sort"
)
// Version represents a distinct configuration version.
type Version struct {
Number string `mapstructure:"number"`
Comment string `mapstructure:"comment"`
ServiceID string `mapstructure:"service_id"`
Active bool `mapstructure:"active"`
Locked bool `mapstructure:"locked"`
Deployed bool `mapstructure:"deployed"`
Staging bool `mapstructure:"staging"`
Testing bool `mapstructure:"testing"`
}
// versionsByNumber is a sortable list of versions. This is used by the version
// `List()` function to sort the API responses.
type versionsByNumber []*Version
// Len, Swap, and Less implement the sortable interface.
func (s versionsByNumber) Len() int { return len(s) }
func (s versionsByNumber) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s versionsByNumber) Less(i, j int) bool {
return s[i].Number < s[j].Number
}
// ListVersionsInput is the input to the ListVersions function.
type ListVersionsInput struct {
// Service is the ID of the service (required).
Service string
}
// ListVersions returns the full list of all versions of the given service.
func (c *Client) ListVersions(i *ListVersionsInput) ([]*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
path := fmt.Sprintf("/service/%s/version", i.Service)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var e []*Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
sort.Sort(versionsByNumber(e))
return e, nil
}
// LatestVersionInput is the input to the LatestVersion function.
type LatestVersionInput struct {
// Service is the ID of the service (required).
Service string
}
// LatestVersion fetches the latest version. If there are no versions, this
// function will return nil (but not an error).
func (c *Client) LatestVersion(i *LatestVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
list, err := c.ListVersions(&ListVersionsInput{Service: i.Service})
if err != nil {
return nil, err
}
if len(list) < 1 {
return nil, nil
}
e := list[len(list)-1]
return e, nil
}
// CreateVersionInput is the input to the CreateVersion function.
type CreateVersionInput struct {
// Service is the ID of the service (required).
Service string
}
// CreateVersion constructs a new version. There are no request parameters, but
// you should consult the resulting version number. Note that `CloneVersion` is
// preferred in almost all scenarios, since `Create()` creates a _blank_
// configuration where `Clone()` builds off of an existing configuration.
func (c *Client) CreateVersion(i *CreateVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
path := fmt.Sprintf("/service/%s/version", i.Service)
resp, err := c.Post(path, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}
// GetVersionInput is the input to the GetVersion function.
type GetVersionInput struct {
// Service is the ID of the service (required).
Service string
// Version is the version number to fetch (required).
Version string
}
// GetVersion fetches a version with the given information.
func (c *Client) GetVersion(i *GetVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}
// UpdateVersionInput is the input to the UpdateVersion function.
type UpdateVersionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Comment string `form:"comment,omitempty"`
}
// UpdateVersion updates the given version
func (c *Client) UpdateVersion(i *UpdateVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s", i.Service, i.Version)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}
// ActivateVersionInput is the input to the ActivateVersion function.
type ActivateVersionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// ActivateVersion activates the given version.
func (c *Client) ActivateVersion(i *ActivateVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/activate", i.Service, i.Version)
resp, err := c.Put(path, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}
// DeactivateVersionInput is the input to the DeactivateVersion function.
type DeactivateVersionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// DeactivateVersion deactivates the given version.
func (c *Client) DeactivateVersion(i *DeactivateVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/deactivate", i.Service, i.Version)
resp, err := c.Put(path, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}
// CloneVersionInput is the input to the CloneVersion function.
type CloneVersionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// CloneVersion creates a clone of the version with and returns a new
// configuration version with all the same configuration options, but an
// incremented number.
func (c *Client) CloneVersion(i *CloneVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/clone", i.Service, i.Version)
resp, err := c.Put(path, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}
// ValidateVersionInput is the input to the ValidateVersion function.
type ValidateVersionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// ValidateVersion validates if the given version is okay.
func (c *Client) ValidateVersion(i *ValidateVersionInput) (bool, string, error) {
var msg string
if i.Service == "" {
return false, msg, ErrMissingService
}
if i.Version == "" {
return false, msg, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/validate", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return false, msg, err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return false, msg, err
}
msg = r.Msg
return r.Ok(), msg, nil
}
// LockVersionInput is the input to the LockVersion function.
type LockVersionInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// LockVersion locks the specified version.
func (c *Client) LockVersion(i *LockVersionInput) (*Version, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/lock", i.Service, i.Version)
resp, err := c.Put(path, nil)
if err != nil {
return nil, err
}
var e *Version
if err := decodeJSON(&e, resp.Body); err != nil {
return nil, err
}
return e, nil
}

214
vendor/github.com/sethvargo/go-fastly/wordpress.go generated vendored Normal file
View File

@ -0,0 +1,214 @@
package fastly
import (
"fmt"
"sort"
)
// Wordpress represents a wordpress response from the Fastly API.
type Wordpress struct {
ServiceID string `mapstructure:"service_id"`
Version string `mapstructure:"version"`
Name string `mapstructure:"name"`
Path string `mapstructure:"path"`
Comment string `mapstructure:"comment"`
}
// wordpressesByName is a sortable list of wordpresses.
type wordpressesByName []*Wordpress
// Len, Swap, and Less implement the sortable interface.
func (s wordpressesByName) Len() int { return len(s) }
func (s wordpressesByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s wordpressesByName) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
// ListWordpressesInput is used as input to the ListWordpresses function.
type ListWordpressesInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
}
// ListWordpresses returns the list of wordpresses for the configuration version.
func (c *Client) ListWordpresses(i *ListWordpressesInput) ([]*Wordpress, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/wordpress", i.Service, i.Version)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var bs []*Wordpress
if err := decodeJSON(&bs, resp.Body); err != nil {
return nil, err
}
sort.Stable(wordpressesByName(bs))
return bs, nil
}
// CreateWordpressInput is used as input to the CreateWordpress function.
type CreateWordpressInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
Name string `form:"name,omitempty"`
Path string `form:"path,omitempty"`
Comment string `form:"comment,omitempty"`
}
// CreateWordpress creates a new Fastly wordpress.
func (c *Client) CreateWordpress(i *CreateWordpressInput) (*Wordpress, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
path := fmt.Sprintf("/service/%s/version/%s/wordpress", i.Service, i.Version)
resp, err := c.PostForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Wordpress
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// GetWordpressInput is used as input to the GetWordpress function.
type GetWordpressInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the wordpress to fetch.
Name string
}
// GetWordpress gets the wordpress configuration with the given parameters.
func (c *Client) GetWordpress(i *GetWordpressInput) (*Wordpress, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/wordpress/%s", i.Service, i.Version, i.Name)
resp, err := c.Get(path, nil)
if err != nil {
return nil, err
}
var b *Wordpress
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// UpdateWordpressInput is used as input to the UpdateWordpress function.
type UpdateWordpressInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the wordpress to update.
Name string
NewName string `form:"name,omitempty"`
Path string `form:"path,omitempty"`
Comment string `form:"comment,omitempty"`
}
// UpdateWordpress updates a specific wordpress.
func (c *Client) UpdateWordpress(i *UpdateWordpressInput) (*Wordpress, error) {
if i.Service == "" {
return nil, ErrMissingService
}
if i.Version == "" {
return nil, ErrMissingVersion
}
if i.Name == "" {
return nil, ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/wordpress/%s", i.Service, i.Version, i.Name)
resp, err := c.PutForm(path, i, nil)
if err != nil {
return nil, err
}
var b *Wordpress
if err := decodeJSON(&b, resp.Body); err != nil {
return nil, err
}
return b, nil
}
// DeleteWordpressInput is the input parameter to DeleteWordpress.
type DeleteWordpressInput struct {
// Service is the ID of the service. Version is the specific configuration
// version. Both fields are required.
Service string
Version string
// Name is the name of the wordpress to delete (required).
Name string
}
// DeleteWordpress deletes the given wordpress version.
func (c *Client) DeleteWordpress(i *DeleteWordpressInput) error {
if i.Service == "" {
return ErrMissingService
}
if i.Version == "" {
return ErrMissingVersion
}
if i.Name == "" {
return ErrMissingName
}
path := fmt.Sprintf("/service/%s/version/%s/wordpress/%s", i.Service, i.Version, i.Name)
resp, err := c.Delete(path, nil)
if err != nil {
return err
}
var r *statusResp
if err := decodeJSON(&r, resp.Body); err != nil {
return err
}
if !r.Ok() {
return fmt.Errorf("Not Ok")
}
return nil
}

View File

@ -22,6 +22,7 @@ body.layout-dnsimple,
body.layout-docker, body.layout-docker,
body.layout-dyn, body.layout-dyn,
body.layout-github, body.layout-github,
body.layout-fastly,
body.layout-google, body.layout-google,
body.layout-heroku, body.layout-heroku,
body.layout-influxdb, body.layout-influxdb,

View File

@ -0,0 +1,87 @@
---
layout: "fastly"
page_title: "Provider: Fastly"
sidebar_current: "docs-fastly-index"
description: |-
Fastly
---
# Fastly Provider
The Fastly provider is used to interact with the content delivery network (CDN)
provided by Fastly.
In order to use this Provider, you must have an active account with Fastly.
Pricing and signup information can be found at https://www.fastly.com/signup
Use the navigation to the left to read about the available resources.
## Example Usage
```
# Configure the Fastly Provider
provider "fastly" {
api_key = "test"
}
# Create a Service
resource "fastly_service_v1" "myservice" {
name = "myawesometestservice"
...
}
```
## Authentication
The Fastly provider offers an API key based method of providing credentials for
authentication. The following methods are supported, in this order, and
explained below:
- Static API key
- Environment variables
### Static API Key ###
Static credentials can be provided by adding a `api_key` in-line in the
Fastly provider block:
Usage:
```
provider "fastly" {
api_key = "test"
}
resource "fastly_service_v1" "myservice" {
...
}
```
The API key for an account can be found on the Account page: https://app.fastly.com/#account
###Environment variables
You can provide your API key via `FASTLY_API_KEY` environment variable,
representing your Fastly API key. When using this method, you may omit the
Fastly `provider` block entirely:
```
resource "fastly_service_v1" "myservice" {
...
}
```
Usage:
```
$ export FASTLY_API_KEY="afastlyapikey"
$ terraform plan
```
## Argument Reference
The following arguments are supported in the `provider` block:
* `api_key` - (Optional) This is the API key. It must be provided, but
it can also be sourced from the `FASTLY_API_KEY` environment variable

View File

@ -0,0 +1,136 @@
---
layout: "fastly"
page_title: "Fastly: aws_vpc"
sidebar_current: "docs-fastly-resource-service-v1"
description: |-
Provides an Fastly Service
---
# fastly\_service\_v1
Provides a Fastly Service, representing the configuration for a website, app,
api, or anything else to be served through Fastly. A Service encompasses Domains
and Backends.
The Service resource requires a domain name that is correctly set up to direct
traffic to the Fastly service. See Fastly's guide on [Adding CNAME Records][fastly-cname]
on their documentation site for guidance.
## Example Usage
Basic usage:
```
resource "fastly_service_v1" "demo" {
name = "demofastly"
domain {
name = "demo.notexample.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "localhost"
port = 80
}
force_destroy = true
}
```
Basic usage with an Amazon S3 Website:
```
resource "fastly_service_v1" "demo" {
name = "demofastly"
domain {
name = "demo.notexample.com"
comment = "demo"
}
backend {
address = "demo.notexample.com.s3-website-us-west-2.amazonaws.com"
name = "AWS S3 hosting"
port = 80
}
default_host = "${aws_s3_bucket.website.name}.s3-website-us-west-2.amazonaws.com"
force_destroy = true
}
resource "aws_s3_bucket" "website" {
bucket = "demo.notexample.com"
acl = "public-read"
website {
index_document = "index.html"
error_document = "error.html"
}
}
```
**Note:** For an AWS S3 Bucket, the Backend address is
`<domain>.s3-website-<region>.amazonaws.com`. The `default_host` attribute
should be set to `<bucket_name>.s3-website-<region>.amazonaws.com`. See the
Fastly documentation on [Amazon S3][fastly-s3]
## Argument Reference
The following arguments are supported:
* `name` - (Required) The unique name for the Service to create
* `domain` - (Required) A set of Domain names to serve as entry points for your
Service. Defined below.
* `backend` - (Required) A set of Backends to service requests from your Domains.
Defined below.
* `default_host` - (Optional) The default hostname
* `default_ttl` - (Optional) The default Time-to-live (TTL) for requests
* `force_destroy` - (Optional) Services that are active cannot be destroyed. In
order to destroy the Service, set `force_destroy` to `true`. Default `false`.
The `domain` block supports:
* `name` - (Required) The domain that this Service will respond to
* `comment` - (Optional) An optional comment about the Domain
The `backend` block supports:
* `name` - (Required, string) Name for this Backend. Must be unique to this Service
* `address` - (Required, string) An IPv4, hostname, or IPv6 address for the Backend
* `auto_loadbalance` - (Optional, boolean) Denote if this Backend should be
included in the pool of backends that requests are load balanced against.
Default `true`
* `between_bytes_timeout` - (Optional) How long to wait between bytes in milliseconds. Default `10000`
* `connect_timeout` - (Optional) How long to wait for a timeout in milliseconds.
Default `1000`
* `error_threshold` - (Optional) Number of errors to allow before the Backend is marked as down. Default `0`
* `first_byte_timeout` - (Optional) How long to wait for the first bytes in milliseconds. Default `15000`
* `max_conn` - (Optional) Maximum number of connections for this Backend.
Default `200`
* `port` - (Optional) The port number Backend responds on. Default `80`
* `ssl_check_cert` - (Optional) Be strict on checking SSL certs. Default `true`
* `weight` - (Optional) How long to wait for the first bytes in milliseconds.
Default `100`
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the Service
* `name` Name of this service
* `active_version` - The currently active version of your Fastly Service
* `domain`  Set of Domains. See above for details
* `backend`  Set of Backends. See above for details
* `default_host`  Default host specified
* `default_ttl` - Default TTL
* `force_destroy` - Force the destruction of the Service on delete
[fastly-s3]: https://docs.fastly.com/guides/integrations/amazon-s3
[fastly-cname]: https://docs.fastly.com/guides/basic-setup/adding-cname-records

View File

@ -193,6 +193,10 @@
<a href="/docs/providers/github/index.html">Github</a> <a href="/docs/providers/github/index.html">Github</a>
</li> </li>
<li<%= sidebar_current("docs-providers-fastly") %>>
<a href="/docs/providers/fastly/index.html">Fastly</a>
</li>
<li<%= sidebar_current("docs-providers-google") %>> <li<%= sidebar_current("docs-providers-google") %>>
<a href="/docs/providers/google/index.html">Google Cloud</a> <a href="/docs/providers/google/index.html">Google Cloud</a>
</li> </li>

View File

@ -0,0 +1,28 @@
<% wrap_layout :inner do %>
<% content_for :sidebar do %>
<div class="docs-sidebar hidden-print affix-top" role="complementary">
<ul class="nav docs-sidenav">
<li<%= sidebar_current("docs-home") %>>
<a href="/docs/providers/index.html">&laquo; Documentation Home</a>
</li>
<li<%= sidebar_current("docs-fastly-index") %>>
<a href="/docs/providers/fastly/index.html">Fastly Provider</a>
</li>
<li<%= sidebar_current(/^docs-fastly-resource/) %>>
<a href="#">Resources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-fastly-resource-service-v1") %>>
<a href="/docs/providers/fastly/r/service_v1.html">service_v1</a>
</li>
</ul>
</li>
</ul>
</div>
<% end %>
<%= yield %>
<% end %>