Skip to content

Commit fc40de8

Browse files
authored
Application Performance (caching) Resource (#509)
* add resources * add resources * add resources * add resources * fix typo * Add defaults to new resource * review fixes * review fixes * rename docs * rename docs * fix attributes
1 parent 7762789 commit fc40de8

9 files changed

+823
-18
lines changed

incapsula/client_performance.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ type PerformanceSettings struct {
3030
CacheShield bool `json:"cache_shield"`
3131
CacheResponseHeader struct {
3232
Mode string `json:"mode,omitempty"`
33-
Headers []interface{} `json:"headers,omitempty"`
33+
Headers []interface{} `json:"headers"`
3434
} `json:"cache_response_header,omitempty"`
35-
TagResponseHeader string `json:"tag_response_header,omitempty"`
35+
TagResponseHeader string `json:"tag_response_header"`
3636
CacheEmptyResponses bool `json:"cache_empty_responses"`
3737
Cache300X bool `json:"cache_300x"`
3838
CacheHTTP10Responses bool `json:"cache_http_10_responses"`
@@ -53,14 +53,14 @@ type PerformanceSettings struct {
5353
}
5454

5555
// GetPerformanceSettings gets the site performance settings
56-
func (c *Client) GetPerformanceSettings(siteID string) (*PerformanceSettings, int, error) {
56+
func (c *Client) GetPerformanceSettings(siteID string) (*PerformanceSettings, error) {
5757
log.Printf("[INFO] Getting Incapsula Performance Settings for Site ID %s\n", siteID)
5858

5959
// Post form to Incapsula
6060
reqURL := fmt.Sprintf("%s/sites/%s/settings/cache", c.config.BaseURLRev2, siteID)
6161
resp, err := c.DoJsonRequestWithHeaders(http.MethodGet, reqURL, nil, ReadSitePerformance)
6262
if err != nil {
63-
return nil, 0, fmt.Errorf("Error from Incapsula service when reading Incap Performance Settings for Site ID %s: %s", siteID, err)
63+
return nil, fmt.Errorf("Error from Incapsula service when reading Incap Performance Settings for Site ID %s: %s", siteID, err)
6464
}
6565

6666
// Read the body
@@ -72,17 +72,17 @@ func (c *Client) GetPerformanceSettings(siteID string) (*PerformanceSettings, in
7272

7373
// Check the response code
7474
if resp.StatusCode != 200 {
75-
return nil, resp.StatusCode, fmt.Errorf("Error status code %d from Incapsula service when reading Incap Performance Settings for Site ID %s: %s", resp.StatusCode, siteID, string(responseBody))
75+
return nil, fmt.Errorf("Error status code %d from Incapsula service when reading Incap Performance Settings for Site ID %s: %s", resp.StatusCode, siteID, string(responseBody))
7676
}
7777

7878
// Parse the JSON
7979
var performanceSettings PerformanceSettings
8080
err = json.Unmarshal([]byte(responseBody), &performanceSettings)
8181
if err != nil {
82-
return nil, resp.StatusCode, fmt.Errorf("Error parsing Incap Performance Settings JSON response for Site ID %s: %s\nresponse: %s", siteID, err, string(responseBody))
82+
return nil, fmt.Errorf("Error parsing Incap Performance Settings JSON response for Site ID %s: %s\nresponse: %s", siteID, err, string(responseBody))
8383
}
8484

85-
return &performanceSettings, resp.StatusCode, nil
85+
return &performanceSettings, nil
8686
}
8787

8888
// UpdatePerformanceSettings updates the site performance settings

incapsula/client_performance_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func TestClientGetPerformanceSettingsBadConnection(t *testing.T) {
1717
config := &Config{APIID: "foo", APIKey: "bar", BaseURL: "badness.incapsula.com"}
1818
client := &Client{config: config, httpClient: &http.Client{Timeout: time.Millisecond * 1}}
1919
siteID := "123"
20-
performanceSettings, _, err := client.GetPerformanceSettings(siteID)
20+
performanceSettings, err := client.GetPerformanceSettings(siteID)
2121
if err == nil {
2222
t.Errorf("Should have received an error")
2323
}
@@ -47,7 +47,7 @@ func TestClientGetPerformanceSettingsBadJSON(t *testing.T) {
4747
config := &Config{APIID: apiID, APIKey: apiKey, BaseURL: server.URL, BaseURLRev2: server.URL, BaseURLAPI: server.URL}
4848
client := &Client{config: config, httpClient: &http.Client{}}
4949

50-
performanceSettings, _, err := client.GetPerformanceSettings(siteID)
50+
performanceSettings, err := client.GetPerformanceSettings(siteID)
5151
if err == nil {
5252
t.Errorf("Should have received an error")
5353
}
@@ -78,7 +78,7 @@ func TestClientGetPerformanceSettingsInvalidSite(t *testing.T) {
7878
config := &Config{APIID: apiID, APIKey: apiKey, BaseURL: server.URL, BaseURLRev2: server.URL, BaseURLAPI: server.URL}
7979
client := &Client{config: config, httpClient: &http.Client{}}
8080

81-
performanceSettings, _, err := client.GetPerformanceSettings(siteID)
81+
performanceSettings, err := client.GetPerformanceSettings(siteID)
8282
if err == nil {
8383
t.Errorf("Should have received an error")
8484
}
@@ -108,7 +108,7 @@ func TestClientGetPerformanceSettingsValidSite(t *testing.T) {
108108
config := &Config{APIID: apiID, APIKey: apiKey, BaseURL: server.URL, BaseURLRev2: server.URL, BaseURLAPI: server.URL}
109109
client := &Client{config: config, httpClient: &http.Client{}}
110110

111-
performanceSettings, _, err := client.GetPerformanceSettings(siteID)
111+
performanceSettings, err := client.GetPerformanceSettings(siteID)
112112
if err != nil {
113113
t.Errorf("Should not have received an error")
114114
}

incapsula/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func Provider() *schema.Provider {
154154
"incapsula_abp_websites": resourceAbpWebsites(),
155155
"incapsula_delivery_rules_configuration": resourceDeliveryRulesConfiguration(),
156156
"incapsula_simplified_redirect_rules_configuration": resourceSimplifiedRedirectRulesConfiguration(),
157+
"incapsula_site_cache_configuration": resourceSiteCacheConfiguration(),
157158
},
158159
}
159160

incapsula/resource_site.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ package incapsula
22

33
import (
44
"fmt"
5-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
6-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
85
"log"
96
"strconv"
107
"strings"
118
"time"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1213
)
1314

1415
const create_retries = 3
@@ -245,7 +246,7 @@ func resourceSite() *schema.Resource {
245246
Optional: true,
246247
},
247248
"perf_response_cache_response_header_mode": {
248-
Description: "The working mode for caching response headers. Options are `all` and `custom`.",
249+
Description: "The working mode for caching response headers. Options are `all`, `custom` and `disabled`.",
249250
Type: schema.TypeString,
250251
Computed: true,
251252
Optional: true,
@@ -514,7 +515,7 @@ func resourceSiteRead(d *schema.ResourceData, m interface{}) error {
514515
d.Set("hash_salt", maskingResponse.HashSalt)
515516

516517
// Get the performance settings for the site
517-
performanceSettingsResponse, _, err := client.GetPerformanceSettings(d.Id())
518+
performanceSettingsResponse, err := client.GetPerformanceSettings(d.Id())
518519
if err != nil {
519520
log.Printf("[ERROR] Could not read Incapsula site peformance settings for domain: %s and site id: %d, %s\n", domain, siteID, err)
520521
return err
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
package incapsula
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strconv"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
10+
)
11+
12+
func resourceSiteCacheConfiguration() *schema.Resource {
13+
return &schema.Resource{
14+
Create: resourceApplicationPerformanceUpdate,
15+
Read: resourceApplicationPerformanceRead,
16+
Update: resourceApplicationPerformanceUpdate,
17+
Delete: resourceApplicationPerformanceDelete,
18+
Importer: &schema.ResourceImporter{
19+
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
20+
siteID, err := strconv.Atoi(d.Id())
21+
if err != nil {
22+
return nil, fmt.Errorf("failed to convert Site Id from import command for Site Cache Configuration resource, actual value: %s, expected numeric id", d.Id())
23+
}
24+
25+
d.Set("site_id", siteID)
26+
log.Printf("[DEBUG] Import Site Cache Configuration for Site ID %d", siteID)
27+
return []*schema.ResourceData{d}, nil
28+
},
29+
},
30+
31+
Schema: map[string]*schema.Schema{
32+
// Required Arguments
33+
"site_id": {
34+
Description: "Numeric identifier of the site to operate on. ",
35+
Type: schema.TypeInt,
36+
Required: true,
37+
ForceNew: true,
38+
},
39+
"client_comply_no_cache": {
40+
Description: "Comply with No-Cache and Max-Age directives in client requests. By default, these cache directives are ignored. Resources are dynamically profiled and re-configured to optimize performance.",
41+
Type: schema.TypeBool,
42+
Optional: true,
43+
Default: false,
44+
},
45+
"client_enable_client_side_caching": {
46+
Description: "Cache content on client browsers or applications. When not enabled, content is cached only on the Imperva proxies.",
47+
Type: schema.TypeBool,
48+
Optional: true,
49+
Default: false,
50+
},
51+
"client_send_age_header": {
52+
Description: "Send Cache-Control: max-age and Age headers.",
53+
Type: schema.TypeBool,
54+
Optional: true,
55+
Default: false,
56+
},
57+
"key_comply_vary": {
58+
Description: "Comply with Vary. Cache resources in accordance with the Vary response header.",
59+
Type: schema.TypeBool,
60+
Optional: true,
61+
Default: false,
62+
},
63+
"key_unite_naked_full_cache": {
64+
Description: "Use the Same Cache for Full and Naked Domains. For example, use the same cached resource for www.example.com/a and example.com/a.",
65+
Type: schema.TypeBool,
66+
Optional: true,
67+
Default: false,
68+
},
69+
"mode_https": {
70+
Description: "The resources that are cached over HTTPS, the general level applies. Options are `disabled`, `dont_include_html`, `include_html`, and `include_all_resources`.",
71+
Type: schema.TypeString,
72+
Optional: true,
73+
Default: "disabled",
74+
ValidateFunc: validation.StringInSlice([]string{"disabled", "dont_include_html", "include_html", "include_all_resources"}, false),
75+
},
76+
"mode_level": {
77+
Description: "Caching level. Options are `disabled`, `custom_cache_rules_only`, `standard`, `smart`, and `all_resources`.",
78+
Type: schema.TypeString,
79+
Optional: true,
80+
Default: "smart",
81+
ValidateFunc: validation.StringInSlice([]string{"disabled", "custom_cache_rules_only", "standard", "smart", "all_resources"}, false),
82+
},
83+
"mode_time": {
84+
Description: "The time, in seconds, that you set for this option determines how often the cache is refreshed. Relevant for the `include_html` and `include_all_resources` levels only.",
85+
Type: schema.TypeInt,
86+
Optional: true,
87+
Default: 0,
88+
},
89+
"response_cache_300x": {
90+
Description: "When this option is checked Imperva will cache 301, 302, 303, 307, and 308 redirect response headers containing the target URI.",
91+
Type: schema.TypeBool,
92+
Optional: true,
93+
Default: false,
94+
},
95+
"response_cache_404_enabled": {
96+
Description: "Whether or not to cache 404 responses.",
97+
Type: schema.TypeBool,
98+
Optional: true,
99+
Default: false,
100+
},
101+
"response_cache_404_time": {
102+
Description: "The time in seconds to cache 404 responses.",
103+
Type: schema.TypeInt,
104+
Optional: true,
105+
Default: 0,
106+
ValidateFunc: validation.IntDivisibleBy(60),
107+
},
108+
"response_cache_empty_responses": {
109+
Description: "Cache responses that don’t have a message body.",
110+
Type: schema.TypeBool,
111+
Optional: true,
112+
Default: false,
113+
},
114+
"response_cache_http_10_responses": {
115+
Description: "Cache HTTP 1.0 type responses that don’t include the Content-Length header or chunking.",
116+
Type: schema.TypeBool,
117+
Optional: true,
118+
Default: false,
119+
},
120+
"response_cache_response_header_mode": {
121+
Description: "The working mode for caching response headers. Options are `all`, `custom` and `disabled`.",
122+
Type: schema.TypeString,
123+
Optional: true,
124+
Default: "disabled",
125+
ValidateFunc: validation.StringInSlice([]string{"disabled", "custom", "all"}, false),
126+
},
127+
"response_cache_response_headers": {
128+
Description: "An array of strings representing the response headers to be cached when working in `custom` mode. If empty, no response headers are cached.",
129+
Type: schema.TypeSet,
130+
Elem: &schema.Schema{
131+
Type: schema.TypeString,
132+
},
133+
Optional: true,
134+
},
135+
"response_cache_shield": {
136+
Description: "Adds an intermediate cache between other Imperva PoPs and your origin servers to protect your servers from redundant requests.",
137+
Type: schema.TypeBool,
138+
Optional: true,
139+
Default: false,
140+
},
141+
"response_stale_content_mode": {
142+
Description: "The working mode for serving stale content. Options are `disabled`, `adaptive`, and `custom`.",
143+
Type: schema.TypeString,
144+
Optional: true,
145+
Default: "disabled",
146+
ValidateFunc: validation.StringInSlice([]string{"disabled", "adaptive", "custom"}, false),
147+
},
148+
"response_stale_content_time": {
149+
Description: "The time, in seconds, to serve stale content for when working in `custom` work mode.",
150+
Type: schema.TypeInt,
151+
Optional: true,
152+
Default: 0,
153+
},
154+
"response_tag_response_header": {
155+
Description: "Tag the response according to the value of this header. Specify which origin response header contains the cache tags in your resources.",
156+
Type: schema.TypeString,
157+
Optional: true,
158+
},
159+
"ttl_prefer_last_modified": {
160+
Description: "Prefer 'Last Modified' over eTag. When this option is checked, Imperva prefers using Last Modified values (if available) over eTag values (recommended on multi-server setups).",
161+
Type: schema.TypeBool,
162+
Optional: true,
163+
Default: false,
164+
},
165+
"ttl_use_shortest_caching": {
166+
Description: "Use shortest caching duration in case of conflicts. By default, the longest duration is used in case of conflict between caching rules or modes. When this option is checked, Imperva uses the shortest duration in case of conflict.",
167+
Type: schema.TypeBool,
168+
Optional: true,
169+
Default: false,
170+
},
171+
},
172+
}
173+
}
174+
175+
func resourceApplicationPerformanceUpdate(d *schema.ResourceData, m interface{}) error {
176+
client := m.(*Client)
177+
siteID := d.Get("site_id").(int)
178+
siteIdStr := strconv.Itoa(siteID)
179+
180+
performanceSettings := PerformanceSettings{}
181+
performanceSettings.ClientSide.ComplyNoCache = d.Get("client_comply_no_cache").(bool)
182+
performanceSettings.ClientSide.EnableClientSideCaching = d.Get("client_enable_client_side_caching").(bool)
183+
performanceSettings.ClientSide.SendAgeHeader = d.Get("client_send_age_header").(bool)
184+
performanceSettings.Key.ComplyVary = d.Get("key_comply_vary").(bool)
185+
performanceSettings.Key.UniteNakedFullCache = d.Get("key_unite_naked_full_cache").(bool)
186+
performanceSettings.Mode.HTTPS = d.Get("mode_https").(string)
187+
performanceSettings.Mode.Level = d.Get("mode_level").(string)
188+
performanceSettings.Mode.Time = d.Get("mode_time").(int)
189+
performanceSettings.Response.Cache300X = d.Get("response_cache_300x").(bool)
190+
performanceSettings.Response.Cache404.Enabled = d.Get("response_cache_404_enabled").(bool)
191+
performanceSettings.Response.Cache404.Time = d.Get("response_cache_404_time").(int)
192+
performanceSettings.Response.CacheEmptyResponses = d.Get("response_cache_empty_responses").(bool)
193+
performanceSettings.Response.CacheHTTP10Responses = d.Get("response_cache_http_10_responses").(bool)
194+
performanceSettings.Response.CacheResponseHeader.Mode = d.Get("response_cache_response_header_mode").(string)
195+
performanceSettings.Response.CacheResponseHeader.Headers = d.Get("response_cache_response_headers").(*schema.Set).List()
196+
performanceSettings.Response.CacheShield = d.Get("response_cache_shield").(bool)
197+
performanceSettings.Response.StaleContent.Mode = d.Get("response_stale_content_mode").(string)
198+
performanceSettings.Response.StaleContent.Time = d.Get("response_stale_content_time").(int)
199+
performanceSettings.Response.TagResponseHeader = d.Get("response_tag_response_header").(string)
200+
performanceSettings.TTL.PreferLastModified = d.Get("ttl_prefer_last_modified").(bool)
201+
performanceSettings.TTL.UseShortestCaching = d.Get("ttl_use_shortest_caching").(bool)
202+
203+
_, err := client.UpdatePerformanceSettings(siteIdStr, &performanceSettings)
204+
if err != nil {
205+
log.Printf("[ERROR] Could not update Incapsula performance settings for site_id: %s %s\n", d.Id(), err)
206+
return err
207+
}
208+
209+
return resourceApplicationPerformanceRead(d, m)
210+
}
211+
212+
func resourceApplicationPerformanceRead(d *schema.ResourceData, m interface{}) error {
213+
client := m.(*Client)
214+
siteID := d.Get("site_id").(int)
215+
siteIdStr := strconv.Itoa(siteID)
216+
217+
performanceSettingsResponse, err := client.GetPerformanceSettings(siteIdStr)
218+
if err != nil {
219+
log.Printf("[ERROR] Could not read Incapsula site peformance settings for site id: %d, %s\n", siteID, err)
220+
return err
221+
}
222+
223+
d.Set("client_comply_no_cache", performanceSettingsResponse.ClientSide.ComplyNoCache)
224+
d.Set("client_enable_client_side_caching", performanceSettingsResponse.ClientSide.EnableClientSideCaching)
225+
d.Set("client_send_age_header", performanceSettingsResponse.ClientSide.SendAgeHeader)
226+
d.Set("key_comply_vary", performanceSettingsResponse.Key.ComplyVary)
227+
d.Set("key_unite_naked_full_cache", performanceSettingsResponse.Key.UniteNakedFullCache)
228+
d.Set("mode_https", performanceSettingsResponse.Mode.HTTPS)
229+
d.Set("mode_level", performanceSettingsResponse.Mode.Level)
230+
d.Set("mode_time", performanceSettingsResponse.Mode.Time)
231+
d.Set("response_cache_300x", performanceSettingsResponse.Response.Cache300X)
232+
d.Set("response_cache_404_enabled", performanceSettingsResponse.Response.Cache404.Enabled)
233+
d.Set("response_cache_404_time", performanceSettingsResponse.Response.Cache404.Time)
234+
d.Set("response_cache_empty_responses", performanceSettingsResponse.Response.CacheEmptyResponses)
235+
d.Set("response_cache_http_10_responses", performanceSettingsResponse.Response.CacheHTTP10Responses)
236+
d.Set("response_cache_response_header_mode", performanceSettingsResponse.Response.CacheResponseHeader.Mode)
237+
d.Set("response_cache_response_headers", performanceSettingsResponse.Response.CacheResponseHeader.Headers)
238+
d.Set("response_cache_shield", performanceSettingsResponse.Response.CacheShield)
239+
d.Set("response_stale_content_mode", performanceSettingsResponse.Response.StaleContent.Mode)
240+
d.Set("response_stale_content_time", performanceSettingsResponse.Response.StaleContent.Time)
241+
d.Set("response_tag_response_header", performanceSettingsResponse.Response.TagResponseHeader)
242+
d.Set("ttl_prefer_last_modified", performanceSettingsResponse.TTL.PreferLastModified)
243+
d.Set("ttl_use_shortest_caching", performanceSettingsResponse.TTL.UseShortestCaching)
244+
245+
d.SetId(siteIdStr)
246+
247+
return nil
248+
}
249+
250+
func resourceApplicationPerformanceDelete(d *schema.ResourceData, m interface{}) error {
251+
d.SetId("")
252+
return nil
253+
}

0 commit comments

Comments
 (0)