Skip to content

Commit

Permalink
feat: vcl_snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
Integralist committed Apr 17, 2024
1 parent 772be21 commit c7d022f
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 0 deletions.
121 changes: 121 additions & 0 deletions fastly/data_source_vcl_snippets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package fastly

import (
"context"
"encoding/json"
"log"
"strconv"

gofastly "github.com/fastly/go-fastly/v9/fastly"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/fastly/terraform-provider-fastly/fastly/hashcode"
)

func dataSourceFastlyVCLSnippets() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceFastlyVCLSnippetsRead,
Schema: map[string]*schema.Schema{
"service_id": {
Type: schema.TypeString,
Required: true,
Description: "Alphanumeric string identifying the service.",
},
"service_version": {
Type: schema.TypeInt,
Required: true,
Description: "Integer identifying a service version.",
},
"vcl_snippets": {
Type: schema.TypeSet,
Computed: true,
Description: "List of all VCL snippets for the version of the service.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"content": {
Type: schema.TypeString,
Computed: true,
Description: "The VCL code that specifies exactly what the snippet does.",
},
"id": {
Type: schema.TypeString,
Computed: true,
Description: "Alphanumeric string identifying a VCL Snippet.",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "The name for the snippet. ",
},
"priority": {
Type: schema.TypeInt,
Computed: true,
Description: "Priority determines execution order. Lower numbers execute first.",
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: "The location in generated VCL where the snippet should be placed.",
},
},
},
},
},
}
}

func dataSourceFastlyVCLSnippetsRead(_ context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
conn := meta.(*APIClient).conn

log.Printf("[DEBUG] Reading VCL snippets")

remoteState, err := conn.ListSnippets(&gofastly.ListSnippetsInput{
ServiceID: d.Get("service_id").(string),
ServiceVersion: d.Get("service_version").(int),
})
if err != nil {
return diag.Errorf("error fetching VCL snippets: %s", err)
}

hashBase, _ := json.Marshal(remoteState)
hashString := strconv.Itoa(hashcode.String(string(hashBase)))
d.SetId(hashString)

if err := d.Set("vcl_snippets", flattenDataSourceVCLSnippets(remoteState)); err != nil {
return diag.Errorf("error setting vcl_snippets: %s", err)
}

return nil
}

// flattenDataSourceVCLSnippets models data into format suitable for saving to
// Terraform state.
func flattenDataSourceVCLSnippets(remoteState []*gofastly.Snippet) []map[string]any {
result := make([]map[string]any, len(remoteState))
if len(remoteState) == 0 {
return result
}

for i, resource := range remoteState {
result[i] = map[string]any{}

if resource.Content != nil {
result[i]["content"] = *resource.Content
}
if resource.SnippetID != nil {
result[i]["id"] = *resource.SnippetID
}
if resource.Name != nil {
result[i]["name"] = *resource.Name
}
if resource.Priority != nil {
result[i]["priority"] = *resource.Priority
}
if resource.Type != nil {
result[i]["type"] = *resource.Type
}
}

return result
}
101 changes: 101 additions & 0 deletions fastly/data_source_vcl_snippets_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package fastly

import (
"fmt"
"strconv"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccFastlyDataSourceVCLSnippets_Config(t *testing.T) {
h := generateHex()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccFastlyDataSourceVCLSnippetsConfig(h),
Check: resource.ComposeTestCheckFunc(
func(s *terraform.State) error {
r := s.RootModule().Resources["data.fastly_vcl_snippets.example"]
a := r.Primary.Attributes

snippets, err := strconv.Atoi(a["vcl_snippets.#"])
if err != nil {
return err
}

if snippets != 3 {
return fmt.Errorf("expected three snippets to be returned (as per the config)")
}

// NOTE: API doesn't guarantee order.
for i := 0; i < 3; i++ {
var found bool
for _, d := range generateNames(h, 3) {
if a[fmt.Sprintf("vcl_snippets.%d.name", i)] == d {
found = true
break
}
}
if !found {
want := fmt.Sprintf("tf_%s_%d", h, i+1)
return fmt.Errorf("expected: %s", want)
}
}

return nil
},
),
},
},
})
}

func testAccFastlyDataSourceVCLSnippetsConfig(h string) string {
tf := `
resource "fastly_service_vcl" "example" {
name = "tf_example_service_for_vcl_snippets_data_source"
domain {
name = "%s.com"
}
snippet {
name = "tf_%s_1"
content = "# EXAMPLE 1"
type = "init"
priority = 1
}
snippet {
name = "tf_%s_2"
content = "# EXAMPLE 2"
type = "init"
priority = 2
}
snippet {
name = "tf_%s_3"
content = "# EXAMPLE 3"
type = "init"
priority = 3
}
force_destroy = true
}
data "fastly_vcl_snippets" "example" {
depends_on = [fastly_service_vcl.example]
service_id = fastly_service_vcl.example.id
service_version = fastly_service_vcl.example.active_version
}
`

return fmt.Sprintf(tf, h, h, h, h)
}
1 change: 1 addition & 0 deletions fastly/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func Provider() *schema.Provider {
"fastly_tls_private_key_ids": dataSourceFastlyTLSPrivateKeyIDs(),
"fastly_tls_subscription": dataSourceFastlyTLSSubscription(),
"fastly_tls_subscription_ids": dataSourceFastlyTLSSubscriptionIDs(),
"fastly_vcl_snippets": dataSourceFastlyVCLSnippets(),
"fastly_waf_rules": dataSourceFastlyWAFRules(),
},
ResourcesMap: map[string]*schema.Resource{
Expand Down

0 comments on commit c7d022f

Please sign in to comment.