-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add region resource volume #778
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,208 @@ | ||||||
package ovh | ||||||
|
||||||
import ( | ||||||
"context" | ||||||
"fmt" | ||||||
"net/url" | ||||||
"time" | ||||||
|
||||||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" | ||||||
"github.com/ovh/go-ovh/ovh" | ||||||
) | ||||||
|
||||||
var _ resource.ResourceWithConfigure = (*cloudProjectVolumeResource)(nil) | ||||||
|
||||||
func NewCloudProjectVolumeResource() resource.Resource { | ||||||
return &cloudProjectVolumeResource{} | ||||||
} | ||||||
|
||||||
type cloudProjectVolumeResource struct { | ||||||
config *Config | ||||||
} | ||||||
|
||||||
func (r *cloudProjectVolumeResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||||||
resp.TypeName = req.ProviderTypeName + "_cloud_project_volume" | ||||||
} | ||||||
|
||||||
func (d *cloudProjectVolumeResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||||||
if req.ProviderData == nil { | ||||||
return | ||||||
} | ||||||
|
||||||
config, ok := req.ProviderData.(*Config) | ||||||
if !ok { | ||||||
resp.Diagnostics.AddError( | ||||||
"Unexpected Resource Configure Type", | ||||||
fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
d.config = config | ||||||
} | ||||||
|
||||||
func (d *cloudProjectVolumeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { | ||||||
resp.Schema = CloudProjectVolumeResourceSchema(ctx) | ||||||
} | ||||||
|
||||||
func (r *cloudProjectVolumeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||||||
var data, responseData CloudProjectVolumeModelOp | ||||||
|
||||||
// Read Terraform plan data into the model | ||||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) | ||||||
if resp.Diagnostics.HasError() { | ||||||
return | ||||||
} | ||||||
|
||||||
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume" | ||||||
if err := r.config.OVHClient.Post(endpoint, data.ToCreate(), &responseData); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Post %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
err := r.WaitForVolumeCreation(ctx, r.config.OVHClient, data.ServiceName.ValueString(), responseData.Id.ValueString()) | ||||||
if err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Operation"), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
res := &CloudProjectVolumeModelOp{} | ||||||
endpoint = "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/operation/" + url.PathEscape(responseData.Id.ValueString()) | ||||||
if err := r.config.OVHClient.Get(endpoint, res); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Post %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
resVol := &CloudProjectVolumeModelOp{} | ||||||
endpoint = "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(res.ResourceId.ValueString()) | ||||||
if err := r.config.OVHClient.Get(endpoint, resVol); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Post %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
data.MergeWith(resVol) | ||||||
|
||||||
// Save data into Terraform state | ||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||||||
} | ||||||
|
||||||
func (d *cloudProjectVolumeResource) WaitForVolumeCreation(ctx context.Context, client *ovh.Client, serviceName, operationId string) error { | ||||||
stateConf := &retry.StateChangeConf{ | ||||||
Pending: []string{"null", "in-progress", "created", ""}, | ||||||
Target: []string{"completed"}, | ||||||
Refresh: func() (interface{}, string, error) { | ||||||
res := &CloudProjectVolumeModelOp{} | ||||||
endpoint := "/cloud/project/" + url.PathEscape(serviceName) + "/operation/" + url.PathEscape(operationId) | ||||||
err := client.GetWithContext(ctx, endpoint, res) | ||||||
if err != nil { | ||||||
return res, "", err | ||||||
} | ||||||
return res, res.Status.ValueString(), nil | ||||||
}, | ||||||
Timeout: 360 * time.Second, | ||||||
Delay: 10 * time.Second, | ||||||
MinTimeout: 3 * time.Second, | ||||||
} | ||||||
|
||||||
_, err := stateConf.WaitForStateContext(ctx) | ||||||
return err | ||||||
} | ||||||
|
||||||
func (r *cloudProjectVolumeResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||||||
var data, responseData CloudProjectVolumeModelOp | ||||||
|
||||||
// Read Terraform prior state data into the model | ||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||||||
if resp.Diagnostics.HasError() { | ||||||
return | ||||||
} | ||||||
|
||||||
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString()) + "" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
if err := r.config.OVHClient.Get(endpoint, &responseData); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Get %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
data.MergeWith(&responseData) | ||||||
|
||||||
// Save updated data into Terraform state | ||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||||||
} | ||||||
|
||||||
func (r *cloudProjectVolumeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||||||
var data, planData, responseData CloudProjectVolumeModelOp | ||||||
|
||||||
// Read Terraform plan data into the model | ||||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &planData)...) | ||||||
if resp.Diagnostics.HasError() { | ||||||
return | ||||||
} | ||||||
|
||||||
// Read Terraform prior state data into the model | ||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||||||
if resp.Diagnostics.HasError() { | ||||||
return | ||||||
} | ||||||
|
||||||
// Update resource | ||||||
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when using POST on this route, won't it just recreate a new volume ? |
||||||
if err := r.config.OVHClient.Post(endpoint, planData.ToUpdate(), nil); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Post %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
// Read updated resource | ||||||
endpoint = "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString()) + "" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
if err := r.config.OVHClient.Get(endpoint, &responseData); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Get %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
return | ||||||
} | ||||||
|
||||||
responseData.MergeWith(&planData) | ||||||
|
||||||
// Save updated data into Terraform state | ||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &responseData)...) | ||||||
} | ||||||
|
||||||
func (r *cloudProjectVolumeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||||||
var data CloudProjectVolumeModelOp | ||||||
|
||||||
// Read Terraform prior state data into the model | ||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||||||
|
||||||
if resp.Diagnostics.HasError() { | ||||||
return | ||||||
} | ||||||
|
||||||
// Delete API call logic | ||||||
endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString()) + "" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
if err := r.config.OVHClient.Delete(endpoint, nil); err != nil { | ||||||
resp.Diagnostics.AddError( | ||||||
fmt.Sprintf("Error calling Delete %s", endpoint), | ||||||
err.Error(), | ||||||
) | ||||||
} | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should retrieve the last result instead like the following:
and use
res
in create func, so that you can remove lines 76-84.