Skip to content

Commit

Permalink
feat(package): make package optional (#733)
Browse files Browse the repository at this point in the history
  • Loading branch information
Integralist authored Aug 7, 2023
1 parent d6ed5eb commit 5c16f56
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 44 deletions.
24 changes: 13 additions & 11 deletions docs/resources/service_compute.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Provides a Fastly Compute@Edge service. Compute@Edge is a computation platform c

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](https://docs.fastly.com/en/guides/adding-cname-records) on their documentation site for guidance.

~> **Note:** If you omit the `package` block, you must set `activate = false` to avoid service validation errors.

## Example Usage

Basic usage:
Expand Down Expand Up @@ -66,7 +68,6 @@ $ terraform import fastly_service_compute.demo xxxxxxxxxxxxxxxxxxxx@2

- `domain` (Block Set, Min: 1) A set of Domain names to serve as entry points for your Service (see [below for nested schema](#nestedblock--domain))
- `name` (String) The unique name for the Service to create
- `package` (Block List, Min: 1, Max: 1) The `package` block supports uploading or modifying Wasm packages for use in a Fastly Compute@Edge service. See Fastly's documentation on [Compute@Edge](https://developer.fastly.com/learning/compute/) (see [below for nested schema](#nestedblock--package))

### Optional

Expand Down Expand Up @@ -101,6 +102,7 @@ $ terraform import fastly_service_compute.demo xxxxxxxxxxxxxxxxxxxx@2
- `logging_splunk` (Block Set) (see [below for nested schema](#nestedblock--logging_splunk))
- `logging_sumologic` (Block Set) (see [below for nested schema](#nestedblock--logging_sumologic))
- `logging_syslog` (Block Set) (see [below for nested schema](#nestedblock--logging_syslog))
- `package` (Block List, Max: 1) The `package` block supports uploading or modifying Wasm packages for use in a Fastly Compute@Edge service (if omitted, ensure `activate = false` is set on `fastly_service_compute` to avoid service validation errors). See Fastly's documentation on [Compute@Edge](https://developer.fastly.com/learning/compute/) (see [below for nested schema](#nestedblock--package))
- `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`
Expand All @@ -126,16 +128,6 @@ Optional:
- `comment` (String) An optional comment about the Domain.


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

Optional:

- `content` (String) The contents of the Wasm deployment package as a base64 encoded string (e.g. could be provided using an input variable or via external data source output variable). Conflicts with `filename`. Exactly one of these two arguments must be specified
- `filename` (String) The path to the Wasm deployment package within your local filesystem. Conflicts with `content`. Exactly one of these two arguments must be specified
- `source_code_hash` (String) Used to trigger updates. Must be set to a SHA512 hash of all files (in sorted order) within the package. The usual way to set this is using the fastly_package_hash data source.


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

Expand Down Expand Up @@ -643,6 +635,16 @@ Optional:
- `use_tls` (Boolean) Whether to use TLS for secure logging. Default `false`


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

Optional:

- `content` (String) The contents of the Wasm deployment package as a base64 encoded string (e.g. could be provided using an input variable or via external data source output variable). Conflicts with `filename`. Exactly one of these two arguments must be specified
- `filename` (String) The path to the Wasm deployment package within your local filesystem. Conflicts with `content`. Exactly one of these two arguments must be specified
- `source_code_hash` (String) Used to trigger updates. Must be set to a SHA512 hash of all files (in sorted order) within the package. The usual way to set this is using the fastly_package_hash data source.


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

Expand Down
33 changes: 21 additions & 12 deletions fastly/base_fastly_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,21 +403,30 @@ func resourceServiceUpdate(ctx context.Context, d *schema.ResourceData, meta any
}
}

// Validate version.
log.Printf("[DEBUG] Validating Fastly Service (%s), Version (%v)", d.Id(), latestVersion)
valid, msg, err := conn.ValidateVersion(&gofastly.ValidateVersionInput{
ServiceID: d.Id(),
ServiceVersion: latestVersion,
})
if err != nil {
return diag.Errorf("error checking validation: %s", err)
}
// Only validate the service if `activate = true`.
// This is primarily for compute services with no package defined.
// The user needs to set `activate = false` to prevent errors.
// As they can't activate a service without a package.
// There's no value showing validation errors to users in 'draft' mode.
if i := d.Get("activate"); i != nil {
if i.(bool) {
// Validate version.
log.Printf("[DEBUG] Validating Fastly Service (%s), Version (%v)", d.Id(), latestVersion)
valid, msg, err := conn.ValidateVersion(&gofastly.ValidateVersionInput{
ServiceID: d.Id(),
ServiceVersion: latestVersion,
})
if err != nil {
return diag.Errorf("error checking validation: %s", err)
}

if !valid {
return diag.Errorf("invalid configuration for Fastly Service (%s): %s", d.Id(), msg)
if !valid {
return diag.Errorf("invalid configuration for Fastly Service (%s): %s", d.Id(), msg)
}
}
}

err = d.Set("cloned_version", latestVersion)
err := d.Set("cloned_version", latestVersion)
if err != nil {
return diag.FromErr(err)
}
Expand Down
5 changes: 2 additions & 3 deletions fastly/block_fastly_service_package.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ func NewServicePackage(sa ServiceMetadata) ServiceAttributeDefinition {
func (h *PackageServiceAttributeHandler) Register(s *schema.Resource) error {
s.Schema[h.GetKey()] = &schema.Schema{
Type: schema.TypeList,
Required: true,
Description: "The `package` block supports uploading or modifying Wasm packages for use in a Fastly Compute@Edge service. See Fastly's documentation on [Compute@Edge](https://developer.fastly.com/learning/compute/)",
Optional: true,
Description: "The `package` block supports uploading or modifying Wasm packages for use in a Fastly Compute@Edge service (if omitted, ensure `activate = false` is set on `fastly_service_compute` to avoid service validation errors). See Fastly's documentation on [Compute@Edge](https://developer.fastly.com/learning/compute/)",
MaxItems: 1,
MinItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"content": {
Expand Down
80 changes: 62 additions & 18 deletions fastly/block_fastly_service_package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccFastlyServiceVCL_package_basic(t *testing.T) {
func TestAccFastlyServiceCompute_package_basic(t *testing.T) {
var service gofastly.ServiceDetail
name01 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
domain01 := fmt.Sprintf("fastly-test.%s.com", name01)
Expand Down Expand Up @@ -49,29 +49,29 @@ func TestAccFastlyServiceVCL_package_basic(t *testing.T) {
CheckDestroy: testAccCheckServiceVCLDestroy,
Steps: []resource.TestStep{
{
Config: testAccServiceVCLPackageConfig(name01, domain01),
Config: testAccServiceComputePackageConfig(name01, domain01),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
testAccCheckFastlyServiceVCLPackageAttributes(&service, &want),
testAccCheckFastlyServiceComputePackageAttributes(&service, &want),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name01),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "1"),
),
},
{
Config: testAccServiceVCLPackageConfig(name02, domain02),
Config: testAccServiceComputePackageConfig(name02, domain02),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
testAccCheckFastlyServiceVCLPackageAttributes(&service, &want),
testAccCheckFastlyServiceComputePackageAttributes(&service, &want),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name02),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "1"),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "active_version", "2"),
),
},
{
Config: testAccServiceVCLPackageConfigNew(name02, domain02),
Config: testAccServiceComputePackageConfigNew(name02, domain02),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
testAccCheckFastlyServiceVCLPackageAttributes(&service, &want2),
testAccCheckFastlyServiceComputePackageAttributes(&service, &want2),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name02),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "1"),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "active_version", "3"),
Expand All @@ -81,7 +81,7 @@ func TestAccFastlyServiceVCL_package_basic(t *testing.T) {
})
}

func TestAccFastlyServiceVCL_package_content(t *testing.T) {
func TestAccFastlyServiceCompute_package_content(t *testing.T) {
validPackageContent, _ := os.ReadFile("test_fixtures/package/valid.tar.gz")
b64Content := base64.StdEncoding.EncodeToString(validPackageContent)

Expand Down Expand Up @@ -124,29 +124,29 @@ func TestAccFastlyServiceVCL_package_content(t *testing.T) {
CheckDestroy: testAccCheckServiceVCLDestroy,
Steps: []resource.TestStep{
{
Config: testAccServiceVCLPackageConfigContent(name01, domain01, b64Content),
Config: testAccServiceComputePackageConfigContent(name01, domain01, b64Content),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
testAccCheckFastlyServiceVCLPackageAttributes(&service, &want),
testAccCheckFastlyServiceComputePackageAttributes(&service, &want),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name01),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "1"),
),
},
{
Config: testAccServiceVCLPackageConfigContent(name02, domain02, b64Content),
Config: testAccServiceComputePackageConfigContent(name02, domain02, b64Content),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
testAccCheckFastlyServiceVCLPackageAttributes(&service, &want),
testAccCheckFastlyServiceComputePackageAttributes(&service, &want),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name02),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "1"),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "active_version", "2"),
),
},
{
Config: testAccServiceVCLPackageConfigContent(name02, domain02, b64Content2),
Config: testAccServiceComputePackageConfigContent(name02, domain02, b64Content2),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
testAccCheckFastlyServiceVCLPackageAttributes(&service, &want2),
testAccCheckFastlyServiceComputePackageAttributes(&service, &want2),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name02),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "1"),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "active_version", "3"),
Expand All @@ -156,7 +156,31 @@ func TestAccFastlyServiceVCL_package_content(t *testing.T) {
})
}

func testAccCheckFastlyServiceVCLPackageAttributes(service *gofastly.ServiceDetail, want *gofastly.Package) resource.TestCheckFunc {
func TestAccFastlyServiceCompute_package_optional(t *testing.T) {
var service gofastly.ServiceDetail
name := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
domain := fmt.Sprintf("fastly-test.%s.com", name)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
ProviderFactories: testAccProviders,
CheckDestroy: testAccCheckServiceVCLDestroy,
Steps: []resource.TestStep{
{
Config: testAccServiceComputePackageOptional(name, domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("fastly_service_compute.foo", &service),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "name", name),
resource.TestCheckResourceAttr("fastly_service_compute.foo", "package.#", "0"),
),
},
},
})
}

func testAccCheckFastlyServiceComputePackageAttributes(service *gofastly.ServiceDetail, want *gofastly.Package) resource.TestCheckFunc {
return func(_ *terraform.State) error {
conn := testAccProvider.Meta().(*APIClient).conn
got, err := conn.GetPackage(&gofastly.GetPackageInput{
Expand Down Expand Up @@ -187,7 +211,7 @@ func testAccCheckFastlyServiceVCLPackageAttributes(service *gofastly.ServiceDeta
}
}

func testAccServiceVCLPackageConfig(name string, domain string) string {
func testAccServiceComputePackageConfig(name string, domain string) string {
return fmt.Sprintf(`
data "fastly_package_hash" "example" {
filename = "./test_fixtures/package/valid.tar.gz"
Expand All @@ -212,7 +236,7 @@ resource "fastly_service_compute" "foo" {
`, name, domain)
}

func testAccServiceVCLPackageConfigNew(name string, domain string) string {
func testAccServiceComputePackageConfigNew(name string, domain string) string {
return fmt.Sprintf(`
data "fastly_package_hash" "example" {
filename = "./test_fixtures/package/valid2.tar.gz"
Expand Down Expand Up @@ -244,7 +268,7 @@ resource "fastly_service_compute" "foo" {
// So instead we had to use `locals` variable as a workaround.
// https://developer.hashicorp.com/terraform/language/values/locals
// The use of `-var` and input variables will work fine with actual TF project.
func testAccServiceVCLPackageConfigContent(name, domain, b64Content string) string {
func testAccServiceComputePackageConfigContent(name, domain, b64Content string) string {
return fmt.Sprintf(`
locals {
package_content = "%s"
Expand All @@ -267,3 +291,23 @@ resource "fastly_service_compute" "foo" {
}
`, b64Content, name, domain)
}

// NOTE: Config must set `activate = false` to avoid validation errors.
// You can't activate a compute service without a package.
func testAccServiceComputePackageOptional(name string, domain string) string {
return fmt.Sprintf(`
resource "fastly_service_compute" "foo" {
name = "%s"
domain {
name = "%s"
comment = "tf-package-test"
}
backend {
address = "aws.amazon.com"
name = "amazon docs"
}
force_destroy = true
activate = false
}
`, name, domain)
}
2 changes: 2 additions & 0 deletions templates/resources/service_compute.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Provides a Fastly Compute@Edge service. Compute@Edge is a computation platform c

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](https://docs.fastly.com/en/guides/adding-cname-records) on their documentation site for guidance.

~> **Note:** If you omit the `package` block, you must set `activate = false` to avoid service validation errors.

## Example Usage

Basic usage:
Expand Down

0 comments on commit 5c16f56

Please sign in to comment.