-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(datasource/sites): support sites list #160
Changes from 5 commits
1c9c345
2b1c2c2
5f56735
13885ca
7b810e8
7402484
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,3 +50,4 @@ override.tf.json | |
terraform-provider-sigsci | ||
|
||
dist/ | ||
bin |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
provider_installation { | ||
|
||
dev_overrides { | ||
"signalsciences/sigsci" = "/Users/integralist/Code/fastly/terraform-provider-sigsci/bin" | ||
} | ||
|
||
direct {} | ||
} |
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", | ||
}, | ||
Comment on lines
+51
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NOTE: The API has a |
||
"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") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously I was dynamically generating a dynamic ID but opted for a static ID as I don't imagine there will be multiple instances of the |
||
|
||
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] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The implementation for the If we want the filter to return multiple potential sites, then the implementation should be updated. |
||
} | ||
} | ||
} | ||
|
||
return results | ||
} |
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, | ||
}, | ||
}, | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My editor made a bunch of automated refactors. |
||
for i, detection := range detections { | ||
fieldSet := make([]interface{}, len(detection.Fields)) | ||
for j, field := range detection.Fields { | ||
|
@@ -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, | ||
|
@@ -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, | ||
|
@@ -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{}{ | ||
|
@@ -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 | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enables me to locally test the provider.