provider/fastly: Add support for Cache Settings (#6781)
* provider/fastly: Add cache settings Docs, tests, and implementation for Cache Settings support
This commit is contained in:
parent
b20744b133
commit
9437912d3f
|
@ -21,6 +21,9 @@ func resourceServiceV1() *schema.Resource {
|
||||||
Read: resourceServiceV1Read,
|
Read: resourceServiceV1Read,
|
||||||
Update: resourceServiceV1Update,
|
Update: resourceServiceV1Update,
|
||||||
Delete: resourceServiceV1Delete,
|
Delete: resourceServiceV1Delete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
State: schema.ImportStatePassthrough,
|
||||||
|
},
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"name": &schema.Schema{
|
"name": &schema.Schema{
|
||||||
|
@ -193,6 +196,43 @@ func resourceServiceV1() *schema.Resource {
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"cache_setting": &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: "A name to refer to this Cache Setting",
|
||||||
|
},
|
||||||
|
"cache_condition": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Condition to check if this Cache Setting applies",
|
||||||
|
},
|
||||||
|
"action": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "Action to take",
|
||||||
|
},
|
||||||
|
// optional
|
||||||
|
"stale_ttl": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Description: "Max 'Time To Live' for stale (unreachable) objects.",
|
||||||
|
Default: 300,
|
||||||
|
},
|
||||||
|
"ttl": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Description: "The 'Time To Live' for the object",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
"gzip": &schema.Schema{
|
"gzip": &schema.Schema{
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -560,6 +600,7 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
|
||||||
"s3logging",
|
"s3logging",
|
||||||
"condition",
|
"condition",
|
||||||
"request_setting",
|
"request_setting",
|
||||||
|
"cache_setting",
|
||||||
"vcl",
|
"vcl",
|
||||||
} {
|
} {
|
||||||
if d.HasChange(v) {
|
if d.HasChange(v) {
|
||||||
|
@ -1020,6 +1061,7 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find differences in VCLs
|
// Find differences in VCLs
|
||||||
if d.HasChange("vcl") {
|
if d.HasChange("vcl") {
|
||||||
// Note: as above with Gzip and S3 logging, we don't utilize the PUT
|
// Note: as above with Gzip and S3 logging, we don't utilize the PUT
|
||||||
|
@ -1086,6 +1128,56 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find differences in Cache Settings
|
||||||
|
if d.HasChange("cache_setting") {
|
||||||
|
oc, nc := d.GetChange("cache_setting")
|
||||||
|
if oc == nil {
|
||||||
|
oc = new(schema.Set)
|
||||||
|
}
|
||||||
|
if nc == nil {
|
||||||
|
nc = new(schema.Set)
|
||||||
|
}
|
||||||
|
|
||||||
|
ocs := oc.(*schema.Set)
|
||||||
|
ncs := nc.(*schema.Set)
|
||||||
|
|
||||||
|
remove := ocs.Difference(ncs).List()
|
||||||
|
add := ncs.Difference(ocs).List()
|
||||||
|
|
||||||
|
// Delete removed Cache Settings
|
||||||
|
for _, dRaw := range remove {
|
||||||
|
df := dRaw.(map[string]interface{})
|
||||||
|
opts := gofastly.DeleteCacheSettingInput{
|
||||||
|
Service: d.Id(),
|
||||||
|
Version: latestVersion,
|
||||||
|
Name: df["name"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Fastly Cache Settings removal opts: %#v", opts)
|
||||||
|
err := conn.DeleteCacheSetting(&opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST new Cache Settings
|
||||||
|
for _, dRaw := range add {
|
||||||
|
opts, err := buildCacheSetting(dRaw.(map[string]interface{}))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[DEBUG] Error building Cache Setting: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.Service = d.Id()
|
||||||
|
opts.Version = latestVersion
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Fastly Cache Settings Addition opts: %#v", opts)
|
||||||
|
_, err = conn.CreateCacheSetting(opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validate version
|
// validate version
|
||||||
log.Printf("[DEBUG] Validating Fastly Service (%s), Version (%s)", d.Id(), latestVersion)
|
log.Printf("[DEBUG] Validating Fastly Service (%s), Version (%s)", d.Id(), latestVersion)
|
||||||
valid, msg, err := conn.ValidateVersion(&gofastly.ValidateVersionInput{
|
valid, msg, err := conn.ValidateVersion(&gofastly.ValidateVersionInput{
|
||||||
|
@ -1282,6 +1374,7 @@ func resourceServiceV1Read(d *schema.ResourceData, meta interface{}) error {
|
||||||
if err := d.Set("request_setting", rl); err != nil {
|
if err := d.Set("request_setting", rl); err != nil {
|
||||||
log.Printf("[WARN] Error setting Request Settings for (%s): %s", d.Id(), err)
|
log.Printf("[WARN] Error setting Request Settings for (%s): %s", d.Id(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh VCLs
|
// refresh VCLs
|
||||||
log.Printf("[DEBUG] Refreshing VCLs for (%s)", d.Id())
|
log.Printf("[DEBUG] Refreshing VCLs for (%s)", d.Id())
|
||||||
vclList, err := conn.ListVCLs(&gofastly.ListVCLsInput{
|
vclList, err := conn.ListVCLs(&gofastly.ListVCLsInput{
|
||||||
|
@ -1298,6 +1391,22 @@ func resourceServiceV1Read(d *schema.ResourceData, meta interface{}) error {
|
||||||
log.Printf("[WARN] Error setting VCLs for (%s): %s", d.Id(), err)
|
log.Printf("[WARN] Error setting VCLs for (%s): %s", d.Id(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// refresh Cache Settings
|
||||||
|
log.Printf("[DEBUG] Refreshing Cache Settings for (%s)", d.Id())
|
||||||
|
cslList, err := conn.ListCacheSettings(&gofastly.ListCacheSettingsInput{
|
||||||
|
Service: d.Id(),
|
||||||
|
Version: s.ActiveVersion.Number,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[ERR] Error looking up Cache Settings for (%s), version (%s): %s", d.Id(), s.ActiveVersion.Number, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
csl := flattenCacheSettings(cslList)
|
||||||
|
|
||||||
|
if err := d.Set("cache_setting", csl); err != nil {
|
||||||
|
log.Printf("[WARN] Error setting Cache Settings for (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[DEBUG] Active Version for Service (%s) is empty, no state to refresh", d.Id())
|
log.Printf("[DEBUG] Active Version for Service (%s) is empty, no state to refresh", d.Id())
|
||||||
}
|
}
|
||||||
|
@ -1497,6 +1606,31 @@ func buildHeader(headerMap interface{}) (*gofastly.CreateHeaderInput, error) {
|
||||||
return &opts, nil
|
return &opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildCacheSetting(cacheMap interface{}) (*gofastly.CreateCacheSettingInput, error) {
|
||||||
|
df := cacheMap.(map[string]interface{})
|
||||||
|
opts := gofastly.CreateCacheSettingInput{
|
||||||
|
Name: df["name"].(string),
|
||||||
|
StaleTTL: uint(df["stale_ttl"].(int)),
|
||||||
|
CacheCondition: df["cache_condition"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := df["ttl"]; ok {
|
||||||
|
opts.TTL = uint(v.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
act := strings.ToLower(df["action"].(string))
|
||||||
|
switch act {
|
||||||
|
case "cache":
|
||||||
|
opts.Action = gofastly.CacheSettingActionCache
|
||||||
|
case "pass":
|
||||||
|
opts.Action = gofastly.CacheSettingActionPass
|
||||||
|
case "restart":
|
||||||
|
opts.Action = gofastly.CacheSettingActionRestart
|
||||||
|
}
|
||||||
|
|
||||||
|
return &opts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func flattenGzips(gzipsList []*gofastly.Gzip) []map[string]interface{} {
|
func flattenGzips(gzipsList []*gofastly.Gzip) []map[string]interface{} {
|
||||||
var gl []map[string]interface{}
|
var gl []map[string]interface{}
|
||||||
for _, g := range gzipsList {
|
for _, g := range gzipsList {
|
||||||
|
@ -1662,6 +1796,32 @@ func buildRequestSetting(requestSettingMap interface{}) (*gofastly.CreateRequest
|
||||||
|
|
||||||
return &opts, nil
|
return &opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flattenCacheSettings(csList []*gofastly.CacheSetting) []map[string]interface{} {
|
||||||
|
var csl []map[string]interface{}
|
||||||
|
for _, cl := range csList {
|
||||||
|
// Convert Cache Settings to a map for saving to state.
|
||||||
|
clMap := map[string]interface{}{
|
||||||
|
"name": cl.Name,
|
||||||
|
"action": cl.Action,
|
||||||
|
"cache_condition": cl.CacheCondition,
|
||||||
|
"stale_ttl": cl.StaleTTL,
|
||||||
|
"ttl": cl.TTL,
|
||||||
|
}
|
||||||
|
|
||||||
|
// prune any empty values that come from the default string value in structs
|
||||||
|
for k, v := range clMap {
|
||||||
|
if v == "" {
|
||||||
|
delete(clMap, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
csl = append(csl, clMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
return csl
|
||||||
|
}
|
||||||
|
|
||||||
func flattenVCLs(vclList []*gofastly.VCL) []map[string]interface{} {
|
func flattenVCLs(vclList []*gofastly.VCL) []map[string]interface{} {
|
||||||
var vl []map[string]interface{}
|
var vl []map[string]interface{}
|
||||||
for _, vcl := range vclList {
|
for _, vcl := range vclList {
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
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 TestAccFastlyServiceV1CacheSetting_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))
|
||||||
|
|
||||||
|
cq1 := gofastly.CacheSetting{
|
||||||
|
Name: "alt_backend",
|
||||||
|
Action: "pass",
|
||||||
|
StaleTTL: uint(3600),
|
||||||
|
CacheCondition: "serve_alt_backend",
|
||||||
|
}
|
||||||
|
|
||||||
|
cq2 := gofastly.CacheSetting{
|
||||||
|
Name: "cache_backend",
|
||||||
|
Action: "restart",
|
||||||
|
StaleTTL: uint(1600),
|
||||||
|
CacheCondition: "cache_alt_backend",
|
||||||
|
TTL: uint(300),
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckServiceV1Destroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccServiceV1CacheSetting(name, domainName1),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
|
||||||
|
testAccCheckFastlyServiceV1CacheSettingsAttributes(&service, []*gofastly.CacheSetting{&cq1}),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"fastly_service_v1.foo", "name", name),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"fastly_service_v1.foo", "cache_setting.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"fastly_service_v1.foo", "condition.#", "1"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccServiceV1CacheSetting_update(name, domainName1),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckServiceV1Exists("fastly_service_v1.foo", &service),
|
||||||
|
testAccCheckFastlyServiceV1CacheSettingsAttributes(&service, []*gofastly.CacheSetting{&cq1, &cq2}),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"fastly_service_v1.foo", "cache_setting.#", "2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"fastly_service_v1.foo", "condition.#", "2"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckFastlyServiceV1CacheSettingsAttributes(service *gofastly.ServiceDetail, rqs []*gofastly.CacheSetting) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
|
||||||
|
conn := testAccProvider.Meta().(*FastlyClient).conn
|
||||||
|
rqList, err := conn.ListCacheSettings(&gofastly.ListCacheSettingsInput{
|
||||||
|
Service: service.ID,
|
||||||
|
Version: service.ActiveVersion.Number,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[ERR] Error looking up Request Setting for (%s), version (%s): %s", service.Name, service.ActiveVersion.Number, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rqList) != len(rqs) {
|
||||||
|
return fmt.Errorf("Request Setting List count mismatch, expected (%d), got (%d)", len(rqs), len(rqList))
|
||||||
|
}
|
||||||
|
|
||||||
|
var found int
|
||||||
|
for _, r := range rqs {
|
||||||
|
for _, lr := range rqList {
|
||||||
|
if r.Name == lr.Name {
|
||||||
|
// we don't know these things ahead of time, so populate them now
|
||||||
|
r.ServiceID = service.ID
|
||||||
|
r.Version = service.ActiveVersion.Number
|
||||||
|
if !reflect.DeepEqual(r, lr) {
|
||||||
|
return fmt.Errorf("Bad match Request Setting match, expected (%#v), got (%#v)", r, lr)
|
||||||
|
}
|
||||||
|
found++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found != len(rqs) {
|
||||||
|
return fmt.Errorf("Error matching Request Setting rules (%d/%d)", found, len(rqs))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccServiceV1CacheSetting(name, domain string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "fastly_service_v1" "foo" {
|
||||||
|
name = "%s"
|
||||||
|
|
||||||
|
domain {
|
||||||
|
name = "%s"
|
||||||
|
comment = "demo"
|
||||||
|
}
|
||||||
|
|
||||||
|
backend {
|
||||||
|
address = "tftesting.tftesting.net.s3-website-us-west-2.amazonaws.com"
|
||||||
|
name = "AWS S3 hosting"
|
||||||
|
port = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
backend {
|
||||||
|
address = "tftestingother.tftesting.net.s3-website-us-west-2.amazonaws.com"
|
||||||
|
name = "OtherAWSS3hosting"
|
||||||
|
port = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
name = "serve_alt_backend"
|
||||||
|
type = "CACHE"
|
||||||
|
priority = 10
|
||||||
|
statement = "req.url ~ \"^/alt/\""
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_setting {
|
||||||
|
name = "alt_backend"
|
||||||
|
stale_ttl = 3600
|
||||||
|
cache_condition = "serve_alt_backend"
|
||||||
|
action = "pass"
|
||||||
|
}
|
||||||
|
|
||||||
|
default_host = "tftesting.tftesting.net.s3-website-us-west-2.amazonaws.com"
|
||||||
|
|
||||||
|
force_destroy = true
|
||||||
|
}`, name, domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccServiceV1CacheSetting_update(name, domain string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "fastly_service_v1" "foo" {
|
||||||
|
name = "%s"
|
||||||
|
|
||||||
|
domain {
|
||||||
|
name = "%s"
|
||||||
|
comment = "demo"
|
||||||
|
}
|
||||||
|
|
||||||
|
backend {
|
||||||
|
address = "tftesting.tftesting.net.s3-website-us-west-2.amazonaws.com"
|
||||||
|
name = "AWS S3 hosting"
|
||||||
|
port = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
backend {
|
||||||
|
address = "tftestingother.tftesting.net.s3-website-us-west-2.amazonaws.com"
|
||||||
|
name = "OtherAWSS3hosting"
|
||||||
|
port = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
name = "serve_alt_backend"
|
||||||
|
type = "CACHE"
|
||||||
|
priority = 10
|
||||||
|
statement = "req.url ~ \"^/alt/\""
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
name = "cache_alt_backend"
|
||||||
|
type = "CACHE"
|
||||||
|
priority = 20
|
||||||
|
statement = "req.url ~ \"^/cache/\""
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_setting {
|
||||||
|
name = "alt_backend"
|
||||||
|
stale_ttl = 3600
|
||||||
|
cache_condition = "serve_alt_backend"
|
||||||
|
action = "pass"
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_setting {
|
||||||
|
name = "cache_backend"
|
||||||
|
stale_ttl = 1600
|
||||||
|
cache_condition = "cache_alt_backend"
|
||||||
|
action = "restart"
|
||||||
|
ttl = 300
|
||||||
|
}
|
||||||
|
|
||||||
|
default_host = "tftesting.tftesting.net.s3-website-us-west-2.amazonaws.com"
|
||||||
|
|
||||||
|
force_destroy = true
|
||||||
|
}`, name, domain)
|
||||||
|
}
|
|
@ -134,6 +134,8 @@ Service. Defined below
|
||||||
Defined below
|
Defined below
|
||||||
* `condition` - (Optional) A set of conditions to add logic to any basic
|
* `condition` - (Optional) A set of conditions to add logic to any basic
|
||||||
configuration object in this service. Defined below
|
configuration object in this service. Defined below
|
||||||
|
* `cache_setting` - (Optional) A set of Cache Settings, allowing you to override
|
||||||
|
when an item is not to be cached based on an above `condition`. Defined below
|
||||||
* `gzip` - (Required) A set of gzip rules to control automatic gzipping of
|
* `gzip` - (Required) A set of gzip rules to control automatic gzipping of
|
||||||
content. Defined below
|
content. Defined below
|
||||||
* `header` - (Optional) A set of Headers to manipulate for each request. Defined
|
* `header` - (Optional) A set of Headers to manipulate for each request. Defined
|
||||||
|
@ -187,6 +189,17 @@ conditions execute. Lower numbers execute first
|
||||||
* `type` - (Required) Type of the condition, either `REQUEST` (req), `RESPONSE`
|
* `type` - (Required) Type of the condition, either `REQUEST` (req), `RESPONSE`
|
||||||
(req, resp), or `CACHE` (req, beresp)
|
(req, resp), or `CACHE` (req, beresp)
|
||||||
|
|
||||||
|
The `cache_setting` block supports:
|
||||||
|
|
||||||
|
* `name` - (Required) A unique name to label this Cache Setting
|
||||||
|
* `action` - (Required) One of `cache`, `pass`, or `restart`, as defined
|
||||||
|
on Fastly's documenation under ["Caching action descriptions"](https://docs.fastly.com/guides/performance-tuning/controlling-caching#caching-action-descriptions)
|
||||||
|
* `cache_condition` - (Required) Name of the condition used to test whether this settings object should be used.
|
||||||
|
This Condition must be of type `CACHE`
|
||||||
|
* `stale_ttl` - (Optional) Max "Time To Live" for stale (unreachable) objects.
|
||||||
|
Default `300`
|
||||||
|
* `ttl` - (Optional) The "Time To Live" for the object
|
||||||
|
|
||||||
The `gzip` block supports:
|
The `gzip` block supports:
|
||||||
|
|
||||||
* `name` - (Required) A unique name
|
* `name` - (Required) A unique name
|
||||||
|
|
Loading…
Reference in New Issue