feat: Update resource_cloudstack_security_group to allow domainid or projectid#262
feat: Update resource_cloudstack_security_group to allow domainid or projectid#262ianc769 wants to merge 2 commits intoapache:mainfrom
resource_cloudstack_security_group to allow domainid or projectid#262Conversation
| ForceNew: true, | ||
| }, | ||
|
|
||
| "projectid": { |
There was a problem hiding this comment.
| "projectid": { | |
| "project": { |
to maintain consistency with other resources.
There was a problem hiding this comment.
Pull request overview
This PR updates the cloudstack_security_group Terraform resource to support creating security groups either in an account/domain context (account + domainid) or in a project context (projectid), aligning with the CloudStack createSecurityGroup API parameters.
Changes:
- Rename
projectargument toprojectid, and addaccount+domainidsupport in the resource implementation. - Extend docs with examples for account/domain and project usage, and update argument reference accordingly.
- Add new acceptance tests for account- and project-scoped security group creation.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
cloudstack/resource_cloudstack_security_group.go |
Adds account, domainid, projectid schema/behavior and updates read/delete logic to use projectid. |
cloudstack/resources.go |
Adds a setDomainid helper and retains generic import logic (project-prefix parsing). |
cloudstack/resource_cloudstack_security_group_test.go |
Adds acceptance tests for project and account variants. |
website/docs/r/security_group.html.markdown |
Adds usage examples and updates argument docs to account/domainid/projectid. |
Comments suppressed due to low confidence (3)
cloudstack/resource_cloudstack_security_group_test.go:107
- The docs explicitly describe importing security groups with a project prefix (
<project-name>/<id>), but the acceptance tests only cover non-project import. Adding an import-in-project acceptance test (similar toTestAccCloudStackInstance_importProject) would prevent regressions around theproject->projectidrename and importer behavior.
func TestAccCloudStackSecurityGroup_import(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudStackSecurityGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudStackSecurityGroup_basic,
},
{
ResourceName: "cloudstack_security_group.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
cloudstack/resources.go:184
importStatePassthroughsets the project prefix into theprojectattribute. After renaming resources to useprojectid(e.g., security group), imports with aproject/IDformat will no longer populate the correct field. Consider either: (1) adding a new importer for resources that useprojectid, or (2) setting bothprojectandprojectidhere (ignoring Set() errors when the key doesn't exist).
func importStatePassthrough(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
// Try to split the ID to extract the optional project name.
s := strings.SplitN(d.Id(), "/", 2)
if len(s) == 2 {
d.Set("project", s[0])
}
cloudstack/resource_cloudstack_security_group.go:72
- Schema-level validation is missing for the new argument combinations. Since
accountandprojectidare mutually exclusive andaccountrequiresdomainid, consider encoding this via schema constraints (e.g.,ConflictsWithonaccountvsprojectid, andRequiredWith/CustomizeDiff foraccount->domainid). This will surface errors at plan time instead of failing during apply.
"account": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"domainid": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"projectid": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // If there is a domain supplied, we retrieve and set the domain id | ||
| func setDomainid(p cloudstack.DomainIDSetter, cs *cloudstack.CloudStackClient, d *schema.ResourceData) error { | ||
| if domain, ok := d.GetOk("domain"); ok { | ||
| domainid, e := retrieveID(cs, "domain", domain.(string)) | ||
| if e != nil { | ||
| return e.Error() | ||
| } | ||
| p.SetDomainid(domainid) | ||
| } | ||
|
|
||
| return nil | ||
| } |
There was a problem hiding this comment.
setDomainid is introduced but not used anywhere in the current codebase (search only finds its definition). If this helper is intended for upcoming changes, consider adding the call sites in this PR; otherwise, it’s dead code that increases maintenance surface and can be removed until needed.
| // Get the security group details | ||
| sg, count, err := cs.SecurityGroup.GetSecurityGroupByID( | ||
| d.Id(), | ||
| cloudstack.WithProject(d.Get("project").(string)), | ||
| cloudstack.WithProject(d.Get("projectid").(string)), | ||
| ) |
There was a problem hiding this comment.
Import uses importStatePassthrough, which populates the state attribute project, but this resource now reads project context from projectid (WithProject(d.Get("projectid"))). Importing with a project prefix (e.g., my-project/<id>) will therefore lose the project scope and may fail to read/delete the SG. Consider switching this resource to a dedicated importer that sets projectid from the prefix (and optionally also supports legacy project for backward compatibility).
| if account, ok := d.GetOk("account"); ok { | ||
| if _, domainOk := d.GetOk("domainid"); !domainOk { | ||
| return fmt.Errorf("account parameter requires domainid to be set") | ||
| } | ||
| // Account and projectid are mutually exclusive | ||
| if _, projectOk := d.GetOk("projectid"); projectOk { | ||
| return fmt.Errorf("account and projectid parameters are mutually exclusive") | ||
| } | ||
| log.Printf("[DEBUG] Creating security group %s for account %s", name, account) | ||
| } |
There was a problem hiding this comment.
account from d.GetOk("account") is an interface{}; logging it with %s will produce %!s(interface {}=...) in logs. Cast to string (or use %v) before logging.
Update
resource_cloudstack_security_groupto allowdomainidorprojectidhttps://cloudstack.apache.org/api/apidocs-4.21/apis/createSecurityGroup.html
This is breaking since I'm renaming
projecttoprojectid(just more descriptive as to what is expected in this field and matches the actual api call)With the code: