Enhance cloudstack_disk_offering resource and datasource - #301
Conversation
There was a problem hiding this comment.
Pull request overview
This PR enhances the cloudstack_disk_offering Terraform resource to support additional CloudStack disk-offering parameters and completes the CRUD implementation, while also introducing a new cloudstack_disk_offering data source (plus docs and acceptance tests) so disk offerings can be discovered and referenced by other resources.
Changes:
- Expanded
cloudstack_disk_offeringresource schema (custom sizing, storage/provisioning type, tags, display flag) and implemented Read/Update/Delete + Importer. - Added
cloudstack_disk_offeringdata source with filter-based selection and acceptance tests. - Updated/added website documentation for the resource and data source.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| website/docs/r/disk_offering.html.markdown | Documents the expanded disk offering resource arguments and attributes. |
| website/docs/d/disk_offering.html.markdown | Adds documentation for the new disk offering data source. |
| cloudstack/resource_cloudstack_disk_offering.go | Implements full disk offering resource CRUD/import and adds missing schema parameters. |
| cloudstack/resource_cloudstack_disk_offering_test.go | Adds acceptance tests for disk offering resource scenarios (basic/customized/update). |
| cloudstack/provider.go | Registers the new disk offering data source with the provider. |
| cloudstack/data_source_cloudstack_disk_offering.go | Implements the disk offering data source and filter logic. |
| cloudstack/data_source_cloudstack_disk_offering_test.go | Adds an acceptance test validating the disk offering data source against a created resource. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
19e1531 to
0b8428c
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (3)
cloudstack/resource_cloudstack_disk_offering.go:64
customizedhasDefault: falsebut Create() forces it totruewheneverdisk_sizeis omitted. This means a config that omits both fields will plan withcustomized=falseand then read backcustomized=true, causing perpetual diffs / forced recreation. The service offering resource avoids this by makingcustomizedComputed: trueinstead of defaulting it.
"customized": {
Description: "Whether the disk offering allows a custom disk size at deployment time",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
ConflictsWith: []string{"disk_size"},
},
website/docs/r/disk_offering.html.markdown:36
- The
customizedargument docs currently say it "Defaults tofalse" but also say it's "implied whendisk_sizeis omitted" (and the implementation sets it totruewhendisk_sizeis omitted). Please update the wording so the default/implicit behavior is not contradictory and matches provider behavior.
* `customized` - (Optional) Whether the disk offering allows a custom disk size
to be specified at deployment time. Conflicts with `disk_size`, and is
implied when `disk_size` is omitted. Defaults to `false`. Changing this
forces a new resource to be created.
cloudstack/resource_cloudstack_disk_offering_test.go:95
- The acceptance tests cover
customized = trueexplicitly, but not the documented/implemented behavior where omitting bothdisk_sizeandcustomizedshould create a customized offering. Adding coverage for that case would prevent regressions (and would have caught the schema default drift issue).
const testAccCloudStackDiskOffering_customized = `
resource "cloudstack_disk_offering" "custom" {
name = "custom_disk_offering"
display_text = "Custom Test"
customized = true
storage_type = "local"
provisioning_type = "thin"
tags = "ssd"
}
0b8428c to
6256342
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (2)
cloudstack/resource_cloudstack_disk_offering.go:61
customizedis declared withDefault: false, but the Create logic forcescustomized=truewheneverdisk_sizeis omitted (even when the user didn’t setcustomized). With a default, Terraform will treat an omittedcustomizedasfalsein config, so after Read setscustomized=truefrom the API this will cause a perpetual diff / forced recreation. Other offering resources avoid this by makingcustomizedComputed: truewith no default (e.g. service offering).
"customized": {
Description: "Whether the disk offering allows a custom disk size at deployment time",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
website/docs/r/disk_offering.html.markdown:36
- Docs say
customizeddefaults tofalse, but the resource Create path implicitly setscustomized=truewheneverdisk_sizeis omitted. With the schema fix to makecustomizedcomputed/derived, the docs should describe it as derived from whetherdisk_sizeis set rather than a fixed default, otherwise users will hit confusing diffs.
* `customized` - (Optional) Whether the disk offering allows a custom disk size
to be specified at deployment time. Conflicts with `disk_size`, and is
implied when `disk_size` is omitted. Defaults to `false`. Changing this
forces a new resource to be created.
|
This is missing a number of fields. I added all API fields in this PR. #313 note, I didn't add the data sources in my PR. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (4)
cloudstack/resource_cloudstack_disk_offering.go:63
customizedhasDefault: false, butCreateforcescustomized=truewheneverdisk_sizeis omitted. This makes it impossible to represent the “unset” state and can lead to a permanent diff when users omit both arguments (docs say it should become customized automatically). Consider aligning this withcloudstack_service_offering(Optional+Computed) by removing the default and makingcustomizedcomputed.
"customized": {
Description: "Whether the disk offering allows a custom disk size at deployment time",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
ConflictsWith: []string{"disk_size"},
cloudstack/resource_cloudstack_disk_offering.go:129
- The
customizedcalculation can’t distinguish betweencustomized = falseset explicitly vs not set at all becauseGetOk("customized")is false for booleanfalse, and then the code unconditionally overrides it totruewhendisk_sizeis omitted. Ifcustomizedis intended to be implied only when unset, useGetOkExistsand/or return a validation error whencustomized=falseanddisk_sizeis not set.
if v, ok := d.GetOk("disk_size"); ok {
p.SetDisksize(int64(v.(int)))
}
customized := false
if v, ok := d.GetOk("customized"); ok {
customized = v.(bool)
}
if _, ok := d.GetOk("disk_size"); !ok {
customized = true
}
p.SetCustomized(customized)
website/docs/r/disk_offering.html.markdown:36
- The docs say
customized"Defaults tofalse", but the resource logic treatscustomizedas implied/true whendisk_sizeis omitted. This is a conditional default, so documenting an unconditional default offalseis misleading.
* `customized` - (Optional) Whether the disk offering allows a custom disk size
to be specified at deployment time. Conflicts with `disk_size`, and is
implied when `disk_size` is omitted. Defaults to `false`. Changing this
forces a new resource to be created.
cloudstack/resource_cloudstack_disk_offering_test.go:84
- There’s no acceptance test that re-applies a config with neither
disk_sizenorcustomizedset to verify the implied-customized behavior and catch a potential permadiff. Adding a secondPlanOnly: truestep (like other tests in the repo) would ensure the resource converges whencustomizedis implied.
func TestAccCloudStackDiskOffering_customized(t *testing.T) {
var do cloudstack.DiskOffering
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudStackDiskOfferingDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudStackDiskOffering_customized,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudStackDiskOfferingExists("cloudstack_disk_offering.custom", &do),
resource.TestCheckResourceAttr("cloudstack_disk_offering.custom", "customized", "true"),
resource.TestCheckResourceAttr("cloudstack_disk_offering.custom", "storage_type", "local"),
resource.TestCheckResourceAttr("cloudstack_disk_offering.custom", "provisioning_type", "thin"),
resource.TestCheckResourceAttr("cloudstack_disk_offering.custom", "tags", "ssd"),
),
},
},
})
}
aab7e8f to
2794602
Compare
There was a problem hiding this comment.
🟡 Changes recommended
It introduces a breaking removal of autoscale data sources and has idempotency issues around customized defaults/inference that can cause perpetual diffs.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (3)
cloudstack/resource_cloudstack_disk_offering.go:62
customizedis declared withDefault: false, but Create forcescustomized=truewheneverdisk_sizeis omitted. That combination can cause perpetual diffs/recreates when users omit both fields (or import an offering) because Terraform will treatcustomizedas explicitlyfalsein config while state/API returnstrue. Align this with the existing pattern used bycloudstack_service_offeringby makingcustomizedOptional+Computed and removing the unconditional default.
Description: "Whether the disk offering allows a custom disk size at deployment time",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
cloudstack/resource_cloudstack_disk_offering.go:129
- Create currently overrides an explicitly configured
customized=falsewheneverdisk_sizeis omitted (customizedgets forced totrue). That makes the provider ignore user intent and also hides a configuration error case (fixed-size offering withoutdisk_size). Computecustomizedfrom inputs in a single place: ifdisk_sizeis set => customized=false; else ifcustomizedis explicitly set => use it; else default to customized=true. Ifcustomizedis explicitly false whiledisk_sizeis unset, return a helpful error.
customized := false
if v, ok := d.GetOk("customized"); ok {
customized = v.(bool)
}
if _, ok := d.GetOk("disk_size"); !ok {
customized = true
}
p.SetCustomized(customized)
cloudstack/provider.go:84
- This change removes the autoscale data sources from
DataSourcesMap(while the autoscale resources still exist). That is a breaking provider surface-area change and doesn’t match the PR’s stated scope (disk offering resource/datasource). If unintentional, re-add the autoscale data sources here.
DataSourcesMap: map[string]*schema.Resource{
"cloudstack_condition": dataSourceCloudstackCondition(),
"cloudstack_counter": dataSourceCloudstackCounter(),
"cloudstack_template": dataSourceCloudstackTemplate(),
"cloudstack_ssh_keypair": dataSourceCloudstackSSHKeyPair(),
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
| * `customized` - (Optional) Whether the disk offering allows a custom disk size | ||
| to be specified at deployment time. Conflicts with `disk_size`, and is | ||
| implied when `disk_size` is omitted. Defaults to `false`. Changing this | ||
| forces a new resource to be created. |
|
@bddvlpr could you please address following comments:
|
2794602 to
886a17b
Compare
|
Unsure how the deletion of the entries got in, was an issue with a rebase. |
Adds a bunch of missing parameters to the disk offering resource. Initialized the data source for it while I was at it.
Tested on simulator.