Skip to content

Commit 5bf86ae

Browse files
authored
Merge pull request #133 from katrinpolit/text-record
txt-record resource - add acceptance test, edit related documentation
2 parents fe4428f + 0d052a7 commit 5bf86ae

File tree

7 files changed

+236
-94
lines changed

7 files changed

+236
-94
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 3.3.2 (Not Released)
2+
3+
* Edit business logic, add acceptance test for incapsula_txt_record resource
4+
5+
## 3.3.1 (Released)
6+
7+
* No Changes were detected
8+
19
## 3.3.0 (Released)
210

311
* SubAccount resource addition (incapsula_subaccount)
Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log"
88
"net/http"
99
"net/url"
10+
"strings"
1011
)
1112

1213
// TXTResponse contains the relevant information when creating/updating/deleting a TXT record
@@ -64,6 +65,11 @@ func (c *Client) ReadTXTRecords(siteID int) (*TXTRecordResponse, error) {
6465
return nil, fmt.Errorf("Error parsing Incap TXT record(s) JSON response for siteID: %d\n%s\nresponse: %s", siteID, err, string(responseBody))
6566
}
6667

68+
response := []byte(responseBody)
69+
if strings.Contains(string(response), "no TXT records") {
70+
return nil, fmt.Errorf("[ERROR] The Text Records for Site ID %d does not exist", siteID)
71+
}
72+
6773
return &txtRecords, nil
6874
}
6975

@@ -156,13 +162,13 @@ func (c *Client) UpdateTXTRecord(siteID int, txtRecordValueOne string, txtRecord
156162

157163
// DeleteTXTRecord deletes TXT record(s) on the siteID.
158164
func (c *Client) DeleteTXTRecord(siteID int, recordNumber string) error {
159-
log.Printf("[INFO] Delete Incapsula TXT record number %d for siteID %s\n ", siteID, recordNumber)
165+
log.Printf("[INFO] Delete Incapsula TXT record number %s for siteID %d\n ", recordNumber, siteID)
160166

161-
// Post request to Incapsula
162167
reqURL := fmt.Sprintf("%s/sites/%d/settings/general/additionalTxtRecords?record_number=%s", c.config.BaseURLRev2, siteID, recordNumber)
163168
resp, err := c.DoJsonRequestWithHeaders(http.MethodDelete, reqURL, nil)
164169
if err != nil {
165-
return fmt.Errorf("Error deleting TXT record(s) for siteID %d: %s", siteID, err)
170+
log.Printf("[DEBUG] Error deleting TXT record for siteID %d: %s", siteID, err)
171+
return fmt.Errorf("Error deleting TXT record for siteID %d", siteID)
166172
}
167173

168174
// Read the body
@@ -172,9 +178,36 @@ func (c *Client) DeleteTXTRecord(siteID int, recordNumber string) error {
172178
// Dump JSON
173179
log.Printf("[DEBUG] Incapsula DeleteTXTRecord JSON response: %s\n", string(responseBody))
174180

181+
response := []byte(responseBody)
175182
// Check the response code
176-
if resp.StatusCode != 200 {
177-
return fmt.Errorf("Error status code %d from Incapsula service when deleting TXT record(s) for siteID %d: %s", resp.StatusCode, siteID, string(responseBody))
183+
// The response code of successful request is 400
184+
if resp.StatusCode != 400 && !strings.Contains(string(response), "OK") {
185+
return fmt.Errorf("Error status code %d from Incapsula service when deleting TXT record for siteID %d: %s", resp.StatusCode, siteID, string(responseBody))
186+
}
187+
188+
return nil
189+
}
190+
191+
func (c *Client) DeleteTXTRecordAll(siteID int) error {
192+
log.Printf("[INFO] Delete Incapsula All TXT records for siteID %s\n ", siteID)
193+
reqURL := fmt.Sprintf("%s/sites/%d/settings/general/additionalTxtRecords/delete-all", c.config.BaseURLRev2, siteID)
194+
195+
resp, err := c.DoJsonRequestWithHeaders(http.MethodDelete, reqURL, nil)
196+
if err != nil {
197+
return fmt.Errorf("Error deleting TXT records for siteID %d: %v", siteID, err)
198+
}
199+
// Read the body
200+
defer resp.Body.Close()
201+
responseBody, err := ioutil.ReadAll(resp.Body)
202+
203+
// Dump JSON
204+
log.Printf("[DEBUG] Incapsula DeleteTXTRecords JSON response: %s\n", string(responseBody))
205+
206+
response := []byte(responseBody)
207+
// Check the response code
208+
if resp.StatusCode != 400 && !strings.Contains(string(response), "OK") {
209+
return fmt.Errorf("Error status code %d from Incapsula service when deleting all "+
210+
"TXT records for siteID %d: %s", resp.StatusCode, siteID, string(responseBody))
178211
}
179212

180213
return nil
File renamed without changes.

incapsula/resource_api_security_api_config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func testACCStateApiSecurityApiConfigDestroy(s *terraform.State) error {
7070

7171
_, err = client.GetApiSecurityApiConfig(siteIDInt, apiID)
7272
if err == nil {
73-
return fmt.Errorf("Resource%sforIncapsulaApiSecurityApi:ApiId%d,siteID%dstillexists", apiSecApiConfigResourceName, apiID, siteIDInt)
73+
return fmt.Errorf("Resource %s for Incapsula Api Security Api: Api Id %d, site ID %d still exists", apiSecApiConfigResourceName, apiID, siteIDInt)
7474
}
7575
}
7676
return fmt.Errorf("Error finding site_id")
Lines changed: 72 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package incapsula
33
import (
44
"log"
55
"strconv"
6+
"strings"
67

78
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
89
)
@@ -57,9 +58,9 @@ func resourceTXTRecord() *schema.Resource {
5758

5859
func resourceTXTRecordCreate(d *schema.ResourceData, m interface{}) error {
5960
// Implement by create the TXT Records
60-
6161
client := m.(*Client)
6262
siteID := d.Get("site_id").(int)
63+
6364
TXTRecordOne := d.Get("txt_record_value_one").(string)
6465
TXTRecordTwo := d.Get("txt_record_value_two").(string)
6566
TXTRecordThree := d.Get("txt_record_value_three").(string)
@@ -76,7 +77,7 @@ func resourceTXTRecordCreate(d *schema.ResourceData, m interface{}) error {
7677
}
7778

7879
// Set the ID
79-
d.SetId(d.Get("site_id").(string))
80+
d.SetId(strconv.Itoa(siteID))
8081
log.Printf("[INFO] Create Incapsula TXT Records: %s, %s, %s, %s, %s, for siteID: %d\n", TXTRecordOne, TXTRecordTwo, TXTRecordThree, TXTRecordFour, TXTRecordFive, siteID)
8182

8283
return resourceTXTRecordRead(d, m)
@@ -85,7 +86,19 @@ func resourceTXTRecordCreate(d *schema.ResourceData, m interface{}) error {
8586
func resourceTXTRecordUpdate(d *schema.ResourceData, m interface{}) error {
8687
client := m.(*Client)
8788
siteID := d.Get("site_id").(int)
89+
errDelete := deleteSpecificTXTRecordIfNeeded(d, siteID, client)
90+
if errDelete != nil {
91+
return errDelete
92+
}
93+
errUpdate := updateSpecificTXTRecordIfNeeded(d, siteID, client)
94+
if errUpdate != nil {
95+
return errUpdate
96+
}
97+
98+
return resourceTXTRecordRead(d, m)
99+
}
88100

101+
func updateSpecificTXTRecordIfNeeded(d *schema.ResourceData, siteID int, client *Client) error {
89102
if (d.HasChange("txt_record_value_one") && d.Get("txt_record_value_one") != "") ||
90103
(d.HasChange("txt_record_value_two") && d.Get("txt_record_value_two") != "") ||
91104
(d.HasChange("txt_record_value_three") && d.Get("txt_record_value_three") != "") ||
@@ -106,24 +119,68 @@ func resourceTXTRecordUpdate(d *schema.ResourceData, m interface{}) error {
106119
log.Printf("[ERROR] Could not set Incapsula TXT Records: %s, %s, %s, %s, %s, for siteID: %d\n%s", TXTRecordOne, TXTRecordTwo, TXTRecordThree, TXTRecordFour, TXTRecordFive, siteID, err)
107120
return err
108121
}
109-
110122
// Set the ID
111123
log.Printf("[INFO] Update Incapsula TXT Records: %s, %s, %s, %s, %s, for siteID: %d\n", TXTRecordOne, TXTRecordTwo, TXTRecordThree, TXTRecordFour, TXTRecordFive, siteID)
112124
}
113-
return resourceTXTRecordRead(d, m)
125+
return nil
126+
}
127+
128+
func deleteSpecificTXTRecordIfNeeded(d *schema.ResourceData, siteID int, client *Client) error {
129+
if d.HasChange("txt_record_value_one") && d.Get("txt_record_value_one") == "" {
130+
log.Printf("[INFO] Delete Incapsula TXT Record 1, for siteID: %d", siteID)
131+
err := client.DeleteTXTRecord(siteID, "1")
132+
if err != nil {
133+
log.Printf("[ERROR] Could not delete Incapsula TXT Records 1, for siteID: %d\n%s", siteID, err)
134+
return err
135+
}
136+
} else if d.HasChange("txt_record_value_two") && d.Get("txt_record_value_two") == "" {
137+
log.Printf("[INFO] Delete Incapsula TXT Record 2, for siteID: %d", siteID)
138+
err := client.DeleteTXTRecord(siteID, "2")
139+
if err != nil {
140+
log.Printf("[ERROR] Could not delete Incapsula TXT Records 2, for siteID: %d\n%s", siteID, err)
141+
return err
142+
}
143+
} else if d.HasChange("txt_record_value_three") && d.Get("txt_record_value_three") == "" {
144+
log.Printf("[INFO] Delete Incapsula TXT Record 3, for siteID: %d", siteID)
145+
err := client.DeleteTXTRecord(siteID, "3")
146+
if err != nil {
147+
log.Printf("[ERROR] Could not delete Incapsula TXT Records 3, for siteID: %d\n%s", siteID, err)
148+
return err
149+
}
150+
} else if d.HasChange("txt_record_value_four") && d.Get("txt_record_value_four") == "" {
151+
log.Printf("[INFO] Delete Incapsula TXT Record 4, for siteID: %d", siteID)
152+
err := client.DeleteTXTRecord(siteID, "4")
153+
if err != nil {
154+
log.Printf("[ERROR] Could not delete Incapsula TXT Records 4, for siteID: %d\n%s", siteID, err)
155+
return err
156+
}
157+
} else if d.HasChange("txt_record_value_five") && d.Get("txt_record_value_five") == "" {
158+
log.Printf("[INFO] Delete Incapsula TXT Record 5, for siteID: %d", siteID)
159+
err := client.DeleteTXTRecord(siteID, "5")
160+
if err != nil {
161+
log.Printf("[ERROR] Could not delete Incapsula TXT Records 5, for siteID: %d\n%s", siteID, err)
162+
return err
163+
}
164+
}
165+
return nil
114166
}
115167

116168
func resourceTXTRecordRead(d *schema.ResourceData, m interface{}) error {
117169
// Implement by reading the TXTRecordResponse for the TXT Records
118170
client := m.(*Client)
171+
id, err := strconv.Atoi(d.Id())
172+
if err != nil {
173+
log.Printf("[ERROR] The ID should be numeric. Currrent value: %s", d.Id())
174+
return err
175+
}
119176

120-
id, _ := strconv.Atoi(d.Id())
121177
recordResponse, err := client.ReadTXTRecords(id)
178+
d.Set("site_id", id)
122179

123180
// Gte TXT response object
124181
if recordResponse != nil {
125182
// Res can oscillate between strings and ints
126-
if recordResponse.Res == 0 {
183+
if recordResponse.Res == 0 && !strings.Contains(recordResponse.ResMessage, "no TXT records") {
127184
d.Set("txt_record_value_one", recordResponse.TxtRecordValueOne)
128185
d.Set("txt_record_value_two", recordResponse.TxtRecordValueTwo)
129186
d.Set("txt_record_value_three", recordResponse.TxtRecordValueThree)
@@ -135,47 +192,21 @@ func resourceTXTRecordRead(d *schema.ResourceData, m interface{}) error {
135192
if err != nil {
136193
return err
137194
}
138-
139195
return nil
140196
}
141197

142198
func resourceTXTRecordDelete(d *schema.ResourceData, m interface{}) error {
143199
// Implement by deleting the a TXT Record
144200
client := m.(*Client)
145-
id, _ := strconv.Atoi(d.Id())
146-
147-
if d.HasChange("txt_record_value_one") && d.Get("txt_record_value_one") == "" {
148-
log.Printf("[INFO] Delete Incapsula TXT Record 1, for siteID: %d", id)
149-
err := client.DeleteTXTRecord(id, "1")
150-
if err != nil {
151-
log.Printf("[ERROR] Could not delete Incapsula TXT Records 1, for siteID: %d\n%s", id, err)
152-
}
153-
} else if d.HasChange("txt_record_value_two") && d.Get("txt_record_value_two") == "" {
154-
log.Printf("[INFO] Delete Incapsula TXT Record 2, for siteID: %d", id)
155-
err := client.DeleteTXTRecord(id, "2")
156-
if err != nil {
157-
log.Printf("[ERROR] Could not delete Incapsula TXT Records 2, for siteID: %d\n%s", id, err)
158-
}
159-
} else if d.HasChange("txt_record_value_three") && d.Get("txt_record_value_three") == "" {
160-
log.Printf("[INFO] Delete Incapsula TXT Record 3, for siteID: %d", id)
161-
err := client.DeleteTXTRecord(id, "3")
162-
if err != nil {
163-
log.Printf("[ERROR] Could not delete Incapsula TXT Records 3, for siteID: %d\n%s", id, err)
164-
}
165-
} else if d.HasChange("txt_record_value_four") && d.Get("txt_record_value_four") == "" {
166-
log.Printf("[INFO] Delete Incapsula TXT Record 4, for siteID: %d", id)
167-
err := client.DeleteTXTRecord(id, "4")
168-
if err != nil {
169-
log.Printf("[ERROR] Could not delete Incapsula TXT Records 4, for siteID: %d\n%s", id, err)
170-
}
171-
} else if d.HasChange("txt_record_value_five") && d.Get("txt_record_value_five") == "" {
172-
log.Printf("[INFO] Delete Incapsula TXT Record 5, for siteID: %d", id)
173-
err := client.DeleteTXTRecord(id, "5")
174-
if err != nil {
175-
log.Printf("[ERROR] Could not delete Incapsula TXT Records 5, for siteID: %d\n%s", id, err)
176-
}
201+
siteID := d.Get("site_id").(int)
202+
err := client.DeleteTXTRecordAll(siteID)
203+
if err != nil {
204+
log.Printf("[ERROR] Could not delete all Incapsula TXT Records, for siteID: %d\n%s", siteID, err)
205+
return err
177206
}
178207

179-
// Will not nil the record, they will just be empty on a delete
180-
return resourceTXTRecordRead(d, m)
208+
// Set the ID to empty
209+
// Implicitly clears the resource
210+
d.SetId("")
211+
return nil
181212
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package incapsula
2+
3+
import (
4+
"fmt"
5+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
7+
"log"
8+
"strconv"
9+
"strings"
10+
"testing"
11+
)
12+
13+
const txtRecordResourceName = "incapsula_txt_record"
14+
const txtRecordResource = txtRecordResourceName + "." + textRecordName
15+
const textRecordName = "testacc-terraform-txt-record"
16+
17+
func TestAccIncapsulaTxtRecord_Basic(t *testing.T) {
18+
log.Printf("========================BEGIN TEST========================")
19+
log.Printf("[DEBUG]Running test resource_txt_record.TestAccIncapsulaApiSecurityApiConfig_Basic")
20+
resource.Test(t, resource.TestCase{
21+
PreCheck: func() { testAccPreCheck(t) },
22+
Providers: testAccProviders,
23+
CheckDestroy: testACCStateTXTRecordDestroy,
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testAccCheckTxtRecordBasic(t),
27+
Check: resource.ComposeTestCheckFunc(
28+
testCheckTxtRecordExists(txtRecordResource),
29+
resource.TestCheckResourceAttr(txtRecordResource, "txt_record_value_one", "test1"),
30+
resource.TestCheckResourceAttr(txtRecordResource, "txt_record_value_two", "test2"),
31+
resource.TestCheckResourceAttr(txtRecordResource, "txt_record_value_three", "test3"),
32+
resource.TestCheckResourceAttr(txtRecordResource, "txt_record_value_four", "test4"),
33+
resource.TestCheckResourceAttr(txtRecordResource, "txt_record_value_five", "test5"),
34+
),
35+
},
36+
{
37+
ResourceName: txtRecordResource,
38+
ImportState: true,
39+
ImportStateVerify: true,
40+
ImportStateIdFunc: testACCStateTxtRecordID,
41+
},
42+
},
43+
})
44+
}
45+
46+
func testACCStateTXTRecordDestroy(s *terraform.State) error {
47+
client := testAccProvider.Meta().(*Client)
48+
49+
for _, rs := range s.RootModule().Resources {
50+
if rs.Type != txtRecordResource {
51+
continue
52+
}
53+
siteID := rs.Primary.ID
54+
if siteID == "" {
55+
fmt.Errorf("Parameter site_id was not found in resource %s", txtRecordResourceName)
56+
}
57+
siteIDInt, err := strconv.Atoi(siteID)
58+
if err != nil {
59+
fmt.Errorf("failed to convert Site Id from import command, actual value : %s, expected numeric id", siteID)
60+
}
61+
recordResponse, err := client.ReadTXTRecords(siteIDInt)
62+
if err == nil || !strings.Contains(recordResponse.ResMessage, "no TXT records") {
63+
return fmt.Errorf("Resource %s for Incapsula TXT Record : site ID %d still exists", txtRecordResourceName, siteIDInt)
64+
}
65+
}
66+
return nil
67+
}
68+
69+
func testACCStateTxtRecordID(s *terraform.State) (string, error) {
70+
for _, rs := range s.RootModule().Resources {
71+
if rs.Type != txtRecordResourceName {
72+
continue
73+
}
74+
siteID, err := strconv.Atoi(rs.Primary.Attributes["site_id"])
75+
if err != nil {
76+
return "", fmt.Errorf("Error parsing site ID %v to int", rs.Primary.Attributes["site_id"])
77+
}
78+
return fmt.Sprintf("%d", siteID), nil
79+
}
80+
return "", fmt.Errorf("Error finding a TXT Record for SiteID, state")
81+
}
82+
83+
func testCheckTxtRecordExists(name string) resource.TestCheckFunc {
84+
return func(state *terraform.State) error {
85+
res, ok := state.RootModule().Resources[name]
86+
if !ok {
87+
return fmt.Errorf("Incapsula TXT Record resource not found: %s", name)
88+
}
89+
siteId, err := strconv.Atoi(res.Primary.ID)
90+
if err != nil {
91+
return fmt.Errorf("Error parsing ID %v to int", res.Primary.ID)
92+
}
93+
94+
client := testAccProvider.Meta().(*Client)
95+
recordResponse, err := client.ReadTXTRecords(siteId)
96+
if err != nil || strings.Contains(recordResponse.ResMessage, "no TXT records") {
97+
fmt.Errorf("Incapsula TXT Record doesn't exist")
98+
}
99+
100+
return nil
101+
}
102+
}
103+
104+
func testAccCheckTxtRecordBasic(t *testing.T) string {
105+
return testAccCheckIncapsulaSiteConfigBasic(GenerateTestDomain(t)) + fmt.Sprintf(`
106+
resource "incapsula_txt_record" "%s" {
107+
site_id = "${incapsula_site.testacc-terraform-site.id}"
108+
txt_record_value_one = "test1"
109+
txt_record_value_two = "test2"
110+
txt_record_value_three = "test3"
111+
txt_record_value_four = "test4"
112+
txt_record_value_five = "test5"
113+
depends_on = ["%s"]
114+
}`,
115+
textRecordName, siteResourceName,
116+
)
117+
}

0 commit comments

Comments
 (0)