Skip to content

Commit 48151d5

Browse files
committed
r/ip_reverse: rewrite of the resource
1 parent 4b36b21 commit 48151d5

6 files changed

+153
-154
lines changed

ovh/provider.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func Provider() *schema.Provider {
9898
"ovh_domain_zone": resourceDomainZone(),
9999
"ovh_domain_zone_record": resourceOvhDomainZoneRecord(),
100100
"ovh_domain_zone_redirection": resourceOvhDomainZoneRedirection(),
101-
"ovh_ip_reverse": resourceOvhIpReverse(),
101+
"ovh_ip_reverse": resourceIpReverse(),
102102
"ovh_ip_service": resourceIpService(),
103103
"ovh_iploadbalancing": resourceIpLoadbalancing(),
104104
"ovh_iploadbalancing_http_farm": resourceIpLoadbalancingHttpFarm(),

ovh/provider_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ func testAccPreCheckCredentials(t *testing.T) {
7373
// are set.
7474
func testAccPreCheckIp(t *testing.T) {
7575
testAccPreCheckCredentials(t)
76-
checkEnvOrSkip(t, "OVH_IP")
77-
checkEnvOrSkip(t, "OVH_IP_BLOCK")
78-
checkEnvOrSkip(t, "OVH_IP_REVERSE")
76+
checkEnvOrSkip(t, "OVH_IP_TEST")
77+
checkEnvOrSkip(t, "OVH_IP_BLOCK_TEST")
78+
checkEnvOrSkip(t, "OVH_IP_REVERSE_TEST")
7979
}
8080

8181
// Checks that the environment variables needed to order /ip/service for acceptance tests

ovh/resource_ip_reverse.go

+64-104
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,27 @@ package ovh
33
import (
44
"fmt"
55
"log"
6-
"net"
6+
"net/url"
77
"strings"
88

99
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1010
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
11-
12-
"github.com/ovh/go-ovh/ovh"
1311
)
1412

15-
type OvhIpReverse struct {
16-
IpReverse string `json:"ipReverse"`
17-
Reverse string `json:"reverse"`
18-
}
19-
20-
func resourceOvhIpReverse() *schema.Resource {
13+
func resourceIpReverse() *schema.Resource {
2114
return &schema.Resource{
22-
Create: resourceOvhIpReverseCreate,
23-
Read: resourceOvhIpReverseRead,
24-
Update: resourceOvhIpReverseUpdate,
25-
Delete: resourceOvhIpReverseDelete,
15+
Create: resourceIpReverseCreate,
16+
Read: resourceIpReverseRead,
17+
Delete: resourceIpReverseDelete,
18+
Importer: &schema.ResourceImporter{
19+
State: resourceIpReverseImportState,
20+
},
2621

2722
Schema: map[string]*schema.Schema{
2823
"ip": {
2924
Type: schema.TypeString,
3025
Required: true,
26+
ForceNew: true,
3127
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
3228
err := helpers.ValidateIpBlock(v.(string))
3329
if err != nil {
@@ -36,9 +32,11 @@ func resourceOvhIpReverse() *schema.Resource {
3632
return
3733
},
3834
},
39-
"ipreverse": {
35+
36+
"ip_reverse": {
4037
Type: schema.TypeString,
41-
Optional: true,
38+
Required: true,
39+
ForceNew: true,
4240
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
4341
err := helpers.ValidateIp(v.(string))
4442
if err != nil {
@@ -47,130 +45,92 @@ func resourceOvhIpReverse() *schema.Resource {
4745
return
4846
},
4947
},
48+
5049
"reverse": {
5150
Type: schema.TypeString,
51+
ForceNew: true,
5252
Required: true,
5353
},
5454
},
5555
}
5656
}
5757

58-
func resourceOvhIpReverseCreate(d *schema.ResourceData, meta interface{}) error {
59-
provider := meta.(*Config)
60-
61-
// Create the new reverse
62-
newIp := d.Get("ip").(string)
63-
newReverse := &OvhIpReverse{
64-
Reverse: d.Get("reverse").(string),
65-
}
66-
67-
newIpReverse, ok := d.GetOk("ipreverse")
68-
if !ok || newIpReverse == "" {
69-
ipAddr, ipNet, _ := net.ParseCIDR(newIp)
70-
prefixSize, _ := ipNet.Mask.Size()
71-
72-
if ipAddr.To4() != nil && prefixSize != 32 {
73-
return fmt.Errorf("ipreverse must be set if ip (%s) is not a /32", newIp)
74-
} else if ipAddr.To4() == nil && prefixSize != 128 {
75-
return fmt.Errorf("ipreverse must be set if ip (%s) is not a /128", newIp)
76-
}
77-
78-
newIpReverse = ipAddr.String()
79-
d.Set("ipreverse", newIpReverse)
58+
func resourceIpReverseImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
59+
givenId := d.Id()
60+
splitId := strings.SplitN(givenId, ":", 2)
61+
if len(splitId) != 2 {
62+
return nil, fmt.Errorf("Import Id is not ip:ip_reverse formatted")
8063
}
64+
ip := splitId[0]
65+
ipReverse := splitId[1]
66+
d.SetId(ipReverse)
67+
d.Set("ip", ip)
68+
69+
results := make([]*schema.ResourceData, 1)
70+
results[0] = d
71+
return results, nil
72+
}
8173

82-
newReverse.IpReverse = newIpReverse.(string)
83-
84-
log.Printf("[DEBUG] OVH IP Reverse create configuration: %#v", newReverse)
85-
86-
resultReverse := OvhIpReverse{}
74+
func resourceIpReverseCreate(d *schema.ResourceData, meta interface{}) error {
75+
config := meta.(*Config)
8776

88-
err := provider.OVHClient.Post(
89-
fmt.Sprintf("/ip/%s/reverse", strings.Replace(newIp, "/", "%2F", 1)),
90-
newReverse,
91-
&resultReverse,
77+
// Create the new reverse
78+
ip := d.Get("ip").(string)
79+
opts := (&IpReverseCreateOpts{}).FromResource(d)
80+
res := &IpReverse{}
81+
82+
err := config.OVHClient.Post(
83+
fmt.Sprintf("/ip/%s/reverse", url.PathEscape(ip)),
84+
opts,
85+
&res,
9286
)
9387
if err != nil {
9488
return fmt.Errorf("Failed to create OVH IP Reverse: %s", err)
9589
}
9690

97-
d.SetId(fmt.Sprintf("%s_%s", newIp, resultReverse.IpReverse))
91+
d.SetId(res.IpReverse)
9892

99-
return resourceOvhIpReverseRead(d, meta)
93+
return resourceIpReverseRead(d, meta)
10094
}
10195

102-
func resourceOvhIpReverseRead(d *schema.ResourceData, meta interface{}) error {
103-
provider := meta.(*Config)
96+
func resourceIpReverseRead(d *schema.ResourceData, meta interface{}) error {
97+
config := meta.(*Config)
10498

105-
reverse := OvhIpReverse{}
99+
ip := d.Get("ip").(string)
100+
101+
res := &IpReverse{}
106102
endpoint := fmt.Sprintf(
107103
"/ip/%s/reverse/%s",
108-
strings.Replace(d.Get("ip").(string), "/", "%2F", 1),
109-
d.Get("ipreverse").(string),
104+
url.PathEscape(ip),
105+
url.PathEscape(d.Id()),
110106
)
111107

112-
if err := provider.OVHClient.Get(endpoint, &reverse); err != nil {
108+
if err := config.OVHClient.Get(endpoint, &res); err != nil {
113109
return helpers.CheckDeleted(d, err, endpoint)
114110
}
115111

116-
d.Set("ipreverse", reverse.IpReverse)
117-
d.Set("reverse", reverse.Reverse)
118-
119-
return nil
120-
}
121-
122-
func resourceOvhIpReverseUpdate(d *schema.ResourceData, meta interface{}) error {
123-
provider := meta.(*Config)
124-
125-
reverse := OvhIpReverse{}
126-
127-
if attr, ok := d.GetOk("ipreverse"); ok {
128-
reverse.IpReverse = attr.(string)
129-
}
130-
if attr, ok := d.GetOk("reverse"); ok {
131-
reverse.Reverse = attr.(string)
112+
for k, v := range res.ToMap() {
113+
d.Set(k, v)
132114
}
133115

134-
log.Printf("[DEBUG] OVH IP Reverse update configuration: %#v", reverse)
135-
136-
err := provider.OVHClient.Post(
137-
fmt.Sprintf("/ip/%s/reverse", strings.Replace(d.Get("ip").(string), "/", "%2F", 1)),
138-
reverse,
139-
nil,
140-
)
141-
if err != nil {
142-
return fmt.Errorf("Failed to update OVH IP Reverse: %s", err)
143-
}
144-
145-
return resourceOvhIpReverseRead(d, meta)
116+
return nil
146117
}
147118

148-
func resourceOvhIpReverseDelete(d *schema.ResourceData, meta interface{}) error {
149-
provider := meta.(*Config)
119+
func resourceIpReverseDelete(d *schema.ResourceData, meta interface{}) error {
120+
config := meta.(*Config)
150121

151-
log.Printf("[INFO] Deleting OVH IP Reverse: %s->%s", d.Get("reverse").(string), d.Get("ipreverse").(string))
152-
153-
err := provider.OVHClient.Delete(
154-
fmt.Sprintf("/ip/%s/reverse/%s", strings.Replace(d.Get("ip").(string), "/", "%2F", 1), d.Get("ipreverse").(string)),
155-
nil,
122+
log.Printf("[INFO] Deleting OVH IP Reverse: %s->%s", d.Get("reverse").(string), d.Get("ip_reverse").(string))
123+
ip := d.Get("ip").(string)
124+
endpoint := fmt.Sprintf(
125+
"/ip/%s/reverse/%s",
126+
url.PathEscape(ip),
127+
url.PathEscape(d.Id()),
156128
)
157129

158-
if err != nil {
159-
return fmt.Errorf("Error deleting OVH IP Reverse: %s", err)
160-
}
161-
162-
return nil
163-
}
164-
165-
func resourceOvhIpReverseExists(ip, ipreverse string, c *ovh.Client) error {
166-
reverse := OvhIpReverse{}
167-
endpoint := fmt.Sprintf("/ip/%s/reverse/%s", strings.Replace(ip, "/", "%2F", 1), ipreverse)
168-
169-
err := c.Get(endpoint, &reverse)
170-
if err != nil {
171-
return fmt.Errorf("calling %s:\n\t %q", endpoint, err)
130+
if err := config.OVHClient.Delete(endpoint, nil); err != nil {
131+
return helpers.CheckDeleted(d, err, endpoint)
172132
}
173-
log.Printf("[DEBUG] Read IP reverse: %s", reverse)
174133

134+
d.SetId("")
175135
return nil
176136
}

ovh/resource_ip_reverse_test.go

+53-40
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package ovh
33
import (
44
"fmt"
55
"log"
6+
"net/url"
67
"os"
7-
"strings"
88
"testing"
99
"time"
1010

@@ -14,13 +14,13 @@ import (
1414
"github.com/ovh/go-ovh/ovh"
1515
)
1616

17-
var testAccIpReverseConfig = fmt.Sprintf(`
17+
var testAccIpReverseConfig = `
1818
resource "ovh_ip_reverse" "reverse" {
1919
ip = "%s"
20-
ipreverse = "%s"
20+
ip_reverse = "%s"
2121
reverse = "%s"
2222
}
23-
`, os.Getenv("OVH_IP_BLOCK"), os.Getenv("OVH_IP"), os.Getenv("OVH_IP_REVERSE"))
23+
`
2424

2525
func init() {
2626
resource.AddTestSweepers("ovh_ip_reverse", &resource.Sweeper{
@@ -35,10 +35,13 @@ func testSweepIpReverse(region string) error {
3535
return fmt.Errorf("error getting client: %s", err)
3636
}
3737

38-
reverse := OvhIpReverse{}
39-
testIp := os.Getenv("OVH_IP_BLOCK")
40-
testIpReverse := os.Getenv("OVH_IP")
41-
endpoint := fmt.Sprintf("/ip/%s/reverse/%s", strings.Replace(testIp, "/", "%2F", 1), testIpReverse)
38+
reverse := IpReverse{}
39+
testIp := os.Getenv("OVH_IP_BLOCK_TEST")
40+
testIpReverse := os.Getenv("OVH_IP_TEST")
41+
endpoint := fmt.Sprintf("/ip/%s/reverse/%s",
42+
url.PathEscape(testIp),
43+
url.PathEscape(testIpReverse),
44+
)
4245
if err := client.Get(endpoint, &reverse); err != nil {
4346
if errOvh, ok := err.(*ovh.APIError); ok && errOvh.Code == 404 {
4447
// no ip reverse set, nothing to sweep
@@ -65,53 +68,63 @@ func testSweepIpReverse(region string) error {
6568
}
6669

6770
func TestAccIpReverse_basic(t *testing.T) {
71+
block := os.Getenv("OVH_IP_BLOCK_TEST")
72+
ip := os.Getenv("OVH_IP_TEST")
73+
reverse := os.Getenv("OVH_IP_REVERSE_TEST")
74+
75+
config := fmt.Sprintf(testAccIpReverseConfig, block, ip, reverse)
76+
6877
resource.Test(t, resource.TestCase{
69-
PreCheck: func() { testAccPreCheckIp(t) },
70-
Providers: testAccProviders,
71-
CheckDestroy: testAccCheckIpReverseDestroy,
78+
PreCheck: func() { testAccPreCheckIp(t) },
79+
Providers: testAccProviders,
7280
Steps: []resource.TestStep{
7381
{
74-
Config: testAccIpReverseConfig,
82+
Config: config,
7583
Check: resource.ComposeTestCheckFunc(
76-
testAccCheckIpReverseExists("ovh_ip_reverse.reverse", t),
84+
resource.TestCheckResourceAttr("ovh_ip_reverse.reverse", "ip", block),
85+
resource.TestCheckResourceAttr("ovh_ip_reverse.reverse", "ip_reverse", ip),
86+
resource.TestCheckResourceAttr("ovh_ip_reverse.reverse", "reverse", reverse),
7787
),
7888
},
7989
},
8090
})
8191
}
8292

83-
func testAccCheckIpReverseExists(n string, t *testing.T) resource.TestCheckFunc {
84-
return func(s *terraform.State) error {
85-
config := testAccProvider.Meta().(*Config)
86-
87-
rs, ok := s.RootModule().Resources[n]
88-
if !ok {
89-
return fmt.Errorf("Not found: %s", n)
90-
}
91-
92-
if rs.Primary.Attributes["ip"] == "" {
93-
return fmt.Errorf("No IP block is set")
94-
}
93+
func TestAccIpReverse_importBasic(t *testing.T) {
94+
block := os.Getenv("OVH_IP_BLOCK_TEST")
95+
ip := os.Getenv("OVH_IP_TEST")
96+
reverse := os.Getenv("OVH_IP_REVERSE_TEST")
9597

96-
if rs.Primary.Attributes["ipreverse"] == "" {
97-
return fmt.Errorf("No IP is set")
98-
}
98+
config := fmt.Sprintf(testAccIpReverseConfig, block, ip, reverse)
9999

100-
return resourceOvhIpReverseExists(rs.Primary.Attributes["ip"], rs.Primary.Attributes["ipreverse"], config.OVHClient)
101-
}
100+
resource.Test(t, resource.TestCase{
101+
PreCheck: func() { testAccPreCheckIp(t) },
102+
Providers: testAccProviders,
103+
Steps: []resource.TestStep{
104+
{
105+
Config: config,
106+
},
107+
{
108+
ResourceName: "ovh_ip_reverse.reverse",
109+
ImportState: true,
110+
ImportStateVerify: true,
111+
ImportStateIdFunc: testAccIpReverseImportId("ovh_ip_reverse.reverse"),
112+
},
113+
},
114+
})
102115
}
103116

104-
func testAccCheckIpReverseDestroy(s *terraform.State) error {
105-
config := testAccProvider.Meta().(*Config)
106-
for _, rs := range s.RootModule().Resources {
107-
if rs.Type != "ovh_ip_reverse" {
108-
continue
117+
func testAccIpReverseImportId(resourceName string) resource.ImportStateIdFunc {
118+
return func(s *terraform.State) (string, error) {
119+
subnet, ok := s.RootModule().Resources[resourceName]
120+
if !ok {
121+
return "", fmt.Errorf("resource not found: %s", resourceName)
109122
}
110123

111-
err := resourceOvhIpReverseExists(rs.Primary.Attributes["ip"], rs.Primary.Attributes["ipreverse"], config.OVHClient)
112-
if err == nil {
113-
return fmt.Errorf("IP Reverse still exists")
114-
}
124+
return fmt.Sprintf(
125+
"%s:%s",
126+
subnet.Primary.Attributes["ip"],
127+
subnet.Primary.Attributes["ip_reverse"],
128+
), nil
115129
}
116-
return nil
117130
}

0 commit comments

Comments
 (0)