Skip to content

Commit 4432c49

Browse files
authored
Merge pull request #234 from albeego/master
Adding failover IP address data and resource blocks for lookup and at…
2 parents b0d920c + cf80ced commit 4432c49

12 files changed

+528
-1
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Terraform OVH Provider
55
- [![Gitter chat](https://badges.gitter.im/hashicorp-terraform/Lobby.png)](https://gitter.im/hashicorp-terraform/Lobby)
66
- Mailing list: [Google Groups](http://groups.google.com/group/terraform-tool)
77

8-
<img src="https://cdn.rawgit.com/hashicorp/terraform-website/master/content/source/assets/images/logo-hashicorp.svg" width="600px">
8+
<img alt="chat on gitter" src="https://cdn.rawgit.com/hashicorp/terraform-website/master/content/source/assets/images/logo-hashicorp.svg" width="600px">
99

1010
Requirements
1111
------------
@@ -90,6 +90,9 @@ export OVH_IP_BLOCK_TEST="..."
9090
export OVH_IP_REVERSE_TEST="..."
9191
export OVH_IPLB_SERVICE_TEST="..."
9292
export OVH_CLOUD_PROJECT_SERVICE_TEST="..."
93+
export OVH_CLOUD_PROJECT_FAILOVER_IP_TEST="..."
94+
export OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_1_TEST="..."
95+
export OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_2_TEST="..."
9396
export OVH_VRACK_SERVICE_TEST="..."
9497
export OVH_ZONE_TEST="..."
9598

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package ovh
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
5+
)
6+
7+
func dataSourceCloudProjectFailoverIpAttach() *schema.Resource {
8+
return &schema.Resource{
9+
Read: func(d *schema.ResourceData, meta interface{}) error {
10+
return resourceCloudProjectFailoverIpAttachRead(d, meta)
11+
},
12+
Schema: resourceCloudProjectFailoverIpAttachSchema(),
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
)
10+
11+
const testAccDataSourceCloudProjectFailoverIpAttach = `
12+
data "ovh_cloud_project_failover_ip_attach" "myfailoverip" {
13+
service_name = "%s"
14+
ip = "%s"
15+
}
16+
`
17+
18+
func TestAccDataSourceCloudProjectFailoverIpAttach(t *testing.T) {
19+
serviceName := os.Getenv("OVH_CLOUD_PROJECT_SERVICE_TEST")
20+
ipAddress := os.Getenv("OVH_CLOUD_PROJECT_FAILOVER_IP_TEST")
21+
config := fmt.Sprintf(
22+
testAccDataSourceCloudProjectFailoverIpAttach,
23+
serviceName,
24+
ipAddress,
25+
)
26+
27+
resource.Test(t, resource.TestCase{
28+
PreCheck: func() { testAccPreCheckFailoverIpAttach(t) },
29+
30+
Providers: testAccProviders,
31+
Steps: []resource.TestStep{
32+
{
33+
Config: config,
34+
Check: resource.ComposeTestCheckFunc(
35+
resource.TestCheckResourceAttr(
36+
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
37+
"service_name",
38+
serviceName,
39+
),
40+
resource.TestCheckResourceAttr(
41+
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
42+
"ip",
43+
ipAddress,
44+
),
45+
resource.TestCheckResourceAttrSet(
46+
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
47+
"id",
48+
),
49+
resource.TestCheckResourceAttrSet(
50+
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
51+
"routed_to",
52+
),
53+
),
54+
},
55+
},
56+
})
57+
}

ovh/provider.go

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func Provider() *schema.Provider {
4646
"ovh_cloud_project_containerregistries": dataSourceCloudProjectContainerRegistries(),
4747
"ovh_cloud_project_containerregistry": dataSourceCloudProjectContainerRegistry(),
4848
"ovh_cloud_project_containerregistry_users": dataSourceCloudProjectContainerRegistryUsers(),
49+
"ovh_cloud_project_failover_ip_attach": dataSourceCloudProjectFailoverIpAttach(),
4950
"ovh_cloud_project_kube": dataSourceCloudProjectKube(),
5051
"ovh_cloud_project_region": dataSourceCloudProjectRegion(),
5152
"ovh_cloud_project_regions": dataSourceCloudProjectRegions(),
@@ -84,6 +85,7 @@ func Provider() *schema.Provider {
8485
"ovh_cloud_project": resourceCloudProject(),
8586
"ovh_cloud_project_containerregistry": resourceCloudProjectContainerRegistry(),
8687
"ovh_cloud_project_containerregistry_user": resourceCloudProjectContainerRegistryUser(),
88+
"ovh_cloud_project_failover_ip_attach": resourceCloudProjectFailoverIpAttach(),
8789
"ovh_cloud_project_kube": resourceCloudProjectKube(),
8890
"ovh_cloud_project_kube_nodepool": resourceCloudProjectKubeNodePool(),
8991
"ovh_cloud_project_network_private": resourceCloudProjectNetworkPrivate(),

ovh/provider_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ func testAccPreCheckCloud(t *testing.T) {
120120
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_SERVICE_TEST")
121121
}
122122

123+
// Checks that the environment variables needed for the /cloud/project/{projectId}/ip/failover acceptance tests
124+
// are set.
125+
func testAccPreCheckFailoverIpAttach(t *testing.T) {
126+
testAccPreCheckCredentials(t)
127+
testAccPreCheckCloud(t)
128+
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_FAILOVER_IP_TEST")
129+
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_1_TEST")
130+
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_2_TEST")
131+
}
132+
123133
// Checks that the environment variables needed for the /cloud/{cloudId}/kube acceptance tests
124134
// are set.
125135
func testAccPreCheckKubernetes(t *testing.T) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
6+
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
7+
"log"
8+
"net/url"
9+
)
10+
11+
func resourceCloudProjectFailoverIpAttach() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceCloudProjectFailoverIpAttachCreate,
14+
Read: resourceCloudProjectFailoverIpAttachRead,
15+
Delete: resourceCloudProjectFailoverIpAttachDelete,
16+
17+
Importer: &schema.ResourceImporter{
18+
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
19+
return []*schema.ResourceData{d}, nil
20+
},
21+
},
22+
23+
Schema: resourceCloudProjectFailoverIpAttachSchema(),
24+
}
25+
}
26+
27+
func resourceCloudProjectFailoverIpAttachSchema() map[string]*schema.Schema {
28+
return map[string]*schema.Schema{
29+
"service_name": {
30+
Type: schema.TypeString,
31+
Description: "The service name",
32+
ForceNew: true,
33+
Required: true,
34+
},
35+
36+
"block": {
37+
Type: schema.TypeString,
38+
Description: "IP block",
39+
Optional: true,
40+
Computed: true,
41+
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
42+
err := helpers.ValidateIp(v.(string))
43+
if err != nil {
44+
errors = append(errors, err)
45+
}
46+
return
47+
},
48+
},
49+
"continent_code": {
50+
Type: schema.TypeString,
51+
Description: "Ip continent",
52+
Optional: true,
53+
Computed: true,
54+
},
55+
"geo_loc": {
56+
Type: schema.TypeString,
57+
Description: "Ip location",
58+
Optional: true,
59+
Computed: true,
60+
},
61+
"id": {
62+
Type: schema.TypeString,
63+
Description: "Ip id",
64+
Computed: true,
65+
},
66+
"ip": {
67+
Type: schema.TypeString,
68+
Description: "Ip",
69+
Optional: true,
70+
Computed: true,
71+
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
72+
err := helpers.ValidateIp(v.(string))
73+
if err != nil {
74+
errors = append(errors, err)
75+
}
76+
return
77+
},
78+
},
79+
"progress": {
80+
Type: schema.TypeInt,
81+
Description: "Current operation progress in percent",
82+
Computed: true,
83+
},
84+
"routed_to": {
85+
Type: schema.TypeString,
86+
Description: "Instance where ip is routed to",
87+
Computed: true,
88+
Optional: true,
89+
},
90+
"status": {
91+
Type: schema.TypeString,
92+
Description: "Ip status",
93+
Computed: true,
94+
},
95+
"sub_type": {
96+
Type: schema.TypeString,
97+
Description: "IP sub type",
98+
Computed: true,
99+
},
100+
}
101+
}
102+
103+
func resourceCloudProjectFailoverIpAttachRead(d *schema.ResourceData, meta interface{}) error {
104+
config := meta.(*Config)
105+
106+
serviceName := d.Get("service_name").(string)
107+
108+
log.Printf("[DEBUG] Will read cloud project ip addresses %s", serviceName)
109+
endpoint := fmt.Sprintf("/cloud/project/%s/ip/failover",
110+
url.PathEscape(serviceName),
111+
)
112+
113+
ips := []FailoverIp{}
114+
if err := config.OVHClient.Get(endpoint, &ips); err != nil {
115+
return fmt.Errorf("Error calling GET %s:\n\t %q", endpoint, err)
116+
}
117+
118+
match := false
119+
for _, ip := range ips {
120+
if ip.Ip == d.Get("ip").(string) {
121+
for k, v := range ip.ToMap() {
122+
match = true
123+
if k == "id" {
124+
d.SetId(v.(string))
125+
} else {
126+
err := d.Set(k, v)
127+
if err != nil {
128+
return err
129+
}
130+
}
131+
}
132+
}
133+
}
134+
135+
if !match {
136+
return fmt.Errorf("your query returned no results, " +
137+
"please change your search criteria and try again")
138+
}
139+
140+
return nil
141+
}
142+
143+
func resourceCloudProjectFailoverIpAttachCreate(d *schema.ResourceData, meta interface{}) error {
144+
145+
serviceName := d.Get("service_name").(string)
146+
147+
config := meta.(*Config)
148+
149+
//Fetch Failover IP address to populate ID field
150+
log.Printf("[DEBUG] Will read cloud project ip addresses %s", serviceName)
151+
endpoint := fmt.Sprintf("/cloud/project/%s/ip/failover",
152+
url.PathEscape(serviceName),
153+
)
154+
155+
ips := []FailoverIp{}
156+
if err := config.OVHClient.Get(endpoint, &ips); err != nil {
157+
return fmt.Errorf("Error calling GET %s:\n\t %q", endpoint, err)
158+
}
159+
160+
match := false
161+
for _, ip := range ips {
162+
if ip.Ip == d.Get("ip").(string) {
163+
for k, v := range ip.ToMap() {
164+
match = true
165+
if k == "id" {
166+
d.SetId(v.(string))
167+
}
168+
}
169+
}
170+
}
171+
172+
if !match {
173+
return fmt.Errorf("your query returned no results, " +
174+
"please change your search criteria and try again")
175+
}
176+
177+
id := d.Get("id").(string)
178+
179+
log.Printf("[DEBUG] Will attach failover ip to an instance: %s", serviceName)
180+
opts := (&ProjectIpFailoverAttachCreation{}).FromResource(d)
181+
endpoint = fmt.Sprintf("/cloud/project/%s/ip/failover/%s/attach",
182+
url.PathEscape(serviceName),
183+
url.PathEscape(id),
184+
)
185+
186+
ip := &FailoverIp{}
187+
if err := config.OVHClient.Post(endpoint, opts, ip); err != nil {
188+
return fmt.Errorf("calling Put %s: %q", endpoint, err)
189+
}
190+
191+
for k, v := range ip.ToMap() {
192+
match = true
193+
if k != "id" {
194+
err := d.Set(k, v)
195+
if err != nil {
196+
return err
197+
}
198+
}
199+
}
200+
201+
for d.Get("status").(string) == "operationPending" {
202+
if err := resourceCloudProjectFailoverIpAttachRead(d, meta); err != nil {
203+
return err
204+
}
205+
}
206+
207+
return nil
208+
}
209+
210+
func resourceCloudProjectFailoverIpAttachDelete(d *schema.ResourceData, meta interface{}) error {
211+
// Failover IPs cannot be deleted, the best that can be done in this instance is to check it exists
212+
if err := resourceCloudProjectFailoverIpAttachRead(d, meta); err != nil {
213+
return err
214+
}
215+
return nil
216+
}

0 commit comments

Comments
 (0)