You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
8.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package image
import (
"context"
"strconv"
"time"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/image/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/image/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/image/schemas"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/image/utilities"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &resourceImage{}
_ resource.ResourceWithImportState = &resourceImage{}
)
// NewResourceImage is a helper function to simplify the provider implementation.
func NewResourceImage() resource.Resource {
return &resourceImage{}
}
// resourceImage is the resource implementation.
type resourceImage struct {
client *client.Client
}
// Create the resource and sets the initial Terraform state.
func (r *resourceImage) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var plan models.ImageResourceModel
// Get plan for create cluster
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error receiving the plan")
return
}
tflog.Info(ctx, "Start create image", map[string]any{"name": plan.ImageName.ValueString()})
// Set timeouts
createTimeout, diags := plan.Timeouts.Create(ctx, constants.Timeout600s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set timeout")
return
}
ctx, cancel := context.WithTimeout(ctx, createTimeout)
defer cancel()
// Сhecking for values in the platform
resp.Diagnostics.Append(utilities.CheckParamsExistenceImage(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error check input values")
return
}
// Create k8s_wg and validated
resp.Diagnostics.Append(utilities.ResourceImageCreate(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error create image")
return
}
// Map response body to schema
resp.Diagnostics.Append(flattens.ResourceImage(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error flatten image")
return
}
// Set state to fully populated data
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set state")
return
}
tflog.Info(ctx, "End create image", map[string]any{"image_id": plan.ImageId.ValueInt64()})
}
// Read refreshes the Terraform state with the latest data.
func (r *resourceImage) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state models.ImageResourceModel
// Get current state
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error get state")
return
}
tflog.Info(ctx, "Start read image", map[string]any{"image_id": state.Id.ValueString()})
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout300s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set timeout")
return
}
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
imageId, err := strconv.Atoi(state.Id.ValueString())
if err != nil {
tflog.Error(ctx, "Cannot convert Id to int value"+err.Error())
}
// Read status image
resp.Diagnostics.Append(utilities.ImageReadStatus(ctx, uint64(imageId), r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error read status")
return
}
// Overwrite items with refreshed state
resp.Diagnostics.Append(flattens.ResourceImage(ctx, &state, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error flatten image")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set state")
return
}
tflog.Info(ctx, "End read image", map[string]any{"image_id": state.Id.ValueString()})
}
// Update updates the resource and sets the updated Terraform state on success.
func (r *resourceImage) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var plan models.ImageResourceModel
var state models.ImageResourceModel
// Retrieve values from plan
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error receiving the plan")
return
}
// Retrieve values from state
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error receiving the state")
return
}
tflog.Info(ctx, "Start update image", map[string]any{"image_id": state.ImageId.ValueInt64()})
// Set timeouts
updateTimeout, diags := plan.Timeouts.Update(ctx, constants.Timeout300s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set timeout")
return
}
ctx, cancel := context.WithTimeout(ctx, updateTimeout)
defer cancel()
// Сhecking for values in the platform
resp.Diagnostics.Append(utilities.CheckParamsExistenceImage(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error check input values")
return
}
// Update name image
if !plan.ImageName.Equal(state.ImageName) {
resp.Diagnostics.Append(utilities.ImageUpdateName(ctx, uint64(state.ImageId.ValueInt64()), plan.ImageName.ValueString(), r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error update name image")
return
}
}
// Map response body to schema
resp.Diagnostics.Append(flattens.ResourceImage(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error flatten image")
return
}
// Set data last update
plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850))
// Set state to fully populated data
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set state")
return
}
tflog.Info(ctx, "End update image", map[string]any{"image_id": plan.ImageId.ValueInt64()})
}
// Delete deletes the resource and removes the Terraform state on success.
func (r *resourceImage) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
// Get current state
var state models.ImageResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error get state")
return
}
tflog.Info(ctx, "Start delete image", map[string]any{"image_id": state.ImageId.ValueInt64()})
// Set timeouts
deleteTimeout, diags := state.Timeouts.Delete(ctx, constants.Timeout300s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set timeout")
return
}
ctx, cancel := context.WithTimeout(ctx, deleteTimeout)
defer cancel()
// Delete image
_, err := r.client.CloudAPI().Image().Delete(ctx, image.DeleteRequest{ImageID: uint64(state.ImageId.ValueInt64())})
if err != nil {
resp.Diagnostics.AddError("Error deleting image with error: ", err.Error())
return
}
tflog.Info(ctx, "End delete image", map[string]any{"image_id": state.ImageId.ValueInt64()})
}
// Schema defines the schema for the resource.
func (r *resourceImage) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaResourceImage(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx, timeouts.Opts{Create: true, Read: true, Update: true, Delete: true}),
},
Version: 1,
}
}
// Metadata returns the resource type name.
func (r *resourceImage) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_image"
}
// Configure adds the provider configured client to the resource.
func (r *resourceImage) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
tflog.Info(ctx, "Get configure resource")
r.client = client.Resource(ctx, &req, resp)
tflog.Info(ctx, "Getting configure resource successfully")
}
func (r *resourceImage) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
// Retrieve import ID and save to id attribute
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}