Skip to content

Commit 687e2a5

Browse files
authored
Merge pull request #778 from Tiboau/resource_volume
add region resource volume
2 parents 0200ed8 + 712f1c8 commit 687e2a5

File tree

5 files changed

+1098
-0
lines changed

5 files changed

+1098
-0
lines changed

ovh/provider_new.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ func (p *OvhProvider) Resources(_ context.Context) []func() resource.Resource {
220220
return []func() resource.Resource{
221221
NewCloudProjectAlertingResource,
222222
NewCloudProjectGatewayInterfaceResource,
223+
NewCloudProjectVolumeResource,
223224
NewDbaasLogsTokenResource,
224225
NewDedicatedServerResource,
225226
NewDomainZoneDnssecResource,

ovh/resource_cloud_project_volume.go

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
package ovh
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/url"
7+
"time"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
11+
"github.com/ovh/go-ovh/ovh"
12+
)
13+
14+
var _ resource.ResourceWithConfigure = (*cloudProjectVolumeResource)(nil)
15+
16+
func NewCloudProjectVolumeResource() resource.Resource {
17+
return &cloudProjectVolumeResource{}
18+
}
19+
20+
type cloudProjectVolumeResource struct {
21+
config *Config
22+
}
23+
24+
func (r *cloudProjectVolumeResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
25+
resp.TypeName = req.ProviderTypeName + "_cloud_project_volume"
26+
}
27+
28+
func (d *cloudProjectVolumeResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
29+
if req.ProviderData == nil {
30+
return
31+
}
32+
33+
config, ok := req.ProviderData.(*Config)
34+
if !ok {
35+
resp.Diagnostics.AddError(
36+
"Unexpected Resource Configure Type",
37+
fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData),
38+
)
39+
return
40+
}
41+
42+
d.config = config
43+
}
44+
45+
func (d *cloudProjectVolumeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
46+
resp.Schema = CloudProjectVolumeResourceSchema(ctx)
47+
}
48+
49+
func (r *cloudProjectVolumeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
50+
var data, responseData CloudProjectVolumeModelOp
51+
52+
// Read Terraform plan data into the model
53+
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
54+
if resp.Diagnostics.HasError() {
55+
return
56+
}
57+
58+
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume"
59+
if err := r.config.OVHClient.Post(endpoint, data.ToCreate(), &responseData); err != nil {
60+
resp.Diagnostics.AddError(
61+
fmt.Sprintf("Error calling Post %s", endpoint),
62+
err.Error(),
63+
)
64+
return
65+
}
66+
67+
resWait, err := r.WaitForVolumeCreation(ctx, r.config.OVHClient, data.ServiceName.ValueString(), responseData.Id.ValueString())
68+
if err != nil {
69+
resp.Diagnostics.AddError(
70+
fmt.Sprintf("Error calling Operation"),
71+
err.Error(),
72+
)
73+
return
74+
}
75+
76+
resVol := &CloudProjectVolumeModelOp{}
77+
endpoint = "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(resWait.(string))
78+
if err := r.config.OVHClient.Get(endpoint, resVol); err != nil {
79+
resp.Diagnostics.AddError(
80+
fmt.Sprintf("Error calling Post %s", endpoint),
81+
err.Error(),
82+
)
83+
return
84+
}
85+
86+
data.MergeWith(resVol)
87+
88+
// Save data into Terraform state
89+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
90+
}
91+
92+
func (d *cloudProjectVolumeResource) WaitForVolumeCreation(ctx context.Context, client *ovh.Client, serviceName, operationId string) (interface{}, error) {
93+
stateConf := &retry.StateChangeConf{
94+
Pending: []string{"null", "in-progress", "created", ""},
95+
Target: []string{"completed"},
96+
Refresh: func() (interface{}, string, error) {
97+
res := &CloudProjectVolumeModelOp{}
98+
endpoint := "/cloud/project/" + url.PathEscape(serviceName) + "/operation/" + url.PathEscape(operationId)
99+
err := client.GetWithContext(ctx, endpoint, res)
100+
if err != nil {
101+
return res, "", err
102+
}
103+
return res.ResourceId.ValueString(), res.Status.ValueString(), nil
104+
},
105+
Timeout: 360 * time.Second,
106+
Delay: 10 * time.Second,
107+
MinTimeout: 3 * time.Second,
108+
}
109+
110+
res, err := stateConf.WaitForStateContext(ctx)
111+
112+
return res, err
113+
}
114+
115+
func (r *cloudProjectVolumeResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
116+
var data, responseData CloudProjectVolumeModelOp
117+
118+
// Read Terraform prior state data into the model
119+
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
120+
if resp.Diagnostics.HasError() {
121+
return
122+
}
123+
124+
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString())
125+
126+
if err := r.config.OVHClient.Get(endpoint, &responseData); err != nil {
127+
resp.Diagnostics.AddError(
128+
fmt.Sprintf("Error calling Get %s", endpoint),
129+
err.Error(),
130+
)
131+
return
132+
}
133+
134+
data.MergeWith(&responseData)
135+
136+
// Save updated data into Terraform state
137+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
138+
}
139+
140+
func (r *cloudProjectVolumeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
141+
var data, planData, responseData CloudProjectVolumeModelOp
142+
143+
// Read Terraform plan data into the model
144+
resp.Diagnostics.Append(req.Plan.Get(ctx, &planData)...)
145+
if resp.Diagnostics.HasError() {
146+
return
147+
}
148+
149+
// Read Terraform prior state data into the model
150+
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
151+
if resp.Diagnostics.HasError() {
152+
return
153+
}
154+
155+
// Update resource
156+
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString())
157+
if err := r.config.OVHClient.Put(endpoint, planData.ToUpdate(), nil); err != nil {
158+
resp.Diagnostics.AddError(
159+
fmt.Sprintf("Error calling Post %s", endpoint),
160+
err.Error(),
161+
)
162+
return
163+
}
164+
165+
// Read updated resource
166+
endpoint = "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString())
167+
if err := r.config.OVHClient.Get(endpoint, &responseData); err != nil {
168+
resp.Diagnostics.AddError(
169+
fmt.Sprintf("Error calling Get %s", endpoint),
170+
err.Error(),
171+
)
172+
return
173+
}
174+
175+
responseData.MergeWith(&planData)
176+
177+
// Save updated data into Terraform state
178+
resp.Diagnostics.Append(resp.State.Set(ctx, &responseData)...)
179+
}
180+
181+
func (r *cloudProjectVolumeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
182+
var data CloudProjectVolumeModelOp
183+
184+
// Read Terraform prior state data into the model
185+
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
186+
187+
if resp.Diagnostics.HasError() {
188+
return
189+
}
190+
191+
// Delete API call logic
192+
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString())
193+
if err := r.config.OVHClient.Delete(endpoint, nil); err != nil {
194+
resp.Diagnostics.AddError(
195+
fmt.Sprintf("Error calling Delete %s", endpoint),
196+
err.Error(),
197+
)
198+
}
199+
}

0 commit comments

Comments
 (0)