provider/fastly Adds papertrail logging (#11491)

* Creates papertrail logging resource for fastly

* Adds modification support for fastly papertrail

* Flattens and lists papertrail resources

* Adds testing for fastly papertrail

* Adds papertrail documentation for fastly to the website

* Fixes schema assignment name mistake

* Changes testing hostnames to pass fastly API validation
This commit is contained in:
Traver Tischio 2017-01-30 11:05:27 -05:00 committed by Paul Stack
parent 5411e7d36b
commit 33b43fccdc
3 changed files with 305 additions and 1 deletions

View File

@ -457,6 +457,38 @@ func resourceServiceV1() *schema.Resource {
}, },
}, },
"papertrail": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
// Required fields
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Unique name to refer to this logging setup",
},
"address": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "The address of the papertrail service",
},
"port": &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "The port of the papertrail service",
},
// Optional
"format": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "%h %l %u %t %r %>s",
Description: "Apache-style string or VCL variables to use for log formatting",
},
},
},
},
"request_setting": &schema.Schema{ "request_setting": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
@ -616,6 +648,7 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
"header", "header",
"gzip", "gzip",
"s3logging", "s3logging",
"papertrail",
"condition", "condition",
"request_setting", "request_setting",
"cache_setting", "cache_setting",
@ -1034,6 +1067,58 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
} }
} }
// find difference in Papertrail
if d.HasChange("papertrail") {
os, ns := d.GetChange("papertrail")
if os == nil {
os = new(schema.Set)
}
if ns == nil {
ns = new(schema.Set)
}
oss := os.(*schema.Set)
nss := ns.(*schema.Set)
removePapertrail := oss.Difference(nss).List()
addPapertrail := nss.Difference(oss).List()
// DELETE old papertrail configurations
for _, pRaw := range removePapertrail {
pf := pRaw.(map[string]interface{})
opts := gofastly.DeletePapertrailInput{
Service: d.Id(),
Version: latestVersion,
Name: pf["name"].(string),
}
log.Printf("[DEBUG] Fastly Papertrail removal opts: %#v", opts)
err := conn.DeletePapertrail(&opts)
if err != nil {
return err
}
}
// POST new/updated Papertrail
for _, pRaw := range addPapertrail {
pf := pRaw.(map[string]interface{})
opts := gofastly.CreatePapertrailInput{
Service: d.Id(),
Version: latestVersion,
Name: pf["name"].(string),
Address: pf["address"].(string),
Port: uint(pf["port"].(int)),
Format: pf["format"].(string),
}
log.Printf("[DEBUG] Create Papertrail Opts: %#v", opts)
_, err := conn.CreatePapertrail(&opts)
if err != nil {
return err
}
}
}
// find difference in request settings // find difference in request settings
if d.HasChange("request_setting") { if d.HasChange("request_setting") {
os, ns := d.GetChange("request_setting") os, ns := d.GetChange("request_setting")
@ -1362,6 +1447,23 @@ func resourceServiceV1Read(d *schema.ResourceData, meta interface{}) error {
log.Printf("[WARN] Error setting S3 Logging for (%s): %s", d.Id(), err) log.Printf("[WARN] Error setting S3 Logging for (%s): %s", d.Id(), err)
} }
// refresh Papertrail Logging
log.Printf("[DEBUG] Refreshing Papertrail for (%s)", d.Id())
papertrailList, err := conn.ListPapertrails(&gofastly.ListPapertrailsInput{
Service: d.Id(),
Version: s.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up Papertrail for (%s), version (%s): %s", d.Id(), s.ActiveVersion.Number, err)
}
pl := flattenPapertrails(papertrailList)
if err := d.Set("papertrail", pl); err != nil {
log.Printf("[WARN] Error setting Papertrail for (%s): %s", d.Id(), err)
}
// refresh Conditions // refresh Conditions
log.Printf("[DEBUG] Refreshing Conditions for (%s)", d.Id()) log.Printf("[DEBUG] Refreshing Conditions for (%s)", d.Id())
conditionList, err := conn.ListConditions(&gofastly.ListConditionsInput{ conditionList, err := conn.ListConditions(&gofastly.ListConditionsInput{
@ -1725,6 +1827,30 @@ func flattenS3s(s3List []*gofastly.S3) []map[string]interface{} {
return sl return sl
} }
func flattenPapertrails(papertrailList []*gofastly.Papertrail) []map[string]interface{} {
var pl []map[string]interface{}
for _, p := range papertrailList {
// Convert S3s to a map for saving to state.
ns := map[string]interface{}{
"name": p.Name,
"address": p.Address,
"port": p.Port,
"format": p.Format,
}
// prune any empty values that come from the default string value in structs
for k, v := range ns {
if v == "" {
delete(ns, k)
}
}
pl = append(pl, ns)
}
return pl
}
func flattenConditions(conditionList []*gofastly.Condition) []map[string]interface{} { func flattenConditions(conditionList []*gofastly.Condition) []map[string]interface{} {
var cl []map[string]interface{} var cl []map[string]interface{}
for _, c := range conditionList { for _, c := range conditionList {

View File

@ -0,0 +1,165 @@
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 TestAccFastlyServiceV1_papertrail_basic(t *testing.T) {
var service gofastly.ServiceDetail
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
domainName1 := fmt.Sprintf("%s.notadomain.com", acctest.RandString(10))
log1 := gofastly.Papertrail{
Version: "1",
Name: "papertrailtesting",
Address: "test1.papertrailapp.com",
Port: uint(3600),
Format: "%h %l %u %t %r %>s",
}
log2 := gofastly.Papertrail{
Version: "1",
Name: "papertrailtesting2",
Address: "test2.papertrailapp.com",
Port: uint(8080),
Format: "%h %l %u %t %r %>s",
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckServiceV1Destroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccServiceV1PapertrailConfig(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1PapertrailAttributes(&service, []*gofastly.Papertrail{&log1}),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "name", name),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "papertrail.#", "1"),
),
},
resource.TestStep{
Config: testAccServiceV1PapertrailConfig_update(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
testAccCheckFastlyServiceV1PapertrailAttributes(&service, []*gofastly.Papertrail{&log1, &log2}),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "name", name),
resource.TestCheckResourceAttr(
"fastly_service_v1.foo", "papertrail.#", "2"),
),
},
},
})
}
func testAccCheckFastlyServiceV1PapertrailAttributes(service *gofastly.ServiceDetail, papertrails []*gofastly.Papertrail) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*FastlyClient).conn
papertrailList, err := conn.ListPapertrails(&gofastly.ListPapertrailsInput{
Service: service.ID,
Version: service.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up Papertrail for (%s), version (%s): %s", service.Name, service.ActiveVersion.Number, err)
}
if len(papertrailList) != len(papertrails) {
return fmt.Errorf("Papertrail List count mismatch, expected (%d), got (%d)", len(papertrails), len(papertrailList))
}
var found int
for _, p := range papertrails {
for _, lp := range papertrailList {
if p.Name == lp.Name {
// we don't know these things ahead of time, so populate them now
p.ServiceID = service.ID
p.Version = service.ActiveVersion.Number
// We don't track these, so clear them out because we also wont know
// these ahead of time
lp.CreatedAt = nil
lp.UpdatedAt = nil
if !reflect.DeepEqual(p, lp) {
return fmt.Errorf("Bad match Papertrail match, expected (%#v), got (%#v)", p, lp)
}
found++
}
}
}
if found != len(papertrails) {
return fmt.Errorf("Error matching Papertrail rules")
}
return nil
}
}
func testAccServiceV1PapertrailConfig(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"
}
papertrail {
name = "papertrailtesting"
address = "test1.papertrailapp.com"
port = 3600
}
force_destroy = true
}`, name, domain)
}
func testAccServiceV1PapertrailConfig_update(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"
}
papertrail {
name = "papertrailtesting"
address = "test1.papertrailapp.com"
port = 3600
}
papertrail {
name = "papertrailtesting2"
address = "test2.papertrailapp.com"
port = 8080
}
force_destroy = true
}`, name, domain)
}

View File

@ -150,6 +150,8 @@ order to destroy the Service, set `force_destroy` to `true`. Default `false`.
* `request_setting` - (Optional) A set of Request modifiers. Defined below * `request_setting` - (Optional) A set of Request modifiers. Defined below
* `s3logging` - (Optional) A set of S3 Buckets to send streaming logs too. * `s3logging` - (Optional) A set of S3 Buckets to send streaming logs too.
Defined below. Defined below.
* `papertrail` - (Optional) A Papertrail endpoint to send streaming logs too.
Defined below.
* `vcl` - (Optional) A set of custom VCL configuration blocks. The * `vcl` - (Optional) A set of custom VCL configuration blocks. The
ability to upload custom VCL code is not enabled by default for new Fastly ability to upload custom VCL code is not enabled by default for new Fastly
accounts (see the [Fastly documentation](https://docs.fastly.com/guides/vcl/uploading-custom-vcl) for details). accounts (see the [Fastly documentation](https://docs.fastly.com/guides/vcl/uploading-custom-vcl) for details).
@ -174,7 +176,7 @@ Default `1000`
* `max_conn` - (Optional) Maximum number of connections for this Backend. * `max_conn` - (Optional) Maximum number of connections for this Backend.
Default `200`. Default `200`.
* `port` - (Optional) The port number on which the Backend responds. Default `80`. * `port` - (Optional) The port number on which the Backend responds. Default `80`.
* `request_condition` - (Optional, string) Condition, which if met, will select this backend during a request. * `request_condition` - (Optional, string) Condition, which if met, will select this backend during a request.
* `ssl_check_cert` - (Optional) Be strict about checking SSL certs. Default `true`. * `ssl_check_cert` - (Optional) Be strict about checking SSL certs. Default `true`.
* `ssl_hostname` - (Optional) Used for both SNI during the TLS handshake and to validate the cert. * `ssl_hostname` - (Optional) Used for both SNI during the TLS handshake and to validate the cert.
* `shield` - (Optional) The POP of the shield designated to reduce inbound load. * `shield` - (Optional) The POP of the shield designated to reduce inbound load.
@ -282,6 +284,16 @@ compressed. Default `0`.
Request Setting should be applied. For detailed information about Conditionals, Request Setting should be applied. For detailed information about Conditionals,
see [Fastly's Documentation on Conditionals][fastly-conditionals]. see [Fastly's Documentation on Conditionals][fastly-conditionals].
The `papertrail` block supports:
* `name` - (Required) A unique name to identify this Papertrail endpoint.
* `address` - (Required) The address of the Papertrail endpoint.
* `port` - (Required) The port associated with the address where the Papertrail endpoint can be accessed.
* `format` - (Optional) Apache-style string or VCL variables to use for log formatting. Defaults to Apache Common Log format (`%h %l %u %t %r %>s`)
* `request_condition` - (Optional) The VCL request condition to check if this
Request Setting should be applied. For detailed information about Conditionals,
see [Fastly's Documentation on Conditionals][fastly-conditionals].
The `vcl` block supports: The `vcl` block supports:
* `name` - (Required) A unique name for this configuration block. * `name` - (Required) A unique name for this configuration block.
@ -302,6 +314,7 @@ Service.
* `backend`  Set of Backends. See above for details. * `backend`  Set of Backends. See above for details.
* `header`  Set of Headers. See above for details. * `header`  Set of Headers. See above for details.
* `s3logging`  Set of S3 Logging configurations. See above for details. * `s3logging`  Set of S3 Logging configurations. See above for details.
* `papertrail`  Set of Papertrail configurations. See above for details.
* `vcl`  Set of custom VCL configurations. See above for details. * `vcl`  Set of custom VCL configurations. See above for details.
* `default_host`  Default host specified. * `default_host`  Default host specified.
* `default_ttl` - Default TTL. * `default_ttl` - Default TTL.