diff --git a/docs/data-sources/instance_templates.md b/docs/data-sources/instance_templates.md index 764e118..170f48e 100644 --- a/docs/data-sources/instance_templates.md +++ b/docs/data-sources/instance_templates.md @@ -35,6 +35,7 @@ Optional: - `ib_partition` (String) - `image` (String) - `location` (String) +- `placement_policy` (String) - `project_id` (String) - `public_ip_address_type` (String) - `shutdown_script` (String) diff --git a/docs/resources/instance_template.md b/docs/resources/instance_template.md index 99a1af8..7a436b9 100644 --- a/docs/resources/instance_template.md +++ b/docs/resources/instance_template.md @@ -28,6 +28,7 @@ description: |- - `ib_partition` (String) - `image` (String) - `location` (String) +- `placement_policy` (String) - `project_id` (String) - `public_ip_address_type` (String) - `reservation_id` (String) diff --git a/examples/instance-templates/main.tf b/examples/instance-templates/main.tf index 38c8cb5..cd1709c 100644 --- a/examples/instance-templates/main.tf +++ b/examples/instance-templates/main.tf @@ -23,6 +23,9 @@ resource "crusoe_instance_template" "my_template" { location = "us-northcentral1-a" // this can be obtained via the `crusoe networking vpc-subnets list` CLI command subnet = "bd247b17-fd13-44ba-8aa8-703852b6f326" + // optional parameter to configure placement policy, only "spread" is currently supported + // defaults to "unspecified" if not provided + placement_policy = "spread" # specify the base image image = "ubuntu20.04:latest" diff --git a/go.mod b/go.mod index d0fc9d7..ac9ab68 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/BurntSushi/toml v0.3.1 github.com/antihax/optional v1.0.0 - github.com/crusoecloud/client-go v0.1.51 + github.com/crusoecloud/client-go v0.1.59 github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hashicorp/terraform-plugin-docs v0.18.0 github.com/hashicorp/terraform-plugin-framework v1.3.5 diff --git a/go.sum b/go.sum index 1d970ec..75a0dea 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/crusoecloud/client-go v0.1.51 h1:MLUVVM+w2aP1cckCFSWAmB4oZh3nPnf69dv0M3Z6naI= -github.com/crusoecloud/client-go v0.1.51/go.mod h1:k1FgpUllEJtE53osEwsF+JfbFKILn5t3UuBdHYBVpdY= +github.com/crusoecloud/client-go v0.1.59 h1:iI+017cYXQ/z/TJVCliERameEJpx5Tac0nl1tloaLyc= +github.com/crusoecloud/client-go v0.1.59/go.mod h1:k1FgpUllEJtE53osEwsF+JfbFKILn5t3UuBdHYBVpdY= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/instance_template/instance_template_data_source.go b/internal/instance_template/instance_template_data_source.go index b12444e..19059c1 100644 --- a/internal/instance_template/instance_template_data_source.go +++ b/internal/instance_template/instance_template_data_source.go @@ -38,6 +38,7 @@ type instanceTemplatesModel struct { SubnetId string `tfsdk:"subnet"` IBPartition string `tfsdk:"ib_partition"` Disks []diskModel `tfsdk:"disks"` + PlacementPolicy string `tfsdk:"placement_policy"` } func NewInstanceTemplatesDataSource() datasource.DataSource { @@ -126,6 +127,10 @@ func (ds *instanceTemplatesDataSource) Schema(ctx context.Context, request datas }, }, }, + "placement_policy": schema.StringAttribute{ + Optional: true, + Computed: true, + }, }, }, }, @@ -163,18 +168,19 @@ func (ds *instanceTemplatesDataSource) Read(ctx context.Context, req datasource. var state instanceTemplatesDataSourceModel for i := range dataResp.Items { state.InstanceTemplates = append(state.InstanceTemplates, instanceTemplatesModel{ - ID: dataResp.Items[i].Id, - Name: dataResp.Items[i].Name, - Type: dataResp.Items[i].Type_, - SSHKey: dataResp.Items[i].SshPublicKey, - Location: dataResp.Items[i].Location, - ImageName: dataResp.Items[i].ImageName, - StartupScript: dataResp.Items[i].StartupScript, - ShutdownScript: dataResp.Items[i].ShutdownScript, - SubnetId: dataResp.Items[i].SubnetId, - IBPartition: dataResp.Items[i].IbPartitionId, - ProjectID: dataResp.Items[i].ProjectId, - Disks: disks, + ID: dataResp.Items[i].Id, + Name: dataResp.Items[i].Name, + Type: dataResp.Items[i].Type_, + SSHKey: dataResp.Items[i].SshPublicKey, + Location: dataResp.Items[i].Location, + ImageName: dataResp.Items[i].ImageName, + StartupScript: dataResp.Items[i].StartupScript, + ShutdownScript: dataResp.Items[i].ShutdownScript, + SubnetId: dataResp.Items[i].SubnetId, + IBPartition: dataResp.Items[i].IbPartitionId, + ProjectID: dataResp.Items[i].ProjectId, + Disks: disks, + PlacementPolicy: dataResp.Items[i].PlacementPolicy, }) } diff --git a/internal/instance_template/instance_template_resource.go b/internal/instance_template/instance_template_resource.go index 2c81b3e..fa48b30 100644 --- a/internal/instance_template/instance_template_resource.go +++ b/internal/instance_template/instance_template_resource.go @@ -5,11 +5,13 @@ import ( "fmt" "net/http" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "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/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" @@ -19,6 +21,11 @@ import ( validators "github.com/crusoecloud/terraform-provider-crusoe/internal/validators" ) +const ( + spreadPlacementPolicy = "spread" + unspecifiedPlacementPolicy = "unspecified" +) + type instanceTemplateResource struct { client *swagger.APIClient } @@ -38,6 +45,7 @@ type instanceTemplateResourceModel struct { PublicIpAddressType types.String `tfsdk:"public_ip_address_type"` DisksToCreate types.Set `tfsdk:"disks"` ReservationID types.String `tfsdk:"reservation_id"` + PlacementPolicy types.String `tfsdk:"placement_policy"` } type diskToCreateResourceModel struct { @@ -164,6 +172,13 @@ func (r *instanceTemplateResource) Schema(ctx context.Context, req resource.Sche Computed: true, PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace(), stringplanmodifier.UseStateForUnknown()}, // cannot be updated in place }, + "placement_policy": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("unspecified"), + Validators: []validator.String{stringvalidator.OneOf(spreadPlacementPolicy, unspecifiedPlacementPolicy)}, + PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace(), stringplanmodifier.UseStateForUnknown()}, // cannot be updated in place + }, }, } } @@ -223,6 +238,7 @@ func (r *instanceTemplateResource) Create(ctx context.Context, req resource.Crea Disks: disksToCreate, PublicIpAddressType: plan.PublicIpAddressType.ValueString(), ReservationId: plan.ReservationID.ValueString(), + PlacementPolicy: plan.PlacementPolicy.ValueString(), }, projectID) if err != nil { resp.Diagnostics.AddError("Failed to create instance template", @@ -237,6 +253,8 @@ func (r *instanceTemplateResource) Create(ctx context.Context, req resource.Crea plan.PublicIpAddressType = types.StringValue(dataResp.PublicIpAddressType) plan.Location = types.StringValue(dataResp.Location) plan.Image = types.StringValue(dataResp.ImageName) + plan.PlacementPolicy = types.StringValue(dataResp.PlacementPolicy) + plan.ReservationID = types.StringValue(dataResp.ReservationId) disksToCreateResource := make([]diskToCreateResourceModel, 0, len(dataResp.Disks)) for _, diskToCreate := range disksToCreate { @@ -320,6 +338,11 @@ func (r *instanceTemplateResource) Read(ctx context.Context, req resource.ReadRe } else { state.ShutdownScript = types.StringNull() } + if instanceTemplate.PlacementPolicy != "" { + state.PlacementPolicy = types.StringValue(instanceTemplate.PlacementPolicy) + } else { + state.PlacementPolicy = types.StringValue("unspecified") + } diags = resp.State.Set(ctx, &state) resp.Diagnostics.Append(diags...)