provider/fastly: GCS (#13553)
* PAAS-5611 Adding docs * PAAS-5611 adding gcs logging resource * PAAS-5611 adding gcs testing * Adding testing file * Cleaning up type and making flatten array clearer * Fixing issue with tests
This commit is contained in:
parent
5ce5348070
commit
8995f1afdb
|
@ -647,6 +647,72 @@ func resourceServiceV1() *schema.Resource {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"gcslogging": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
// Required fields
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Unique name to refer to this logging setup",
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "The email address associated with the target GCS bucket on your account.",
|
||||||
|
},
|
||||||
|
"bucket_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "The name of the bucket in which to store the logs.",
|
||||||
|
},
|
||||||
|
"secret_key": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "The secret key associated with the target gcs bucket on your account.",
|
||||||
|
},
|
||||||
|
// Optional fields
|
||||||
|
"path": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "Path to store the files. Must end with a trailing slash",
|
||||||
|
},
|
||||||
|
"gzip_level": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: 0,
|
||||||
|
Description: "Gzip Compression level",
|
||||||
|
},
|
||||||
|
"period": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: 3600,
|
||||||
|
Description: "How frequently the logs should be transferred, in seconds (Default 3600)",
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "%h %l %u %t %r %>s",
|
||||||
|
Description: "Apache-style string or VCL variables to use for log formatting",
|
||||||
|
},
|
||||||
|
"timestamp_format": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "%Y-%m-%dT%H:%M:%S.000",
|
||||||
|
Description: "specified timestamp formatting (default `%Y-%m-%dT%H:%M:%S.000`)",
|
||||||
|
},
|
||||||
|
"response_condition": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "",
|
||||||
|
Description: "Name of a condition to apply this logging.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
"response_object": {
|
"response_object": {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -1450,6 +1516,59 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find difference in gcslogging
|
||||||
|
if d.HasChange("gcslogging") {
|
||||||
|
os, ns := d.GetChange("gcslogging")
|
||||||
|
if os == nil {
|
||||||
|
os = new(schema.Set)
|
||||||
|
}
|
||||||
|
if ns == nil {
|
||||||
|
ns = new(schema.Set)
|
||||||
|
}
|
||||||
|
|
||||||
|
oss := os.(*schema.Set)
|
||||||
|
nss := ns.(*schema.Set)
|
||||||
|
removeGcslogging := oss.Difference(nss).List()
|
||||||
|
addGcslogging := nss.Difference(oss).List()
|
||||||
|
|
||||||
|
// DELETE old gcslogging configurations
|
||||||
|
for _, pRaw := range removeGcslogging {
|
||||||
|
sf := pRaw.(map[string]interface{})
|
||||||
|
opts := gofastly.DeleteGCSInput{
|
||||||
|
Service: d.Id(),
|
||||||
|
Version: latestVersion,
|
||||||
|
Name: sf["name"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Fastly gcslogging removal opts: %#v", opts)
|
||||||
|
err := conn.DeleteGCS(&opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST new/updated gcslogging
|
||||||
|
for _, pRaw := range addGcslogging {
|
||||||
|
sf := pRaw.(map[string]interface{})
|
||||||
|
opts := gofastly.CreateGCSInput{
|
||||||
|
Service: d.Id(),
|
||||||
|
Version: latestVersion,
|
||||||
|
Name: sf["name"].(string),
|
||||||
|
User: sf["email"].(string),
|
||||||
|
Bucket: sf["bucket_name"].(string),
|
||||||
|
SecretKey: sf["secret_key"].(string),
|
||||||
|
Format: sf["format"].(string),
|
||||||
|
ResponseCondition: sf["response_condition"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Create GCS Opts: %#v", opts)
|
||||||
|
_, err := conn.CreateGCS(&opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// find difference in Response Object
|
// find difference in Response Object
|
||||||
if d.HasChange("response_object") {
|
if d.HasChange("response_object") {
|
||||||
or, nr := d.GetChange("response_object")
|
or, nr := d.GetChange("response_object")
|
||||||
|
@ -1883,6 +2002,22 @@ func resourceServiceV1Read(d *schema.ResourceData, meta interface{}) error {
|
||||||
log.Printf("[WARN] Error setting Sumologic for (%s): %s", d.Id(), err)
|
log.Printf("[WARN] Error setting Sumologic for (%s): %s", d.Id(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// refresh GCS Logging
|
||||||
|
log.Printf("[DEBUG] Refreshing GCS for (%s)", d.Id())
|
||||||
|
GCSList, err := conn.ListGCSs(&gofastly.ListGCSsInput{
|
||||||
|
Service: d.Id(),
|
||||||
|
Version: s.ActiveVersion.Number,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[ERR] Error looking up GCS for (%s), version (%s): %s", d.Id(), s.ActiveVersion.Number, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gcsl := flattenGCS(GCSList)
|
||||||
|
if err := d.Set("gcs", gcsl); err != nil {
|
||||||
|
log.Printf("[WARN] Error setting gcs for (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
// refresh Response Objects
|
// refresh Response Objects
|
||||||
log.Printf("[DEBUG] Refreshing Response Object for (%s)", d.Id())
|
log.Printf("[DEBUG] Refreshing Response Object for (%s)", d.Id())
|
||||||
responseObjectList, err := conn.ListResponseObjects(&gofastly.ListResponseObjectsInput{
|
responseObjectList, err := conn.ListResponseObjects(&gofastly.ListResponseObjectsInput{
|
||||||
|
@ -2350,6 +2485,35 @@ func flattenSumologics(sumologicList []*gofastly.Sumologic) []map[string]interfa
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flattenGCS(gcsList []*gofastly.GCS) []map[string]interface{} {
|
||||||
|
var GCSList []map[string]interface{}
|
||||||
|
for _, currentGCS := range gcsList {
|
||||||
|
// Convert gcs to a map for saving to state.
|
||||||
|
GCSMapString := map[string]interface{}{
|
||||||
|
"name": currentGCS.Name,
|
||||||
|
"email": currentGCS.User,
|
||||||
|
"bucket_name": currentGCS.Bucket,
|
||||||
|
"secret_key": currentGCS.SecretKey,
|
||||||
|
"path": currentGCS.Path,
|
||||||
|
"period": int(currentGCS.Period),
|
||||||
|
"gzip_level": int(currentGCS.GzipLevel),
|
||||||
|
"response_condition": currentGCS.ResponseCondition,
|
||||||
|
"format": currentGCS.Format,
|
||||||
|
}
|
||||||
|
|
||||||
|
// prune any empty values that come from the default string value in structs
|
||||||
|
for k, v := range GCSMapString {
|
||||||
|
if v == "" {
|
||||||
|
delete(GCSMapString, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GCSList = append(GCSList, GCSMapString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return GCSList
|
||||||
|
}
|
||||||
|
|
||||||
func flattenResponseObjects(responseObjectList []*gofastly.ResponseObject) []map[string]interface{} {
|
func flattenResponseObjects(responseObjectList []*gofastly.ResponseObject) []map[string]interface{} {
|
||||||
var rol []map[string]interface{}
|
var rol []map[string]interface{}
|
||||||
for _, ro := range responseObjectList {
|
for _, ro := range responseObjectList {
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
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 TestResourceFastlyFlattenGCS(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
remote []*gofastly.GCS
|
||||||
|
local []map[string]interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
remote: []*gofastly.GCS{
|
||||||
|
&gofastly.GCS{
|
||||||
|
Name: "GCS collector",
|
||||||
|
User: "email@example.com",
|
||||||
|
Bucket: "bucketName",
|
||||||
|
SecretKey: "secretKey",
|
||||||
|
Format: "log format",
|
||||||
|
Period: 3600,
|
||||||
|
GzipLevel: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
local: []map[string]interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "GCS collector",
|
||||||
|
"email": "email@example.com",
|
||||||
|
"bucket_name": "bucketName",
|
||||||
|
"secret_key": "secretKey",
|
||||||
|
"format": "log format",
|
||||||
|
"period": 3600,
|
||||||
|
"gzip_level": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
out := flattenGCS(c.remote)
|
||||||
|
if !reflect.DeepEqual(out, c.local) {
|
||||||
|
t.Fatalf("Error matching:\nexpected: %#v\ngot: %#v", c.local, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccFastlyServiceV1_gcslogging(t *testing.T) {
|
||||||
|
var service gofastly.ServiceDetail
|
||||||
|
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||||
|
gcsName := fmt.Sprintf("gcs %s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckServiceV1Destroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccServiceV1Config_gcs(name, gcsName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
|
||||||
|
testAccCheckFastlyServiceV1Attributes_gcs(&service, name, gcsName),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckFastlyServiceV1Attributes_gcs(service *gofastly.ServiceDetail, name, gcsName 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
|
||||||
|
gcsList, err := conn.ListGCSs(&gofastly.ListGCSsInput{
|
||||||
|
Service: service.ID,
|
||||||
|
Version: service.ActiveVersion.Number,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[ERR] Error looking up GCSs for (%s), version (%s): %s", service.Name, service.ActiveVersion.Number, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(gcsList) != 1 {
|
||||||
|
return fmt.Errorf("GCS missing, expected: 1, got: %d", len(gcsList))
|
||||||
|
}
|
||||||
|
|
||||||
|
if gcsList[0].Name != gcsName {
|
||||||
|
return fmt.Errorf("GCS name mismatch, expected: %s, got: %#v", gcsName, gcsList[0].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccServiceV1Config_gcs(name, gcsName string) string {
|
||||||
|
backendName := fmt.Sprintf("%s.aws.amazon.com", acctest.RandString(3))
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
gcslogging {
|
||||||
|
name = "%s"
|
||||||
|
email = "email@example.com",
|
||||||
|
bucket_name = "bucketName",
|
||||||
|
secret_key = "secretKey",
|
||||||
|
format = "log format",
|
||||||
|
response_condition = "",
|
||||||
|
}
|
||||||
|
|
||||||
|
force_destroy = true
|
||||||
|
}`, name, backendName, gcsName)
|
||||||
|
}
|
|
@ -155,6 +155,8 @@ Defined below.
|
||||||
Defined below.
|
Defined below.
|
||||||
* `sumologic` - (Optional) A Sumologic endpoint to send streaming logs too.
|
* `sumologic` - (Optional) A Sumologic endpoint to send streaming logs too.
|
||||||
Defined below.
|
Defined below.
|
||||||
|
* `gcslogging` - (Optional) A gcs endpoint to send streaming logs too.
|
||||||
|
Defined below.
|
||||||
* `response_object` - (Optional) Allows you to create synthetic responses that exist entirely on the varnish machine. Useful for creating error or maintenance pages that exists outside the scope of your datacenter. Best when used with Condition objects.
|
* `response_object` - (Optional) Allows you to create synthetic responses that exist entirely on the varnish machine. Useful for creating error or maintenance pages that exists outside the scope of your datacenter. Best when used with Condition objects.
|
||||||
* `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
|
||||||
|
@ -326,6 +328,22 @@ The `sumologic` block supports:
|
||||||
* `response_condition` - (Optional) Name of already defined `condition` to apply. This `condition` must be of type `RESPONSE`. For detailed information about Conditionals, see [Fastly's Documentation on Conditionals][fastly-conditionals].
|
* `response_condition` - (Optional) Name of already defined `condition` to apply. This `condition` must be of type `RESPONSE`. For detailed information about Conditionals, see [Fastly's Documentation on Conditionals][fastly-conditionals].
|
||||||
* `message_type` - (Optional) How the message should be formatted. One of: classic, loggly, logplex, blank. See [Fastly's Documentation on Sumologic][fastly-sumologic]
|
* `message_type` - (Optional) How the message should be formatted. One of: classic, loggly, logplex, blank. See [Fastly's Documentation on Sumologic][fastly-sumologic]
|
||||||
|
|
||||||
|
The `gcslogging` block supports:
|
||||||
|
|
||||||
|
* `name` - (Required) A unique name to identify this GCS endpoint.
|
||||||
|
* `email` - (Required) The email address associated with the target GCS bucket on your account.
|
||||||
|
* `bucket_name` - (Required) The name of the bucket in which to store the logs.
|
||||||
|
* `secret_key` - (Required) The secret key associated with the target gcs bucket on your account.
|
||||||
|
* `path` - (Optional) Path to store the files. Must end with a trailing slash.
|
||||||
|
If this field is left empty, the files will be saved in the bucket's root path.
|
||||||
|
* `period` - (Optional) How frequently the logs should be transferred, in
|
||||||
|
seconds. Default `3600`.
|
||||||
|
* `gzip_level` - (Optional) Level of GZIP compression, from `0-9`. `0` is no
|
||||||
|
compression. `1` is fastest and least compressed, `9` is slowest and most
|
||||||
|
compressed. Default `0`.
|
||||||
|
* `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`)
|
||||||
|
* `response_condition` - (Optional) Name of already defined `condition` to apply. This `condition` must be of type `RESPONSE`. For detailed information about Conditionals, see [Fastly's Documentation on Conditionals][fastly-conditionals].
|
||||||
|
|
||||||
The `response_object` block supports:
|
The `response_object` block supports:
|
||||||
|
|
||||||
* `name` - (Required) A unique name to identify this Response Object.
|
* `name` - (Required) A unique name to identify this Response Object.
|
||||||
|
@ -369,3 +387,4 @@ Service.
|
||||||
[fastly-cname]: https://docs.fastly.com/guides/basic-setup/adding-cname-records
|
[fastly-cname]: https://docs.fastly.com/guides/basic-setup/adding-cname-records
|
||||||
[fastly-conditionals]: https://docs.fastly.com/guides/conditions/using-conditions
|
[fastly-conditionals]: https://docs.fastly.com/guides/conditions/using-conditions
|
||||||
[fastly-sumologic]: https://docs.fastly.com/api/logging#logging_sumologic
|
[fastly-sumologic]: https://docs.fastly.com/api/logging#logging_sumologic
|
||||||
|
[fastly-gcs]: https://docs.fastly.com/api/logging#logging_gcs
|
||||||
|
|
Loading…
Reference in New Issue