Skip to content

Commit

Permalink
feat(kv_store): support KV Store (#691)
Browse files Browse the repository at this point in the history
* refactor: rename function used across both service types to be generic

* feat(kv_store): add kv_store block

* docs(kv_store): generate documentation

* docs(fastly_service_compute): document kv store feature restriction

* refactor(kv_store): replace block with separate resource

* docs(kv_store): add descriptions for resource_link block

* docs(fastly_kvstore): add examples

* test(fastly_kvstore): add tests with resource_links block validation

* docs: update

* test(fastly_kvstore): validate force_destroy

* fix(kvstore): add ForceNew to name attribute
  • Loading branch information
Integralist authored May 31, 2023
1 parent 774b730 commit 3488948
Show file tree
Hide file tree
Showing 63 changed files with 880 additions and 207 deletions.
73 changes: 73 additions & 0 deletions docs/resources/kvstore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
layout: "fastly"
page_title: "Fastly: kvstore"
sidebar_current: "docs-fastly-resource-kvstore"
description: |-
Provides a persistent, globally consistent key-value store accessible to Compute@Edge services during request processing.
---

# fastly_kvstore

Provides a persistent, globally consistent key-value store accessible to Compute@Edge services during request processing.

-> **Note** The `kv_store` feature does not support seeding the store with data. This is because the size of objects that can be stored is very large and Terraform is designed for containing [configuration, not data](https://developer.fastly.com/learning/integrations/orchestration/terraform/#configuration-not-data). You should use either the [Fastly CLI](https://developer.fastly.com/learning/tools/cli/), [Fastly API](https://developer.fastly.com/reference/api/) or one of the available [Fastly API Clients](https://developer.fastly.com/reference/api/#clients) to populate your KV Store.

## Example Usage

Basic usage:

```terraform
# IMPORTANT: Deleting a KV Store requires first deleting its resource_link.
# This requires a two-step `terraform apply` as we can't guarantee deletion order.
# e.g. resource_link deletion within fastly_service_compute might not finish first.
resource "fastly_kvstore" "example" {
name = "my_kv_store"
}
resource "fastly_service_compute" "example" {
name = "my_compute_service"
domain {
name = "demo.example.com"
}
package {
filename = "package.tar.gz"
source_code_hash = data.fastly_package_hash.example.hash
}
resource_link {
name = "my_resource_link"
resource_id = fastly_kvstore.example.id
}
force_destroy = true
}
data "fastly_package_hash" "example" {
filename = "package.tar.gz"
}
```

## Import

Fastly KV Stores can be imported using their Store ID, e.g.

```sh
$ terraform import fastly_kvstore.example xxxxxxxxxxxxxxxxxxxx
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) A unique name to identify the KV Store. It is important to note that changing this attribute will delete and recreate the KV Store, and discard the current entries.

### Optional

- `force_destroy` (Boolean) Allow the KV store to be deleted, even if it contains entries. Defaults to false.

### Read-Only

- `id` (String) The ID of this resource.
14 changes: 14 additions & 0 deletions docs/resources/service_compute.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ $ terraform import fastly_service_compute.demo xxxxxxxxxxxxxxxxxxxx@2
- `logging_sumologic` (Block Set) (see [below for nested schema](#nestedblock--logging_sumologic))
- `logging_syslog` (Block Set) (see [below for nested schema](#nestedblock--logging_syslog))
- `product_enablement` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--product_enablement))
- `resource_link` (Block Set) A resource link represents a link between a shared resource (such as an KV Store or Config Store) and a service version. (see [below for nested schema](#nestedblock--resource_link))
- `reuse` (Boolean) Services that are active cannot be destroyed. If set to `true` a service Terraform intends to destroy will instead be deactivated (allowing it to be reused by importing it into another Terraform project). If `false`, attempting to destroy an active service will cause an error. Default `false`
- `version_comment` (String) Description field for the version

Expand Down Expand Up @@ -653,3 +654,16 @@ Optional:
Read-Only:

- `name` (String) Used internally by the provider to identify modified settings


<a id="nestedblock--resource_link"></a>
### Nested Schema for `resource_link`

Required:

- `name` (String) The name of the resource link.
- `resource_id` (String) The ID of the underlying linked resource.

Read-Only:

- `link_id` (String) An alphanumeric string identifying the resource link.
1 change: 1 addition & 0 deletions examples/resources/components/kvstore_import_cmd.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import fastly_kvstore.example xxxxxxxxxxxxxxxxxxxx
30 changes: 30 additions & 0 deletions examples/resources/kvstore_basic_usage.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# IMPORTANT: Deleting a KV Store requires first deleting its resource_link.
# This requires a two-step `terraform apply` as we can't guarantee deletion order.
# e.g. resource_link deletion within fastly_service_compute might not finish first.
resource "fastly_kvstore" "example" {
name = "my_kv_store"
}

resource "fastly_service_compute" "example" {
name = "my_compute_service"

domain {
name = "demo.example.com"
}

package {
filename = "package.tar.gz"
source_code_hash = data.fastly_package_hash.example.hash
}

resource_link {
name = "my_resource_link"
resource_id = fastly_kvstore.example.id
}

force_destroy = true
}

data "fastly_package_hash" "example" {
filename = "package.tar.gz"
}
8 changes: 4 additions & 4 deletions fastly/block_fastly_service_acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ func TestAccFastlyServiceVCL_acl(t *testing.T) {
{
Config: testAccServiceVCLConfigACL(name, aclName, domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "a_"+aclName, &aclA),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "b_"+aclName, &aclB),
),
},
{
Config: testAccServiceVCLConfigACL(name, aclNameUpdated, domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "a_"+aclNameUpdated, &aclA),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "b_"+aclNameUpdated, &aclB),
),
Expand All @@ -95,15 +95,15 @@ func TestAccFastlyServiceVCL_acl(t *testing.T) {
{
Config: testAccServiceVCLConfigACLForceDestroy(name, aclNameUpdated, domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "a_"+aclNameUpdated, &aclA),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "b_"+aclNameUpdated, &aclB),
),
},
{
Config: testAccServiceVCLConfigACLForceDestroy(name, aclName, domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "a_"+aclName, &aclA),
testAccCheckFastlyServiceVCLAttributesACL(&service, name, "b_"+aclName, &aclB),
),
Expand Down
4 changes: 2 additions & 2 deletions fastly/block_fastly_service_backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func TestAccFastlyServiceVCLBackend_basic(t *testing.T) {
{
Config: testAccServiceVCLBackend(serviceName, domainName, backendAddress, backendName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", serviceName),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "backend.#", "1"),
testAccCheckFastlyServiceVCLBackendAttributes(&service, []*gofastly.Backend{&b1}),
Expand All @@ -247,7 +247,7 @@ func TestAccFastlyServiceVCLBackend_basic(t *testing.T) {
{
Config: testAccServiceVCLBackendUpdate(serviceName, domainName, backendAddress, backendName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "backend.#", "3"),
testAccCheckFastlyServiceVCLBackendAttributes(&service, []*gofastly.Backend{&b1, &b2, &b3}),
),
Expand Down
4 changes: 2 additions & 2 deletions fastly/block_fastly_service_cachesetting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestAccFastlyServiceVCLCacheSetting_basic(t *testing.T) {
{
Config: testAccServiceVCLCacheSetting(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLCacheSettingsAttributes(&service, []*gofastly.CacheSetting{&cq1}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand All @@ -90,7 +90,7 @@ func TestAccFastlyServiceVCLCacheSetting_basic(t *testing.T) {
{
Config: testAccServiceVCLCacheSettingUpdate(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLCacheSettingsAttributes(&service, []*gofastly.CacheSetting{&cq1, &cq2}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "cache_setting.#", "2"),
Expand Down
4 changes: 2 additions & 2 deletions fastly/block_fastly_service_condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestAccFastlyServiceVCL_conditional_basic(t *testing.T) {
{
Config: testAccServiceVCLConditionConfig(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLConditionalAttributes(&service, name, []*gofastly.Condition{&con1}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand All @@ -84,7 +84,7 @@ func TestAccFastlyServiceVCL_conditional_basic(t *testing.T) {
{
Config: testAccServiceVCLConditionConfigUpdate(name, domainName1, "CACHE"),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLConditionalAttributes(&service, name, []*gofastly.Condition{&con2}),
),
},
Expand Down
10 changes: 5 additions & 5 deletions fastly/block_fastly_service_dictionary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ func TestAccFastlyServiceVCL_dictionary(t *testing.T) {
{
Config: testAccServiceVCLConfigDictionary(name, dictName, backendName, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesDictionary(&service, &dictionary, name, dictName, false),
),
},
{
Config: testAccServiceVCLConfigDictionary(name, updatedDictName, backendName, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesDictionary(&service, &dictionary, name, updatedDictName, false),
),
},
Expand All @@ -91,14 +91,14 @@ func TestAccFastlyServiceVCL_dictionary(t *testing.T) {
{
Config: testAccServiceVCLConfigDictionaryForceDestroy(name, updatedDictName, backendName, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesDictionary(&service, &dictionary, name, updatedDictName, false),
),
},
{
Config: testAccServiceVCLConfigDictionaryForceDestroy(name, dictName, backendName, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesDictionary(&service, &dictionary, name, dictName, false),
),
},
Expand All @@ -124,7 +124,7 @@ func TestAccFastlyServiceVCL_dictionary_write_only(t *testing.T) {
{
Config: testAccServiceVCLConfigDictionaryWriteOnly(name, dictName, backendName, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLAttributesDictionary(&service, &dictionary, name, dictName, true),
),
},
Expand Down
6 changes: 3 additions & 3 deletions fastly/block_fastly_service_director_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func TestAccFastlyServiceVCL_directors_basic(t *testing.T) {
{
Config: testAccServiceVCLDirectorsConfig(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLDirectorsAttributes(&service, []*gofastly.Director{&directorDeveloper, &directorApps}),
testAccCheckFastlyServiceVCLDirectorBackends(&service, []*gofastly.DirectorBackend{&dbDeveloper, &dbApps}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", name),
Expand All @@ -206,7 +206,7 @@ func TestAccFastlyServiceVCL_directors_basic(t *testing.T) {
{
Config: testAccServiceVCLDirectorsConfigUpdate1(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLDirectorsAttributes(&service, []*gofastly.Director{&directorDeveloperUpdated, &directorApps, &directorWWWDemo}),
testAccCheckFastlyServiceVCLDirectorBackends(&service, []*gofastly.DirectorBackend{&dbDeveloperUpdated, &dbApps, &dbWWW, &dbDemo}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", name),
Expand All @@ -217,7 +217,7 @@ func TestAccFastlyServiceVCL_directors_basic(t *testing.T) {
{
Config: testAccServiceVCLDirectorsConfigUpdate2(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLDirectorsAttributes(&service, []*gofastly.Director{&directorApps, &directorWWWDemo2}),
testAccCheckFastlyServiceVCLDirectorBackends(&service, []*gofastly.DirectorBackend{&dbApps, &dbWWW}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", name),
Expand Down
4 changes: 2 additions & 2 deletions fastly/block_fastly_service_dynamicsnippet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestAccFastlyServiceVCLDynamicSnippet_basic(t *testing.T) {
{
Config: testAccServiceVCLDynamicSnippet(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLDynamicSnippetAttributes(&service, []*gofastly.Snippet{&s1}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", name),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "dynamicsnippet.#", "1"),
Expand All @@ -106,7 +106,7 @@ func TestAccFastlyServiceVCLDynamicSnippet_basic(t *testing.T) {
{
Config: testAccServiceVCLDynamicSnippetUpdate(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLDynamicSnippetAttributes(&service, []*gofastly.Snippet{&updatedS1, &updatedS2}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "dynamicsnippet.#", "2"),
resource.TestCheckTypeSetElemNestedAttrs("fastly_service_vcl.foo", "dynamicsnippet.*", map[string]string{
Expand Down
6 changes: 3 additions & 3 deletions fastly/block_fastly_service_gzip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func TestAccFastlyServiceVCL_gzips_basic(t *testing.T) {
{
Config: testAccServiceVCLGzipsConfig(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLGzipsAttributes(&service, []*gofastly.Gzip{&log1, &log2}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand All @@ -120,7 +120,7 @@ func TestAccFastlyServiceVCL_gzips_basic(t *testing.T) {
{
Config: testAccServiceVCLGzipsConfigDeleteCreate(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLGzipsAttributes(&service, []*gofastly.Gzip{&log3}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand All @@ -132,7 +132,7 @@ func TestAccFastlyServiceVCL_gzips_basic(t *testing.T) {
{
Config: testAccServiceVCLGzipsConfigUpdate(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLGzipsAttributes(&service, []*gofastly.Gzip{&log4}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand Down
4 changes: 2 additions & 2 deletions fastly/block_fastly_service_header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func TestAccFastlyServiceVCL_headers_basic(t *testing.T) {
{
Config: testAccServiceVCLHeadersConfig(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLHeaderAttributes(&service, []*gofastly.Header{&log1, &log2}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand All @@ -197,7 +197,7 @@ func TestAccFastlyServiceVCL_headers_basic(t *testing.T) {
{
Config: testAccServiceVCLHeadersConfigUpdate(name, domainName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLHeaderAttributes(&service, []*gofastly.Header{&log1, &log3, &log4}),
resource.TestCheckResourceAttr(
"fastly_service_vcl.foo", "name", name),
Expand Down
4 changes: 2 additions & 2 deletions fastly/block_fastly_service_healthcheck_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func TestAccFastlyServiceVCL_healthcheck_basic(t *testing.T) {
{
Config: testAccServiceVCLHealthCheckConfig(name, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLHealthCheckAttributes(&service, []*gofastly.HealthCheck{&log1}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", name),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "healthcheck.#", "1"),
Expand All @@ -119,7 +119,7 @@ func TestAccFastlyServiceVCL_healthcheck_basic(t *testing.T) {
{
Config: testAccServiceVCLHealthCheckConfigUpdate(name, domainName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceVCLExists("fastly_service_vcl.foo", &service),
testAccCheckServiceExists("fastly_service_vcl.foo", &service),
testAccCheckFastlyServiceVCLHealthCheckAttributes(&service, []*gofastly.HealthCheck{&log1, &log2}),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "name", name),
resource.TestCheckResourceAttr("fastly_service_vcl.foo", "healthcheck.#", "2"),
Expand Down
Loading

0 comments on commit 3488948

Please sign in to comment.