Skip to content

Commit

Permalink
feat(datasource/sites): support sites list (#160)
Browse files Browse the repository at this point in the history
* fix merge conflict

* feat(data-source/sites): allow filtering of sites by name/display_name

* build(make): support local testing of provider

* docs: remove FIXME as it is expected, after doing some local testing

* fix(lint): remove genID as it's no longer used

* omit bin directory
  • Loading branch information
Integralist authored Apr 17, 2023
1 parent 2f7a101 commit 2e4f25c
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ override.tf.json
terraform-provider-sigsci

dist/
bin/
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
clean:
rm -rf ./bin

build:
go build -o terraform-provider-sigsci
build: clean
go build -o bin/terraform-provider-sigsci
@sh -c "'$(CURDIR)/scripts/generate-dev-overrides.sh'"

check:
terraform init
terraform plan

.PHONY: all
all: build check

lint:
Expand All @@ -23,4 +27,4 @@ sweep:
docs:
go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs && tfplugindocs generate

.PHONY: docs
.PHONY: clean docs test
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,6 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/signalsciences/go-sigsci v0.1.13 h1:S8YVQ7ei0hybgWqGj0krle6GkA7l8k23VFgNP3ipQwc=
github.com/signalsciences/go-sigsci v0.1.13/go.mod h1:CXwoXk81ZwFdne6o8cnAYwxvke5kcLg7zE6Bl/e1KUo=
github.com/signalsciences/go-sigsci v0.1.14 h1:a2ucWDWDjXn93NXrVBcd7zyOMjxUcPEznTpCg0CLB+g=
github.com/signalsciences/go-sigsci v0.1.14/go.mod h1:CXwoXk81ZwFdne6o8cnAYwxvke5kcLg7zE6Bl/e1KUo=
github.com/signalsciences/go-sigsci v0.1.15 h1:Z1Wkli5NtN8OsvBBWBgXRS0LpAsmVrl1dgCPqFrKglo=
github.com/signalsciences/go-sigsci v0.1.15/go.mod h1:CXwoXk81ZwFdne6o8cnAYwxvke5kcLg7zE6Bl/e1KUo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
Expand Down
213 changes: 213 additions & 0 deletions provider/datasource_sites.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package provider

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/signalsciences/go-sigsci"
)

func dataSourceSites() *schema.Resource {
return &schema.Resource{
Read: readSites,
Schema: map[string]*schema.Schema{
"filter": {
Type: schema.TypeString,
Optional: true,
Description: "Filter listed domains by either the site 'name' or 'display_name'",
},
"sites": {
Type: schema.TypeList,
Computed: true,
Description: "A list of all sites for a given corp.",
Elem: &schema.Resource{
// NOTE: The API returns multiple objects with a single 'uri' field.
// To avoid extra type complexity we flatten those hierarchies.
// These are the fields below that have the '_uri' suffix.
Schema: map[string]*schema.Schema{
"agent_anon_mode": {
Type: schema.TypeString,
Computed: true,
Description: "Agent IP anonimization mode - 'EU' or 'off'",
},
"agent_level": {
Type: schema.TypeString,
Computed: true,
Description: "Agent action level - 'block', 'log' or 'off'",
},
"agents_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's agents",
},
"alerts_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's alerts",
},
"analytics_events_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's analytics events",
},
"blacklist_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's blacklist",
},
"block_duration_secs": {
Type: schema.TypeInt,
Computed: true,
Description: "Duration to block an IP in seconds",
},
"block_http_code": {
Type: schema.TypeInt,
Computed: true,
Description: "HTTP response code to send when when traffic is being blocked",
},
"block_redirect_url": {
Type: schema.TypeString,
Computed: true,
Description: "URL to redirect to when blockHTTPCode is 301 or 302",
},
"created": {
Type: schema.TypeString,
Computed: true,
Description: "Created RFC3339 date time",
},
"display_name": {
Type: schema.TypeString,
Computed: true,
Description: "Display name of the site",
},
"events_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's events",
},
"header_links_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's header links",
},
"integrations_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's integrations",
},
"members_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's members",
},
"monitors_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's monitors",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Identifying name of the site",
},
"redactions_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's redactions",
},
"requests_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's requests",
},
"suspicious_ips_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's suspicious IPs",
},
"top_attacks_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's top attacks",
},
"whitelist_uri": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the site's whitelist",
},
},
},
},
},
}
}

func readSites(d *schema.ResourceData, m any) error {
pm := m.(providerMetadata)
sc := pm.Client
corp := pm.Corp

// API documentation:
// https://docs.fastly.com/signalsciences/api/#_corps__corpName__sites_get
sites, err := sc.ListSites(corp)
if err != nil {
return err
}

d.SetId("list_sites")

filter := d.Get("filter").(string)

return d.Set("sites", flattenSites(sites, filter))
}

// flattenSites models data into format suitable for saving to Terraform state.
func flattenSites(data []sigsci.Site, filter string) []map[string]any {
results := []map[string]any{}
if len(data) == 0 {
return results
}

for _, site := range data {
data := map[string]any{
"agent_anon_mode": site.AgentAnonMode,
"agent_level": site.AgentLevel,
"agents_uri": site.Agents["uri"],
"alerts_uri": site.Alerts["uri"],
"analytics_events_uri": site.AnalyticsEvents["uri"],
"blacklist_uri": site.Blacklist["uri"],
"block_duration_secs": site.BlockDurationSeconds,
"block_http_code": site.BlockHTTPCode,
"block_redirect_url": site.BlockRedirectURL,
"created": site.Created.String(),
"display_name": site.DisplayName,
"events_uri": site.Events["uri"],
"header_links_uri": site.HeaderLinks["uri"],
"integrations_uri": site.Integrations["uri"],
"members_uri": site.Members["uri"],
"monitors_uri": site.Monitors["uri"],
"name": site.Name,
"redactions_uri": site.Redactions["uri"],
"requests_uri": site.Requests["uri"],
"suspicious_ips_uri": site.SuspiciousIPs["uri"],
"top_attacks_uri": site.TopAttacks["uri"],
"whitelist_uri": site.Whitelist["uri"],
}

// Prune any empty values that come from the default string value in structs.
for k, v := range data {
if v == "" {
delete(data, k)
}
}
results = append(results, data)
}

if filter != "" {
for idx, site := range results {
if site["name"] == filter || site["display_name"] == filter {
return results[idx : idx+1]
}
}
}

return results
}
63 changes: 63 additions & 0 deletions provider/datasource_sites_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package provider

import (
"fmt"
"strconv"
"testing"

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

func TestAccSigSciDataSourceSites(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: `
resource "sigsci_site" "example1" {
short_name = "terraform_site1"
display_name = "terraform test example site1"
}
resource "sigsci_site" "example2" {
short_name = "terraform_site2"
display_name = "terraform test example site2"
}
data "sigsci_sites" "example" {
depends_on = [sigsci_site.example1, sigsci_site.example2]
filter = "terraform_site2"
}
`,
Check: resource.ComposeTestCheckFunc(
func(s *terraform.State) error {
r := s.RootModule().Resources["data.sigsci_sites.example"]
a := r.Primary.Attributes

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

if sites != 1 {
return fmt.Errorf("expected one site to be returned as per the filter")
}

got := a["sites.0.name"]
want := "terraform_site2"
if got != want {
return fmt.Errorf("got: %s, want: %s", got, want)
}

return nil
},
),
ExpectNonEmptyPlan: true,
},
},
})
}
9 changes: 4 additions & 5 deletions provider/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func expandStringArray(entries *schema.Set) []string {
}

func flattenDetections(detections []sigsci.Detection) []interface{} {
var detectionsSet = make([]interface{}, len(detections))
detectionsSet := make([]interface{}, len(detections))
for i, detection := range detections {
fieldSet := make([]interface{}, len(detection.Fields))
for j, field := range detection.Fields {
Expand Down Expand Up @@ -137,7 +137,7 @@ func expandAlerts(entries *schema.Set) []sigsci.Alert {
}

func flattenAlerts(alerts []sigsci.Alert) []interface{} {
var alertsSet = make([]interface{}, len(alerts))
alertsSet := make([]interface{}, len(alerts))
for i, alert := range alerts {
alertsSet[i] = map[string]interface{}{
"id": alert.ID,
Expand Down Expand Up @@ -385,7 +385,7 @@ func expandRuleConditions(conditionsResource *schema.Set) []sigsci.Condition {
}

func flattenRuleConditions(conditions []sigsci.Condition) []interface{} {
var conditionsMap = make([]interface{}, len(conditions))
conditionsMap := make([]interface{}, len(conditions))
for i, condition := range conditions {
conditionMap := map[string]interface{}{
"type": condition.Type,
Expand Down Expand Up @@ -475,7 +475,7 @@ func flattenRuleRateLimit(rateLimit *sigsci.RateLimit) map[string]string {
}

func flattenRuleActions(actions []sigsci.Action, customResponseCode bool) []interface{} {
var actionsMap = make([]interface{}, len(actions))
actionsMap := make([]interface{}, len(actions))
for i, action := range actions {

actionMap := map[string]interface{}{
Expand Down Expand Up @@ -513,7 +513,6 @@ func resourceSiteImport(siteID string) (site string, id string, err error) {
var siteImporter = schema.ResourceImporter{
State: func(d *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) {
site, id, err := resourceSiteImport(d.Id())

if err != nil {
return nil, err
}
Expand Down
3 changes: 3 additions & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ func Provider() terraform.ResourceProvider {
"sigsci_edge_deployment": resourceEdgeDeployment(),
"sigsci_edge_deployment_service": resourceEdgeDeploymentService(),
},
DataSourcesMap: map[string]*schema.Resource{
"sigsci_sites": dataSourceSites(),
},
}
provider.ConfigureFunc = providerConfigure()
return provider
Expand Down
22 changes: 22 additions & 0 deletions scripts/generate-dev-overrides.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

BIN_DIR=$PWD/bin
OVERRIDES_FILENAME=developer_overrides.tfrc

cat <<EOF >$BIN_DIR/$OVERRIDES_FILENAME
provider_installation {
dev_overrides {
"signalsciences/sigsci" = "$BIN_DIR"
}
direct {}
}
EOF

echo ""
echo "A development overrides file has been generated at ./bin/$OVERRIDES_FILENAME."
echo "To make Terraform temporarily use your locally built version of the provider, set TF_CLI_CONFIG_FILE within your terminal"
echo ""
printf "\texport TF_CLI_CONFIG_FILE=$BIN_DIR/$OVERRIDES_FILENAME"
echo ""

0 comments on commit 2e4f25c

Please sign in to comment.