Skip to content

Commit da940b9

Browse files
author
DrummyFloyd
committed
feat(cloud): add gateway ressource
Signed-off-by: DrummyFloyd <[email protected]> Related: ovh#358
1 parent fd109b8 commit da940b9

5 files changed

+457
-0
lines changed

ovh/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ func Provider() *schema.Provider {
173173
"ovh_cloud_project_database_redis_user": resourceCloudProjectDatabaseRedisUser(),
174174
"ovh_cloud_project_database_user": resourceCloudProjectDatabaseUser(),
175175
"ovh_cloud_project_failover_ip_attach": resourceCloudProjectFailoverIpAttach(),
176+
"ovh_cloud_project_gateway": resourceCloudProjectGateway(),
176177
"ovh_cloud_project_kube": resourceCloudProjectKube(),
177178
"ovh_cloud_project_kube_nodepool": resourceCloudProjectKubeNodePool(),
178179
"ovh_cloud_project_kube_oidc": resourceCloudProjectKubeOIDC(),

ovh/resource_cloud_project_gateway.go

+265
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strings"
7+
"time"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
12+
13+
"github.com/ovh/go-ovh/ovh"
14+
)
15+
16+
func resourceOvhCloudProjectGatewayImportState(
17+
d *schema.ResourceData,
18+
meta interface{},
19+
) ([]*schema.ResourceData, error) {
20+
givenId := d.Id()
21+
splitId := strings.SplitN(givenId, "/", 2)
22+
if len(splitId) != 2 {
23+
return nil, fmt.Errorf("Import Id is not OVH_CLOUD_PROJECT/network_id formatted")
24+
}
25+
d.SetId(splitId[1])
26+
d.Set("service_name", splitId[0])
27+
results := make([]*schema.ResourceData, 1)
28+
results[0] = d
29+
return results, nil
30+
}
31+
32+
func resourceCloudProjectGateway() *schema.Resource {
33+
return &schema.Resource{
34+
Create: resourceCloudProjectGatewayCreate,
35+
Read: resourceCloudProjectGatewayRead,
36+
Update: resourceCloudProjectGatewayUpdate,
37+
Delete: resourceCloudProjectGatewayDelete,
38+
Importer: &schema.ResourceImporter{
39+
State: resourceOvhCloudProjectGatewayImportState,
40+
},
41+
42+
Schema: map[string]*schema.Schema{
43+
"service_name": {
44+
Type: schema.TypeString,
45+
Required: true,
46+
ForceNew: true,
47+
DefaultFunc: schema.EnvDefaultFunc("OVH_CLOUD_PROJECT_SERVICE", nil),
48+
Description: "Service name of the resource representing the id of the cloud project.",
49+
},
50+
"name": {
51+
Type: schema.TypeString,
52+
Required: true,
53+
ForceNew: false,
54+
},
55+
"model": {
56+
Type: schema.TypeString,
57+
Required: true,
58+
ForceNew: false,
59+
},
60+
"region": {
61+
Type: schema.TypeString,
62+
Required: true,
63+
ForceNew: true,
64+
},
65+
"network_id": {
66+
Type: schema.TypeString,
67+
Required: true,
68+
ForceNew: true,
69+
},
70+
"subnet_id": {
71+
Type: schema.TypeString,
72+
Required: true,
73+
ForceNew: true,
74+
},
75+
"status": {
76+
Type: schema.TypeString,
77+
Computed: true,
78+
},
79+
},
80+
}
81+
}
82+
83+
func resourceCloudProjectGatewayCreate(d *schema.ResourceData, meta interface{}) error {
84+
config := meta.(*Config)
85+
86+
serviceName := d.Get("service_name").(string)
87+
region := d.Get("region").(string)
88+
network := d.Get("network_id").(string)
89+
subnet := d.Get("subnet_id").(string)
90+
91+
params := &CloudProjectGatewayCreateOpts{
92+
Name: d.Get("name").(string),
93+
Model: d.Get("model").(string),
94+
}
95+
96+
r := &CloudProjectGatewayResponse{}
97+
98+
log.Printf("[DEBUG] Will create public cloud gateway: %s", params)
99+
100+
endpoint := fmt.Sprintf("/cloud/project/%s/region/%s/network/%s/subnet/%s/gateway", serviceName, region, network, subnet)
101+
102+
if err := config.OVHClient.Post(endpoint, params, r); err != nil {
103+
return fmt.Errorf("calling %s with params %s:\n\t %q", endpoint, params, err)
104+
}
105+
106+
log.Printf("[DEBUG] Waiting for Gateway %+v:", r)
107+
108+
stateConf := &resource.StateChangeConf{
109+
Pending: []string{"in-progress"},
110+
Target: []string{"active"},
111+
Refresh: waitForCloudProjectGatewayActive(config.OVHClient, serviceName, r.Id),
112+
Timeout: 10 * time.Minute,
113+
Delay: 10 * time.Second,
114+
MinTimeout: 3 * time.Second,
115+
}
116+
117+
if _, err := stateConf.WaitForState(); err != nil {
118+
return fmt.Errorf("waiting for gateway (%s): %s", params, err)
119+
}
120+
121+
ro := &CloudProjectOperationResponse{}
122+
endpointo := fmt.Sprintf("/cloud/project/%s/operation/%s", serviceName, r.Id)
123+
if err := config.OVHClient.Get(endpointo, ro); err != nil {
124+
return nil
125+
}
126+
log.Printf("[DEBUG] Created Gateway %+v", ro)
127+
128+
gatewayId := ro.ResourceId
129+
130+
// set id
131+
d.SetId(*gatewayId)
132+
133+
return resourceCloudProjectGatewayRead(d, meta)
134+
}
135+
136+
func resourceCloudProjectGatewayRead(d *schema.ResourceData, meta interface{}) error {
137+
config := meta.(*Config)
138+
139+
serviceName := d.Get("service_name").(string)
140+
region := d.Get("region").(string)
141+
142+
r := &CloudProjectGatewayResponse{}
143+
144+
log.Printf("[DEBUG] Will read public cloud gateway for project: %s, region: %s, id: %s", serviceName, region, d.Id())
145+
146+
endpoint := fmt.Sprintf("/cloud/project/%s/region/%s/gateway/%s", serviceName, region, d.Id())
147+
148+
if err := config.OVHClient.Get(endpoint, r); err != nil {
149+
return helpers.CheckDeleted(d, err, endpoint)
150+
}
151+
152+
d.Set("name", r.Name)
153+
d.Set("model", r.Model)
154+
d.Set("status", r.Status)
155+
d.Set("region", region)
156+
d.SetId(r.Id)
157+
d.Set("service_name", serviceName)
158+
159+
// TODO : a voir les interfaces et les extras info.
160+
161+
log.Printf("[DEBUG] Read Public Cloud Gateway %+v", r)
162+
return nil
163+
}
164+
165+
func resourceCloudProjectGatewayUpdate(d *schema.ResourceData, meta interface{}) error {
166+
config := meta.(*Config)
167+
serviceName := d.Get("service_name").(string)
168+
params := &CloudProjectGatewayUpdateOpts{
169+
Name: d.Get("name").(string),
170+
Model: d.Get("model").(string),
171+
}
172+
region := d.Get("region").(string)
173+
174+
log.Printf("[DEBUG] Will update public cloud gateway: %s", params)
175+
176+
endpoint := fmt.Sprintf("/cloud/project/%s/region/%s/gateway/%s", serviceName, region, d.Id())
177+
178+
if err := config.OVHClient.Put(endpoint, params, nil); err != nil {
179+
return fmt.Errorf("calling %s with params %s:\n\t %q", endpoint, params, err)
180+
}
181+
182+
log.Printf("[DEBUG] Updated Public cloud %s Gateway %s:", serviceName, d.Id())
183+
184+
return resourceCloudProjectGatewayRead(d, meta)
185+
}
186+
187+
func resourceCloudProjectGatewayDelete(d *schema.ResourceData, meta interface{}) error {
188+
config := meta.(*Config)
189+
serviceName := d.Get("service_name").(string)
190+
region := d.Get("region").(string)
191+
192+
id := d.Id()
193+
194+
log.Printf("[DEBUG] Will delete public cloud gateway for project: %s, region: %s, id: %s", serviceName, region, id)
195+
196+
endpoint := fmt.Sprintf("/cloud/project/%s/region/%s/gateway/%s", serviceName, region, id)
197+
198+
r := &CloudProjectOperationResponse{}
199+
if err := config.OVHClient.Delete(endpoint, r); err != nil {
200+
return fmt.Errorf("calling %s:\n\t %q", endpoint, err)
201+
}
202+
203+
stateConf := &resource.StateChangeConf{
204+
Pending: []string{"in-progress"},
205+
Target: []string{"completed"},
206+
Refresh: waitForCloudProjectGatewayDelete(config.OVHClient, serviceName, r.Id),
207+
Timeout: 10 * time.Minute,
208+
Delay: 10 * time.Second,
209+
MinTimeout: 3 * time.Second,
210+
}
211+
212+
if _, err := stateConf.WaitForState(); err != nil {
213+
return fmt.Errorf("deleting for gateway (%s): %s", id, err)
214+
}
215+
216+
d.SetId("")
217+
218+
log.Printf("[DEBUG] Deleted Public Cloud %s Gateway %s", serviceName, id)
219+
return nil
220+
}
221+
222+
// AttachmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
223+
// an Attachment Task.
224+
func waitForCloudProjectGatewayActive(c *ovh.Client, serviceName, OperationId string) resource.StateRefreshFunc {
225+
return func() (interface{}, string, error) {
226+
ro := &CloudProjectOperationResponse{}
227+
endpoint := fmt.Sprintf("/cloud/project/%s/operation/%s", serviceName, OperationId)
228+
if err := c.Get(endpoint, ro); err != nil {
229+
return ro, "", err
230+
}
231+
232+
log.Printf("[DEBUG] Pending Operation: %+v", ro)
233+
234+
if ro.ResourceId != nil {
235+
rg := &CloudProjectGatewayResponse{}
236+
gatewayId := ro.ResourceId
237+
endpoint := fmt.Sprintf("/cloud/project/%s/region/%s/gateway/%s", serviceName, ro.Regions[0], *gatewayId)
238+
if err := c.Get(endpoint, rg); err != nil {
239+
return rg, "", err
240+
}
241+
return rg, rg.Status, nil
242+
}
243+
244+
return ro, ro.Status, nil
245+
}
246+
}
247+
248+
// AttachmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
249+
// an Attachment Task.
250+
func waitForCloudProjectGatewayDelete(c *ovh.Client, serviceName, OperationId string) resource.StateRefreshFunc {
251+
return func() (interface{}, string, error) {
252+
r := &CloudProjectOperationResponse{}
253+
endpoint := fmt.Sprintf("/cloud/project/%s/operation/%s", serviceName, OperationId)
254+
if err := c.Get(endpoint, r); err != nil {
255+
if errOvh, ok := err.(*ovh.APIError); ok && errOvh.Code == 404 {
256+
log.Printf("[DEBUG] gateway id %s on project %s deleted", OperationId, serviceName)
257+
return r, "DELETED", nil
258+
} else {
259+
return r, "", err
260+
}
261+
}
262+
log.Printf("[DEBUG] Pending Gateway: %+v", r)
263+
return r, r.Status, nil
264+
}
265+
}
+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
9+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
10+
)
11+
12+
var testAccCloudProjectGatewayConfig = `
13+
resource "ovh_cloud_project_network_private" "mypriv" {
14+
service_name = "%s"
15+
vlan_id = "%d"
16+
name = "%s"
17+
regions = ["%s"]
18+
}
19+
20+
resource "ovh_cloud_project_network_private_subnet" "myprivsub" {
21+
service_name = ovh_cloud_project_network_private.mypriv.service_name
22+
network_id = ovh_cloud_project_network_private.mypriv.id
23+
region = "%s"
24+
start = "10.0.0.2"
25+
end = "10.0.255.254"
26+
network = "10.0.0.0/16"
27+
dhcp = true
28+
}
29+
30+
resource "ovh_cloud_project_gateway" "gateway" {
31+
service_name = ovh_cloud_project_network_private.mypriv.service_name
32+
name = "%s"
33+
model = "s"
34+
region = ovh_cloud_project_network_private_subnet.myprivsub.region
35+
network_id = tolist(ovh_cloud_project_network_private.mypriv.regions_attributes[*].openstackid)[0]
36+
subnet_id = ovh_cloud_project_network_private_subnet.myprivsub.id
37+
}
38+
`
39+
40+
func TestAccCloudProjectGateway(t *testing.T) {
41+
name := acctest.RandomWithPrefix(test_prefix)
42+
gatewayName := acctest.RandomWithPrefix(test_prefix)
43+
vlanId := acctest.RandIntRange(100, 200)
44+
region := os.Getenv("OVH_CLOUD_PROJECT_KUBE_REGION_TEST")
45+
46+
config := fmt.Sprintf(
47+
testAccCloudProjectGatewayConfig,
48+
os.Getenv("OVH_CLOUD_PROJECT_SERVICE_TEST"),
49+
vlanId,
50+
name,
51+
region,
52+
region,
53+
gatewayName,
54+
)
55+
56+
resource.Test(t, resource.TestCase{
57+
PreCheck: func() {
58+
testAccPreCheckCloud(t)
59+
testAccCheckCloudProjectExists(t)
60+
},
61+
62+
Providers: testAccProviders,
63+
Steps: []resource.TestStep{
64+
{
65+
Config: config,
66+
Check: resource.ComposeTestCheckFunc(
67+
resource.TestCheckResourceAttrSet("ovh_cloud_project_gateway.gateway", "service_name"),
68+
resource.TestCheckResourceAttrSet("ovh_cloud_project_gateway.gateway", "network_id"),
69+
resource.TestCheckResourceAttrSet("ovh_cloud_project_gateway.gateway", "subnet_id"),
70+
resource.TestCheckResourceAttrSet("ovh_cloud_project_gateway.gateway", "model"),
71+
resource.TestCheckResourceAttr("ovh_cloud_project_gateway.gateway", "region", region),
72+
resource.TestCheckResourceAttr("ovh_cloud_project_gateway.gateway", "name", gatewayName),
73+
resource.TestCheckResourceAttr("ovh_cloud_project_gateway.gateway", "model", "s"),
74+
),
75+
},
76+
},
77+
})
78+
}

0 commit comments

Comments
 (0)