Skip to content

Commit 7d99999

Browse files
author
Arthur Amstutz
committed
feat: Add resource ovh_vrack_ipv6
1 parent c896b01 commit 7d99999

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed

ovh/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ func Provider() *schema.Provider {
281281
"ovh_vrack_dedicated_server": resourceVrackDedicatedServer(),
282282
"ovh_vrack_dedicated_server_interface": resourceVrackDedicatedServerInterface(),
283283
"ovh_vrack_ip": resourceVrackIp(),
284+
"ovh_vrack_ipv6": resourceVrackIpV6(),
284285
"ovh_vrack_iploadbalancing": resourceVrackIpLoadbalancing(),
285286
},
286287

ovh/resource_vrack_ipv6.go

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"net/url"
6+
"strings"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
10+
)
11+
12+
func resourceVrackIpV6() *schema.Resource {
13+
return &schema.Resource{
14+
Create: resourceVrackIpv6Create,
15+
Read: resourceVrackIpv6Read,
16+
Delete: resourceVrackIpv6Delete,
17+
Importer: &schema.ResourceImporter{
18+
State: resourceVrackIpv6ImportState,
19+
},
20+
21+
Schema: map[string]*schema.Schema{
22+
"service_name": {
23+
Type: schema.TypeString,
24+
Required: true,
25+
ForceNew: true,
26+
Description: "The internal name of your vrack",
27+
},
28+
"block": {
29+
Type: schema.TypeString,
30+
Required: true,
31+
ForceNew: true,
32+
Description: "IPv6 CIDR notation (e.g., 2001:41d0::/128)",
33+
ValidateFunc: func(i interface{}, _ string) ([]string, []error) {
34+
if err := helpers.ValidateIpBlock(i.(string)); err != nil {
35+
return nil, []error{err}
36+
}
37+
return nil, nil
38+
},
39+
},
40+
},
41+
}
42+
}
43+
44+
func resourceVrackIpv6ImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
45+
givenId := d.Id()
46+
splitId := strings.SplitN(givenId, ",", 2)
47+
if len(splitId) != 2 {
48+
return nil, fmt.Errorf("import ID is not SERVICE_NAME,IPv6-block formatted")
49+
}
50+
serviceName := splitId[0]
51+
block := splitId[1]
52+
53+
d.SetId(fmt.Sprintf("vrack_%s-block_%s", serviceName, block))
54+
d.Set("service_name", serviceName)
55+
d.Set("block", block)
56+
57+
return []*schema.ResourceData{d}, nil
58+
}
59+
60+
func resourceVrackIpv6Create(d *schema.ResourceData, meta interface{}) error {
61+
config := meta.(*Config)
62+
63+
serviceName := d.Get("service_name").(string)
64+
65+
opts := (&VrackIpCreateOpts{}).FromResource(d)
66+
task := VrackTask{}
67+
68+
endpoint := fmt.Sprintf("/vrack/%s/ipv6", url.PathEscape(serviceName))
69+
if err := config.OVHClient.Post(endpoint, opts, &task); err != nil {
70+
return fmt.Errorf("error calling POST %s with opts %v:\n\t %q", endpoint, opts, err)
71+
}
72+
73+
if err := waitForVrackTask(&task, config.OVHClient); err != nil {
74+
return fmt.Errorf("error waiting for vrack (%s) to attach ipv6 %v: %s", serviceName, opts, err)
75+
}
76+
77+
d.SetId(fmt.Sprintf("vrack_%s-block_%s", serviceName, opts.Block))
78+
79+
return resourceVrackIpv6Read(d, meta)
80+
}
81+
82+
func resourceVrackIpv6Read(d *schema.ResourceData, meta interface{}) error {
83+
config := meta.(*Config)
84+
85+
serviceName := d.Get("service_name").(string)
86+
block := d.Get("block").(string)
87+
88+
endpoint := fmt.Sprintf("/vrack/%s/ipv6/%s",
89+
url.PathEscape(serviceName),
90+
url.PathEscape(block),
91+
)
92+
93+
if err := config.OVHClient.Get(endpoint, nil); err != nil {
94+
return fmt.Errorf("failed to get vrack-ipv6 link: %w", err)
95+
}
96+
97+
return nil
98+
}
99+
100+
func resourceVrackIpv6Delete(d *schema.ResourceData, meta interface{}) error {
101+
config := meta.(*Config)
102+
103+
serviceName := d.Get("service_name").(string)
104+
block := d.Get("block").(string)
105+
task := VrackTask{}
106+
107+
endpoint := fmt.Sprintf("/vrack/%s/ipv6/%s",
108+
url.PathEscape(serviceName),
109+
url.PathEscape(block),
110+
)
111+
112+
if err := config.OVHClient.Delete(endpoint, &task); err != nil {
113+
return fmt.Errorf("error calling DELETE %s with %s/%s:\n\t %q", endpoint, serviceName, block, err)
114+
}
115+
116+
if err := waitForVrackTask(&task, config.OVHClient); err != nil {
117+
return fmt.Errorf("error waiting for vrack (%s) to detach ip (%s): %s", serviceName, block, err)
118+
}
119+
120+
d.SetId("")
121+
122+
return nil
123+
}

ovh/resource_vrack_ipv6_test.go

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/url"
7+
"os"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
12+
"github.com/ovh/go-ovh/ovh"
13+
)
14+
15+
func init() {
16+
resource.AddTestSweepers("ovh_vrack_ipv6", &resource.Sweeper{
17+
Name: "ovh_vrack_ipv6",
18+
F: testSweepVrackIPv6,
19+
})
20+
}
21+
22+
func testSweepVrackIPv6(region string) error {
23+
client, err := sharedClientForRegion(region)
24+
if err != nil {
25+
return fmt.Errorf("error getting client: %s", err)
26+
}
27+
28+
vrackId := os.Getenv("OVH_VRACK_SERVICE_TEST")
29+
if vrackId == "" {
30+
log.Print("[DEBUG] OVH_VRACK_SERVICE_TEST is not set. No vrack_ipv6 to sweep")
31+
return nil
32+
}
33+
34+
ipBlock := os.Getenv("OVH_IP_V6_BLOCK_TEST")
35+
if ipBlock == "" {
36+
log.Print("[DEBUG] OVH_CLOUD_PROJECT_SERVICE_TEST is not set. No vrack_ipv6 to sweep")
37+
return nil
38+
}
39+
40+
endpoint := fmt.Sprintf("/vrack/%s/ipv6/%s",
41+
url.PathEscape(vrackId),
42+
url.PathEscape(ipBlock),
43+
)
44+
45+
if err := client.Get(endpoint, nil); err != nil {
46+
if errOvh, ok := err.(*ovh.APIError); ok && errOvh.Code == 404 {
47+
return nil
48+
}
49+
return err
50+
}
51+
52+
task := VrackTask{}
53+
if err := client.Delete(endpoint, &task); err != nil {
54+
return fmt.Errorf("Error calling DELETE %s with %s/%s:\n\t %q", endpoint, vrackId, ipBlock, err)
55+
}
56+
57+
if err := waitForVrackTask(&task, client); err != nil {
58+
return fmt.Errorf("Error waiting for vrack (%s) to detach ipv6 (%s): %s", vrackId, ipBlock, err)
59+
}
60+
61+
return nil
62+
}
63+
64+
func TestAccVrackIPv6_basic(t *testing.T) {
65+
serviceName := os.Getenv("OVH_VRACK_SERVICE_TEST")
66+
ipBlock := os.Getenv("OVH_IP_V6_BLOCK_TEST")
67+
68+
resource.Test(t, resource.TestCase{
69+
PreCheck: func() {
70+
testAccPreCheckVRack(t)
71+
},
72+
Providers: testAccProviders,
73+
Steps: []resource.TestStep{
74+
{
75+
Config: fmt.Sprintf(`
76+
resource "ovh_vrack_ipv6" "vrack-ipv6" {
77+
service_name = "%s"
78+
block = "%s"
79+
}
80+
`, serviceName, ipBlock),
81+
Check: resource.ComposeTestCheckFunc(
82+
resource.TestCheckResourceAttr("ovh_vrack_ipv6.vrack-ipv6", "service_name", serviceName),
83+
resource.TestCheckResourceAttr("ovh_vrack_ipv6.vrack-ipv6", "block", ipBlock),
84+
),
85+
},
86+
},
87+
})
88+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
subcategory : "vRack"
3+
---
4+
5+
# ovh_vrack_ipv6
6+
7+
Attach an IPv6 block to a VRack.
8+
9+
10+
## Example Usage
11+
12+
```hcl
13+
resource "ovh_vrack_ipv6" "vrack_block" {
14+
service_name = "<vRack service name>"
15+
block = "<ipv6 block>"
16+
}
17+
```
18+
19+
## Argument Reference
20+
21+
The following arguments are supported:
22+
23+
* `service_name` - (Required) The internal name of your vrack
24+
* `block` - (Required) Your IPv6 block.
25+
26+
## Attributes Reference
27+
28+
No additional attribute is exported.
29+
30+
31+
## Import
32+
33+
Attachment of an IPv6 block and a VRack can be imported using the `service_name` (vRack identifier) and the `block` (IPv6 block), separated by "," E.g.,
34+
35+
```bash
36+
$ terraform import ovh_vrack_ipv6.myattach "<service_name>,<block>"
37+
```

0 commit comments

Comments
 (0)