You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cloudstack.apache.org by "fabiomatavelli (via GitHub)" <gi...@apache.org> on 2024/04/20 18:43:41 UTC

[PR] feat: update to terraform plugin framework [cloudstack-terraform-provider]

fabiomatavelli opened a new pull request, #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113

   This PR will:
   
   - Create the plugin framework provider
   - Migrate the service offering resource to the plugin framework


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "vishesh92 (via GitHub)" <gi...@apache.org>.
vishesh92 merged PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "CodeBleu (via GitHub)" <gi...@apache.org>.
CodeBleu commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2155533458

   > This is ready to be merged @CodeBleu , I just don't have the permission to merge it
   
   I just still see it in "Draft" mode. 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: update to terraform plugin framework [cloudstack-terraform-provider]

Posted by "fabiomatavelli (via GitHub)" <gi...@apache.org>.
fabiomatavelli commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2067754833

   @CodeBleu @vishesh92 I started drafting the migration to the terraform plugin framework, base on the #71 , to see the effort to migrate the provider and resources. You can see the diff [here](https://github.com/fabiomatavelli/terraform-provider-cloudstack/compare/feature/update-sdk...fabiomatavelli:terraform-provider-cloudstack:feature/update-to-terraform-plugin-framework)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "CodeBleu (via GitHub)" <gi...@apache.org>.
CodeBleu commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2155530628

   @fabiomatavelli Just wondering the status of this?  Is this dependent on the following being merged?
   
   https://github.com/apache/cloudstack-terraform-provider/pull/71


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "CodeBleu (via GitHub)" <gi...@apache.org>.
CodeBleu commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2204754368

   @fabiomatavelli can you just remove the offering stuff from this PR, so we can get this plugin framework across the line, and then address the options of splitting up the offering resources or not later? 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "CodeBleu (via GitHub)" <gi...@apache.org>.
CodeBleu commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2249373038

   Thanks!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "vishesh92 (via GitHub)" <gi...@apache.org>.
vishesh92 commented on code in PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#discussion_r1662924675


##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -20,246 +20,735 @@
 package cloudstack
 
 import (
+	"context"
 	"fmt"
-	"log"
 
-	"github.com/apache/cloudstack-go/v2/cloudstack"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+	"github.com/hashicorp/terraform-plugin-framework-validators/boolvalidator"
+	"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+	"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+	"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/booldefault"
+	"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
+	"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
+	"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
+	"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"
 )
 
-func resourceCloudStackServiceOffering() *schema.Resource {
-	return &schema.Resource{
-		Create: resourceCloudStackServiceOfferingCreate,
-		Read:   resourceCloudStackServiceOfferingRead,
-		Update: resourceCloudStackServiceOfferingUpdate,
-		Delete: resourceCloudStackServiceOfferingDelete,
-		Schema: map[string]*schema.Schema{
-			"name": {
-				Type:     schema.TypeString,
-				Required: true,
-			},
-			"display_text": {
-				Type:     schema.TypeString,
-				Required: true,
-			},
-			"cpu_number": {
+func NewCloudstackServiceOfferingResource() resource.Resource {
+	return &resourceCloudstackServiceOffering{}
+}
+
+type resourceCloudstackServiceOffering struct {
+	ResourceWithConfigure
+}
+
+type resourceCloudStackServiceOfferingModel struct {
+	Name                      types.String `tfsdk:"name"`
+	DisplayText               types.String `tfsdk:"display_text"`
+	Customized                types.Bool   `tfsdk:"customized"`
+	CpuNumber                 types.Int64  `tfsdk:"cpu_number"`
+	CpuNumberMin              types.Int64  `tfsdk:"cpu_number_min"`
+	CpuNumberMax              types.Int64  `tfsdk:"cpu_number_max"`
+	CpuSpeed                  types.Int64  `tfsdk:"cpu_speed"`
+	Memory                    types.Int64  `tfsdk:"memory"`
+	MemoryMin                 types.Int64  `tfsdk:"memory_min"`
+	MemoryMax                 types.Int64  `tfsdk:"memory_max"`
+	HostTags                  types.String `tfsdk:"host_tags"`
+	NetworkRate               types.Int64  `tfsdk:"network_rate"`
+	OfferHa                   types.Bool   `tfsdk:"offer_ha"`
+	DynamicScaling            types.Bool   `tfsdk:"dynamic_scaling"`
+	LimitCpuUse               types.Bool   `tfsdk:"limit_cpu_use"`
+	Volatile                  types.Bool   `tfsdk:"volatile"`
+	DeploymentPlanner         types.String `tfsdk:"deployment_planner"`
+	ZoneId                    types.List   `tfsdk:"zone_id"`
+	DiskOfferingId            types.String `tfsdk:"disk_offering_id"`
+	StorageType               types.String `tfsdk:"storage_type"`
+	ProvisioningType          types.String `tfsdk:"provisioning_type"`
+	WriteCacheType            types.String `tfsdk:"write_cache_type"`
+	QosType                   types.String `tfsdk:"qos_type"`
+	DiskReadRateBps           types.Int64  `tfsdk:"disk_read_rate_bps"`
+	DiskWriteRateBps          types.Int64  `tfsdk:"disk_write_rate_bps"`
+	DiskReadRateIops          types.Int64  `tfsdk:"disk_read_rate_iops"`
+	DiskWriteRateIops         types.Int64  `tfsdk:"disk_write_rate_iops"`
+	CustomIops                types.Bool   `tfsdk:"custom_iops"`
+	MinIops                   types.Int64  `tfsdk:"min_iops"`
+	MaxIops                   types.Int64  `tfsdk:"max_iops"`
+	HypervisorSnapshotReserve types.Int64  `tfsdk:"hypervisor_snapshot_reserve"`
+	RootDiskSize              types.Int64  `tfsdk:"root_disk_size"`
+	StorageTags               types.String `tfsdk:"storage_tags"`
+	Encrypt                   types.Bool   `tfsdk:"encrypt"`
+	DiskOfferingStrictness    types.Bool   `tfsdk:"disk_offering_strictness"`
+	Id                        types.String `tfsdk:"id"`
+}
+
+func (r *resourceCloudstackServiceOffering) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+	resp.TypeName = fmt.Sprintf("%s_service_offering", req.ProviderTypeName)
+}
+
+func (r *resourceCloudstackServiceOffering) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = schema.Schema{
+		Attributes: map[string]schema.Attribute{
+			"name": schema.StringAttribute{
+				Description: "The name of the service offering",
+				Required:    true,
+			},
+			"display_text": schema.StringAttribute{
+				Description: "The display text of the service offering",
+				Required:    true,
+			},
+			"customized": schema.BoolAttribute{
+				Description: "Is the service offering customized",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
+				Validators: []validator.Bool{
+					boolvalidator.ConflictsWith(path.MatchRoot("cpu_number"), path.MatchRoot("memory")),
+				},
+			},
+			"cpu_number": schema.Int64Attribute{
 				Description: "Number of CPU cores",
-				Type:        schema.TypeInt,
 				Optional:    true,
-				ForceNew:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("cpu_number_min"), path.MatchRoot("cpu_number_max")),
+				},
+			},
+			"cpu_number_min": schema.Int64Attribute{
+				Description: "Minimum number of CPU cores",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.AlsoRequires(path.MatchRoot("cpu_number_max")),
+					int64validator.AtMostSumOf(path.MatchRoot("cpu_number_max")),
+					int64validator.ConflictsWith(path.MatchRoot("cpu_number")),
+				},
+			},
+			"cpu_number_max": schema.Int64Attribute{
+				Description: "Maximum number of CPU cores",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.AlsoRequires(path.MatchRoot("cpu_number_min")),
+					int64validator.AtLeastSumOf(path.MatchRoot("cpu_number_min")),
+					int64validator.ConflictsWith(path.MatchRoot("cpu_number")),
+				},
 			},
-			"cpu_speed": {
+			"cpu_speed": schema.Int64Attribute{
 				Description: "Speed of CPU in Mhz",
-				Type:        schema.TypeInt,
+				Required:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+			},
+			"memory": schema.Int64Attribute{
+				Description: "The total memory of the service offering in MB",
 				Optional:    true,
-				ForceNew:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("memory_min"), path.MatchRoot("memory_max")),
+				},
 			},
-			"host_tags": {
+			"memory_min": schema.Int64Attribute{
+				Description: "Minimum memory of the service offering in MB",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.AlsoRequires(path.MatchRoot("memory_max")),
+					int64validator.AtMostSumOf(path.MatchRoot("memory_max")),
+					int64validator.ConflictsWith(path.MatchRoot("memory")),
+				},
+			},
+			"memory_max": schema.Int64Attribute{
+				Description: "Maximum memory of the service offering in MB",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.AlsoRequires(path.MatchRoot("memory_min")),
+					int64validator.AtLeastSumOf(path.MatchRoot("memory_min")),
+					int64validator.ConflictsWith(path.MatchRoot("memory")),
+				},
+			},
+			"host_tags": schema.StringAttribute{
 				Description: "The host tag for this service offering",
-				Type:        schema.TypeString,
 				Optional:    true,
+				Computed:    true,
+			},
+			"network_rate": schema.Int64Attribute{
+				Description: "Data transfer rate in megabits per second",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+			},
+			"offer_ha": schema.BoolAttribute{
+				Description: "The HA for the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
+			},
+			"dynamic_scaling": schema.BoolAttribute{
+				Description: "Enable dynamic scaling of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
 			},
-			"limit_cpu_use": {
+			"limit_cpu_use": schema.BoolAttribute{
 				Description: "Restrict the CPU usage to committed service offering",
-				Type:        schema.TypeBool,
 				Optional:    true,
-				ForceNew:    true,
-				Default:     false,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
 			},
-			"memory": {
-				Description: "The total memory of the service offering in MB",
-				Type:        schema.TypeInt,
+			"volatile": schema.BoolAttribute{
+				Description: "Service offering is volatile",
 				Optional:    true,
-				ForceNew:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
 			},
-			"offer_ha": {
-				Description: "The HA for the service offering",
-				Type:        schema.TypeBool,
+			"deployment_planner": schema.StringAttribute{
+				Description: "The deployment planner for the service offering",
 				Optional:    true,
-				ForceNew:    true,
-				Default:     false,
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+				Validators: []validator.String{
+					stringvalidator.OneOf("FirstFitPlanner", "UserDispersingPlanner", "UserConcentratedPodPlanner", "ImplicitDedicationPlanner", "BareMetalPlanner"),
+				},
 			},
-			"storage_type": {
+			"zone_id": schema.ListAttribute{
+				Description: "The ID of the zone(s)",
+				Optional:    true,
+				Computed:    true,
+				ElementType: types.StringType,
+				PlanModifiers: []planmodifier.List{
+					listplanmodifier.RequiresReplace(),
+				},
+			},
+			"disk_offering_id": schema.StringAttribute{
+				Description: "The ID of the disk offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+			},
+			"storage_type": schema.StringAttribute{
 				Description: "The storage type of the service offering. Values are local and shared",
-				Type:        schema.TypeString,
 				Optional:    true,
-				ForceNew:    true,
-				Default:     "shared",
-				ValidateFunc: func(val interface{}, key string) (warns []string, errs []error) {
-					v := val.(string)
-
-					if v == "local" || v == "shared" {
-						return
-					}
-
-					errs = append(errs, fmt.Errorf("storage type should be either local or shared, got %s", v))
-
-					return
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+				Validators: []validator.String{
+					stringvalidator.OneOf("local", "shared"),
+					stringvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+				Default: stringdefault.StaticString("shared"),
+			},
+			"provisioning_type": schema.StringAttribute{
+				Description: "The provisioning type of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+				Validators: []validator.String{
+					stringvalidator.OneOf("thin", "sparse", "fat"),
+					stringvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+				Default: stringdefault.StaticString("thin"),
+			},
+			"write_cache_type": schema.StringAttribute{
+				Description: "The write cache type of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+				Validators: []validator.String{
+					stringvalidator.OneOf("none", "writeback", "writethrough"),
+					stringvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+				Default: stringdefault.StaticString("none"),
+			},
+			"qos_type": schema.StringAttribute{
+				Description: "The QoS type of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+				Validators: []validator.String{
+					stringvalidator.OneOf("none", "hypervisor", "storage"),
+					stringvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+				Default: stringdefault.StaticString("none"),
+			},
+			"disk_read_rate_bps": schema.Int64Attribute{
+				Description: "The read rate of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"disk_write_rate_bps": schema.Int64Attribute{
+				Description: "The write rate of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"disk_read_rate_iops": schema.Int64Attribute{
+				Description: "The read rate of the service offering in IOPS",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"disk_write_rate_iops": schema.Int64Attribute{
+				Description: "The write rate of the service offering in IOPS",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"custom_iops": schema.BoolAttribute{
+				Description: "Custom IOPS",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
+				Validators: []validator.Bool{
+					boolvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+					boolvalidator.ConflictsWith(path.MatchRoot("disk_read_rate_iops"), path.MatchRoot("disk_write_rate_iops")),
+					boolvalidator.ConflictsWith(path.MatchRoot("disk_read_rate_bps"), path.MatchRoot("disk_write_rate_bps")),
+				},
+			},
+			"min_iops": schema.Int64Attribute{
+				Description: "The minimum IOPS of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+					int64validator.ConflictsWith(path.MatchRoot("disk_read_rate_iops"), path.MatchRoot("disk_write_rate_iops")),
+					int64validator.ConflictsWith(path.MatchRoot("disk_read_rate_bps"), path.MatchRoot("disk_write_rate_bps")),
+					int64validator.ConflictsWith(path.MatchRoot("custom_iops")),
+				},
+			},
+			"max_iops": schema.Int64Attribute{
+				Description: "The maximum IOPS of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+					int64validator.ConflictsWith(path.MatchRoot("disk_read_rate_iops"), path.MatchRoot("disk_write_rate_iops")),
+					int64validator.ConflictsWith(path.MatchRoot("disk_read_rate_bps"), path.MatchRoot("disk_write_rate_bps")),
+					int64validator.ConflictsWith(path.MatchRoot("custom_iops")),
+				},
+			},
+			"hypervisor_snapshot_reserve": schema.Int64Attribute{
+				Description: "The hypervisor snapshot reserve of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+					int64validator.ConflictsWith(path.MatchRoot("disk_read_rate_iops"), path.MatchRoot("disk_write_rate_iops")),
+					int64validator.ConflictsWith(path.MatchRoot("disk_read_rate_bps"), path.MatchRoot("disk_write_rate_bps")),
+				},
+			},
+			"root_disk_size": schema.Int64Attribute{
+				Description: "The size of the root disk in GB",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Int64{
+					int64planmodifier.RequiresReplace(),
+				},
+				Validators: []validator.Int64{
+					int64validator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"storage_tags": schema.StringAttribute{
+				Description: "The storage tags of the service offering",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.RequiresReplace(),
+				},
+				Validators: []validator.String{
+					stringvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"encrypt": schema.BoolAttribute{
+				Description: "Encrypt the service offering storage",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
+				Validators: []validator.Bool{
+					boolvalidator.ConflictsWith(path.MatchRoot("disk_offering_id")),
+				},
+			},
+			"disk_offering_strictness": schema.BoolAttribute{
+				Description: "Disk offering strictness",
+				Optional:    true,
+				Computed:    true,
+				PlanModifiers: []planmodifier.Bool{
+					boolplanmodifier.RequiresReplace(),
+				},
+				Default: booldefault.StaticBool(false),
+			},
+			"id": schema.StringAttribute{
+				Description: "The ID of the service offering",
+				Computed:    true,
+				PlanModifiers: []planmodifier.String{
+					stringplanmodifier.UseStateForUnknown(),
 				},
 			},
 		},
 	}
 }
 
-func resourceCloudStackServiceOfferingCreate(d *schema.ResourceData, meta interface{}) error {
-	cs := meta.(*cloudstack.CloudStackClient)
-	name := d.Get("name").(string)
-	display_text := d.Get("display_text").(string)
+func (r *resourceCloudstackServiceOffering) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+	var data resourceCloudStackServiceOfferingModel
+
+	resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+
+	if resp.Diagnostics.HasError() {
+		return
+	}
+
+	p := r.client.ServiceOffering.NewCreateServiceOfferingParams(data.DisplayText.ValueString(), data.Name.ValueString())
+
+	if !data.Customized.ValueBool() {
+		if !data.CpuNumber.IsNull() && !data.CpuNumber.IsUnknown() {
+			p.SetCpunumber(int(data.CpuNumber.ValueInt64()))
+		}
+
+		if !data.Memory.IsNull() && !data.Memory.IsUnknown() {
+			p.SetMemory(int(data.Memory.ValueInt64()))
+		}
 
-	// Create a new parameter struct
-	p := cs.ServiceOffering.NewCreateServiceOfferingParams(display_text, name)
-	if v, ok := d.GetOk("cpu_number"); ok {
-		p.SetCpunumber(v.(int))
+		data.CpuNumberMax = types.Int64Null()
+		data.CpuNumberMin = types.Int64Null()
+		data.MemoryMax = types.Int64Null()
+		data.MemoryMin = types.Int64Null()
+	} else {
+		if !data.CpuNumberMin.IsNull() && !data.CpuNumberMin.IsUnknown() {
+			p.SetMincpunumber(int(data.CpuNumberMin.ValueInt64()))
+		}
+
+		if !data.CpuNumberMax.IsNull() && !data.CpuNumberMax.IsUnknown() {
+			p.SetMaxcpunumber(int(data.CpuNumberMax.ValueInt64()))
+		}
+
+		if !data.MemoryMin.IsNull() && !data.MemoryMin.IsUnknown() {
+			p.SetMinmemory(int(data.MemoryMin.ValueInt64()))
+		}
+
+		if !data.MemoryMax.IsNull() && !data.MemoryMax.IsUnknown() {
+			p.SetMaxmemory(int(data.MemoryMax.ValueInt64()))
+		}
+
+		data.CpuNumber = types.Int64Null()
+		data.Memory = types.Int64Null()
 	}
 
-	if v, ok := d.GetOk("cpu_speed"); ok {
-		p.SetCpuspeed(v.(int))
+	if !data.CpuSpeed.IsNull() && !data.CpuSpeed.IsUnknown() {
+		p.SetCpuspeed(int(data.CpuSpeed.ValueInt64()))
 	}
 
-	if v, ok := d.GetOk("host_tags"); ok {
-		p.SetHosttags(v.(string))
+	if !data.HostTags.IsNull() && !data.HostTags.IsUnknown() {
+		p.SetHosttags(data.HostTags.ValueString())
+	} else {
+		data.HostTags = types.StringNull()
 	}
 
-	if v, ok := d.GetOk("limit_cpu_use"); ok {
-		p.SetLimitcpuuse(v.(bool))
+	if !data.NetworkRate.IsNull() && !data.NetworkRate.IsUnknown() {
+		p.SetNetworkrate(int(data.NetworkRate.ValueInt64()))
+	} else {
+		data.NetworkRate = types.Int64Null()
 	}
 
-	if v, ok := d.GetOk("memory"); ok {
-		p.SetMemory(v.(int))
+	if !data.OfferHa.IsNull() && !data.OfferHa.IsUnknown() {
+		p.SetOfferha(data.OfferHa.ValueBool())
 	}
 
-	if v, ok := d.GetOk("offer_ha"); ok {
-		p.SetOfferha(v.(bool))
+	if !data.DynamicScaling.IsNull() && !data.DynamicScaling.IsUnknown() {
+		p.SetDynamicscalingenabled(data.DynamicScaling.ValueBool())
 	}
 
-	if v, ok := d.GetOk("storage_type"); ok {
-		p.SetStoragetype(v.(string))
+	if !data.LimitCpuUse.IsNull() && !data.LimitCpuUse.IsUnknown() {
+		p.SetLimitcpuuse(data.LimitCpuUse.ValueBool())
 	}
 
-	log.Printf("[DEBUG] Creating Service Offering %s", name)
-	s, err := cs.ServiceOffering.CreateServiceOffering(p)
+	if !data.Volatile.IsNull() && !data.Volatile.IsUnknown() {
+		p.SetIsvolatile(data.Volatile.ValueBool())
+	}
 
-	if err != nil {
-		return err
+	if !data.DeploymentPlanner.IsNull() && !data.DeploymentPlanner.IsUnknown() {
+		p.SetDeploymentplanner(data.DeploymentPlanner.ValueString())
+	} else {
+		data.DeploymentPlanner = types.StringNull()
 	}
 
-	log.Printf("[DEBUG] Service Offering %s successfully created", name)
-	d.SetId(s.Id)
+	if !data.ZoneId.IsNull() && !data.ZoneId.IsUnknown() {
+		zoneIds := make([]string, 0, len(data.ZoneId.Elements()))
+		diags := data.ZoneId.ElementsAs(ctx, &zoneIds, false)
+		if diags.HasError() {
+			resp.Diagnostics.Append(diags...)
+			return
+		}
+		p.SetZoneid(zoneIds)
+	} else {
+		data.ZoneId = types.ListNull(types.StringType)
+	}
 
-	return resourceCloudStackServiceOfferingRead(d, meta)
-}
+	if !data.DiskOfferingId.IsNull() && !data.DiskOfferingId.IsUnknown() {
+		p.SetDiskofferingid(data.DiskOfferingId.ValueString())
+	} else {
+		p.SetDiskofferingid("")
+		data.DiskOfferingId = types.StringNull()
+
+		if !data.StorageType.IsNull() && !data.StorageType.IsUnknown() {
+			p.SetStoragetype(data.StorageType.ValueString())
+		} else {
+			data.StorageType = types.StringNull()
+		}
 
-func resourceCloudStackServiceOfferingRead(d *schema.ResourceData, meta interface{}) error {
-	cs := meta.(*cloudstack.CloudStackClient)
-	log.Printf("[DEBUG] Retrieving Service Offering %s", d.Get("name").(string))
+		if !data.ProvisioningType.IsNull() && !data.ProvisioningType.IsUnknown() {
+			p.SetProvisioningtype(data.ProvisioningType.ValueString())
+		}
 
-	// Get the Service Offering details
-	s, count, err := cs.ServiceOffering.GetServiceOfferingByName(d.Get("name").(string))
+		if !data.WriteCacheType.IsNull() && !data.WriteCacheType.IsUnknown() {
+			p.SetCachemode(data.WriteCacheType.ValueString())
+		}
 
-	if err != nil {
-		if count == 0 {
-			log.Printf("[DEBUG] Service Offering %s does no longer exist", d.Get("name").(string))
-			d.SetId("")
-			return nil
+		if data.QosType.ValueString() == "hypervisor" {
+			if !data.DiskReadRateBps.IsNull() && !data.DiskReadRateBps.IsUnknown() {
+				p.SetBytesreadrate(data.DiskReadRateBps.ValueInt64())
+			}
+
+			if !data.DiskWriteRateBps.IsNull() && !data.DiskWriteRateBps.IsUnknown() {
+				p.SetByteswriterate(data.DiskWriteRateBps.ValueInt64())
+			}
+
+			if !data.DiskReadRateIops.IsNull() && !data.DiskReadRateIops.IsUnknown() {
+				p.SetIopsreadrate(data.DiskReadRateIops.ValueInt64())
+			}
+
+			if !data.DiskWriteRateIops.IsNull() && !data.DiskWriteRateIops.IsUnknown() {
+				p.SetIopswriterate(data.DiskWriteRateIops.ValueInt64())
+			}
+		} else if data.QosType.ValueString() == "storage" {
+			p.SetCustomizediops(data.CustomIops.ValueBool())
+
+			if !data.CustomIops.ValueBool() {
+				if !data.MinIops.IsNull() && !data.MinIops.IsUnknown() {
+					p.SetMiniops(data.MinIops.ValueInt64())
+				}
+
+				if !data.MaxIops.IsNull() && !data.MaxIops.IsUnknown() {
+					p.SetMaxiops(data.MaxIops.ValueInt64())
+				}
+			} else {
+				p.SetMiniops(0)

Review Comment:
   I am not sure. But this could cause issues. I would suggest not doing anything if it's not defined.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "fabiomatavelli (via GitHub)" <gi...@apache.org>.
fabiomatavelli commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2208716702

   @CodeBleu done


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "fabiomatavelli (via GitHub)" <gi...@apache.org>.
fabiomatavelli commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2185000484

   @vishesh92 @kiranchavala can you please review it again and re-approve the CI to run 🙏 
   
   I had to move the V6 (terraform plugin framework) to be tested with a muxed provider instead, as we still need to call resources/datasources in the V5 provider (terraform provider sdk).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "fabiomatavelli (via GitHub)" <gi...@apache.org>.
fabiomatavelli commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2203971835

   @vishesh92 yes, this will be the first resource updated to the tf framework. Do you think the approach used in the #77 is better, by splitting into different resources?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "rohityadavcloud (via GitHub)" <gi...@apache.org>.
rohityadavcloud commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2249362878

   Fine by me, but since I'm less of a developer these days - let's wait from @vishesh92 and/or @kiranchavala to advise.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "fabiomatavelli (via GitHub)" <gi...@apache.org>.
fabiomatavelli commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2155535562

   Ah, sorry @CodeBleu , my bad, this is indeed waiting for #71


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "vishesh92 (via GitHub)" <gi...@apache.org>.
vishesh92 commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2203967104

   @fabiomatavelli There are changes around service offering in PR #77 by @poddm. Does this PR supersede the changes in PR #77?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "vishesh92 (via GitHub)" <gi...@apache.org>.
vishesh92 commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2203982419

   > @vishesh92 yes, this will be the first resource updated to the tf framework. Do you think the approach used in the #77 is better, by splitting into different resources?
   > 
   > This one is just updating to the tf framework and adding all the available params for the service offering.
   
   I am not using this provider. So, this is just my opinion. 
   Splitting into different resources might make it easier for the user to define the service offerings using terraform.
   But I am not sure how easy it would be for users to migrate to the newer version. And if it would cause issues any issue with service offering datasource.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "fabiomatavelli (via GitHub)" <gi...@apache.org>.
fabiomatavelli commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2155532176

   This is ready to be merged @CodeBleu , I just don't have the permission to merge it


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "CodeBleu (via GitHub)" <gi...@apache.org>.
CodeBleu commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2208847456

   @vishesh92  @kiranchavala  Can this be merged now?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] feat: migrate to terraform plugin framework [cloudstack-terraform-provider]

Posted by "CodeBleu (via GitHub)" <gi...@apache.org>.
CodeBleu commented on PR #113:
URL: https://github.com/apache/cloudstack-terraform-provider/pull/113#issuecomment-2248687105

   > @fabiomatavelli @CodeBleu since we recently had a TF release, the next one we can target for Q3/Q4 this year. If you're blocked then let us know, otherwise due to our $dayjobs and other community work (the release work for example), our engagement and responses may be delayed.
   
   CC @kiranchavala @vishesh92 
   
   With the release of Cloudstack 4.19.1 now out, I'm hoping we can get this PR across the line.  I feel like this should be just a matter of clicking the "merge" button, as there have been a lot of back and forth on this one and the last concern about it, had that piece removed to make it easier to proceed with merging this.
   
   I think this PR for the new plugin framework is a pretty important one to get merged in, so that efforts can be made to start porting all of the data and resources over to the new framework.
   
   I appreciate all you are doing for the community and know your busy, but thought it was worth getting this one merged.
   
   Thanks!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@cloudstack.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org