Skip to content

Commit 424dbf1

Browse files
committed
fix: update display_text to displaytext in project resource and tests.
fix: update lookup to use getAccountNameByID helper function
1 parent 97a3b24 commit 424dbf1

2 files changed

Lines changed: 134 additions & 42 deletions

File tree

cloudstack/resource_cloudstack_project.go

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func resourceCloudStackProject() *schema.Resource {
4646
Required: true,
4747
},
4848

49-
"display_text": {
49+
"displaytext": {
5050
Type: schema.TypeString,
5151
Optional: true,
5252
},
@@ -79,9 +79,9 @@ func resourceCloudStackProject() *schema.Resource {
7979
func resourceCloudStackProjectCreate(d *schema.ResourceData, meta any) error {
8080
cs := meta.(*cloudstack.CloudStackClient)
8181

82-
// Get the name and display_text
82+
// Get the name and displaytext
8383
name := d.Get("name").(string)
84-
displaytext := d.Get("display_text").(string)
84+
displaytext := d.Get("displaytext").(string)
8585

8686
// Get domain if provided
8787
var domain string
@@ -101,7 +101,7 @@ func resourceCloudStackProjectCreate(d *schema.ResourceData, meta any) error {
101101

102102
// Set the basic attributes to match the existing project
103103
d.Set("name", existingProject.Name)
104-
d.Set("display_text", existingProject.Displaytext)
104+
d.Set("displaytext", existingProject.Displaytext)
105105
d.Set("domain", existingProject.Domain)
106106

107107
return resourceCloudStackProjectRead(d, meta)
@@ -218,6 +218,32 @@ func getProjectByID(cs *cloudstack.CloudStackClient, id string, domain ...string
218218
return l.Projects[0], nil
219219
}
220220

221+
// Helper function to get an account name by account ID
222+
func getAccountNameByID(cs *cloudstack.CloudStackClient, accountID string) (string, error) {
223+
// Create parameters for listing accounts
224+
p := cs.Account.NewListAccountsParams()
225+
p.SetId(accountID)
226+
227+
// Call the API to list accounts with the specified ID
228+
accounts, err := cs.Account.ListAccounts(p)
229+
if err != nil {
230+
return "", fmt.Errorf("error retrieving account with ID %s: %s", accountID, err)
231+
}
232+
233+
// Check if we found the account
234+
if accounts.Count == 0 {
235+
return "", fmt.Errorf("account with ID %s not found", accountID)
236+
}
237+
238+
// Return the account name
239+
account := accounts.Accounts[0]
240+
if account.Name == "" {
241+
return "", fmt.Errorf("account with ID %s has no name", accountID)
242+
}
243+
244+
return account.Name, nil
245+
}
246+
221247
// Helper function to get a project by name
222248
func getProjectByName(cs *cloudstack.CloudStackClient, name string, domain string) (*cloudstack.Project, error) {
223249
p := cs.Project.NewListProjectsParams()
@@ -300,7 +326,7 @@ func resourceCloudStackProjectRead(d *schema.ResourceData, meta any) error {
300326

301327
// Set the basic attributes
302328
d.Set("name", project.Name)
303-
d.Set("display_text", project.Displaytext)
329+
d.Set("displaytext", project.Displaytext)
304330
d.Set("domain", project.Domain)
305331

306332
// Handle owner information more safely
@@ -369,21 +395,21 @@ func resourceCloudStackProjectRead(d *schema.ResourceData, meta any) error {
369395
func resourceCloudStackProjectUpdate(d *schema.ResourceData, meta any) error {
370396
cs := meta.(*cloudstack.CloudStackClient)
371397

372-
// Check if the name or display text is changed
373-
if d.HasChange("name") || d.HasChange("display_text") {
398+
// Check if the name or displaytext is changed
399+
if d.HasChange("name") || d.HasChange("displaytext") {
374400
// Create a new parameter struct
375401
p := cs.Project.NewUpdateProjectParams(d.Id())
376402

377-
// Set the name and display_text if they have changed
378-
// Note: The 'name' parameter is only available in API 4.19 and higher
379-
// If you're using API 4.18 or lower, the SetName method might not work
380-
// In that case, you might need to update the display_text only
403+
// Set the name and displaytext if they have changed
404+
// Note: The 'name' parameter is only available in CloudStack API 4.19+ and in cloudstack-go SDK v2.11.0+.
405+
// If you're using API 4.18 or lower, or an older SDK, the SetName method might not work.
406+
// In that case, you might need to update the displaytext only.
381407
if d.HasChange("name") {
382408
p.SetName(d.Get("name").(string))
383409
}
384410

385-
if d.HasChange("display_text") {
386-
p.SetDisplaytext(d.Get("display_text").(string))
411+
if d.HasChange("displaytext") {
412+
p.SetDisplaytext(d.Get("displaytext").(string))
387413
}
388414

389415
log.Printf("[DEBUG] Updating project %s", d.Id())
@@ -411,13 +437,24 @@ func resourceCloudStackProjectUpdate(d *schema.ResourceData, meta any) error {
411437
p.SetUserid(d.Get("userid").(string))
412438
}
413439

414-
// Note: accountid is not directly supported by the UpdateProject API,
415-
// but we can use the account parameter instead if accountid has changed
440+
// Note: The UpdateProject API does not accept 'accountid' directly.
441+
// If 'accountid' has changed but 'account' has not, we perform a lookup to get the account name
442+
// corresponding to the new 'accountid' and set it using the 'account' parameter instead.
443+
// This is necessary because the API only allows updating the owner via the account name, not the account ID.
444+
// Only perform the lookup if "account" itself hasn't changed, to avoid conflicting updates.
416445
if d.HasChange("accountid") && !d.HasChange("account") {
417446
// If accountid has changed but account hasn't, we need to look up the account name
418-
// This is a placeholder - in a real implementation, you would need to look up
419-
// the account name from the accountid
420-
log.Printf("[WARN] Updating accountid is not directly supported by the API. Please use account instead.")
447+
// from the accountid and use it in the account parameter
448+
accountid := d.Get("accountid").(string)
449+
if accountid != "" {
450+
accountName, err := getAccountNameByID(cs, accountid)
451+
if err != nil {
452+
log.Printf("[WARN] Failed to look up account name for accountid %s: %s. Skipping account update as account name could not be determined.", accountid, err)
453+
} else {
454+
log.Printf("[DEBUG] Found account name '%s' for accountid %s, using account parameter", accountName, accountid)
455+
p.SetAccount(accountName)
456+
}
457+
}
421458
}
422459

423460
log.Printf("[DEBUG] Updating project owner %s", d.Id())
@@ -452,9 +489,9 @@ func resourceCloudStackProjectUpdate(d *schema.ResourceData, meta any) error {
452489
return retry.RetryableError(fmt.Errorf("project name not updated yet"))
453490
}
454491

455-
if d.HasChange("display_text") && project.Displaytext != d.Get("display_text").(string) {
456-
log.Printf("[DEBUG] Project %s display_text not updated yet, retrying...", d.Id())
457-
return retry.RetryableError(fmt.Errorf("project display_text not updated yet"))
492+
if d.HasChange("displaytext") && project.Displaytext != d.Get("displaytext").(string) {
493+
log.Printf("[DEBUG] Project %s displaytext not updated yet, retrying...", d.Id())
494+
return retry.RetryableError(fmt.Errorf("project displaytext not updated yet"))
458495
}
459496

460497
log.Printf("[DEBUG] Project %s updated successfully", d.Id())
@@ -512,9 +549,7 @@ func resourceCloudStackProjectDelete(d *schema.ResourceData, meta any) error {
512549

513550
// Create a new parameter struct
514551
p := cs.Project.NewDeleteProjectParams(d.Id())
515-
516-
log.Printf("[INFO] Deleting project: %s (%s)", d.Id(), project.Name)
517-
_, err = cs.Project.DeleteProject(p)
552+
result, err := cs.Project.DeleteProject(p)
518553
if err != nil {
519554
// Check for various "not found" or "does not exist" error patterns
520555
if strings.Contains(err.Error(), "not found") ||
@@ -528,6 +563,9 @@ func resourceCloudStackProjectDelete(d *schema.ResourceData, meta any) error {
528563

529564
return fmt.Errorf("error deleting project %s: %s", d.Id(), err)
530565
}
566+
if result == nil {
567+
log.Printf("[WARN] DeleteProject returned nil result for project: %s (%s)", d.Id(), project.Name)
568+
}
531569

532570
log.Printf("[DEBUG] Successfully deleted project: %s (%s)", d.Id(), project.Name)
533571
return nil

cloudstack/resource_cloudstack_project_test.go

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestAccCloudStackProject_basic(t *testing.T) {
4444
resource.TestCheckResourceAttr(
4545
"cloudstack_project.foo", "name", "terraform-test-project"),
4646
resource.TestCheckResourceAttr(
47-
"cloudstack_project.foo", "display_text", "Terraform Test Project"),
47+
"cloudstack_project.foo", "displaytext", "Terraform Test Project"),
4848
),
4949
},
5050
},
@@ -67,7 +67,7 @@ func TestAccCloudStackProject_update(t *testing.T) {
6767
resource.TestCheckResourceAttr(
6868
"cloudstack_project.foo", "name", "terraform-test-project"),
6969
resource.TestCheckResourceAttr(
70-
"cloudstack_project.foo", "display_text", "Terraform Test Project"),
70+
"cloudstack_project.foo", "displaytext", "Terraform Test Project"),
7171
),
7272
},
7373
{
@@ -78,7 +78,7 @@ func TestAccCloudStackProject_update(t *testing.T) {
7878
resource.TestCheckResourceAttr(
7979
"cloudstack_project.foo", "name", "terraform-test-project-updated"),
8080
resource.TestCheckResourceAttr(
81-
"cloudstack_project.foo", "display_text", "Terraform Test Project Updated"),
81+
"cloudstack_project.foo", "displaytext", "Terraform Test Project Updated"),
8282
),
8383
},
8484
},
@@ -119,7 +119,7 @@ func TestAccCloudStackProject_account(t *testing.T) {
119119
resource.TestCheckResourceAttr(
120120
"cloudstack_project.bar", "name", "terraform-test-project-account"),
121121
resource.TestCheckResourceAttr(
122-
"cloudstack_project.bar", "display_text", "Terraform Test Project with Account"),
122+
"cloudstack_project.bar", "displaytext", "Terraform Test Project with Account"),
123123
resource.TestCheckResourceAttr(
124124
"cloudstack_project.bar", "account", "admin"),
125125
),
@@ -144,7 +144,7 @@ func TestAccCloudStackProject_updateAccount(t *testing.T) {
144144
resource.TestCheckResourceAttr(
145145
"cloudstack_project.bar", "name", "terraform-test-project-account"),
146146
resource.TestCheckResourceAttr(
147-
"cloudstack_project.bar", "display_text", "Terraform Test Project with Account"),
147+
"cloudstack_project.bar", "displaytext", "Terraform Test Project with Account"),
148148
resource.TestCheckResourceAttr(
149149
"cloudstack_project.bar", "account", "admin"),
150150
),
@@ -157,7 +157,7 @@ func TestAccCloudStackProject_updateAccount(t *testing.T) {
157157
resource.TestCheckResourceAttr(
158158
"cloudstack_project.bar", "name", "terraform-test-project-account"),
159159
resource.TestCheckResourceAttr(
160-
"cloudstack_project.bar", "display_text", "Terraform Test Project with Account"),
160+
"cloudstack_project.bar", "displaytext", "Terraform Test Project with Account"),
161161
resource.TestCheckResourceAttr(
162162
"cloudstack_project.bar", "account", "admin"),
163163
),
@@ -182,7 +182,7 @@ func TestAccCloudStackProject_emptyDisplayText(t *testing.T) {
182182
resource.TestCheckResourceAttr(
183183
"cloudstack_project.empty", "name", "terraform-test-project-empty-display"),
184184
resource.TestCheckResourceAttr(
185-
"cloudstack_project.empty", "display_text", "terraform-test-project-empty-display"),
185+
"cloudstack_project.empty", "displaytext", "terraform-test-project-empty-display"),
186186
),
187187
},
188188
},
@@ -205,7 +205,7 @@ func TestAccCloudStackProject_updateUserid(t *testing.T) {
205205
resource.TestCheckResourceAttr(
206206
"cloudstack_project.baz", "name", "terraform-test-project-userid"),
207207
resource.TestCheckResourceAttr(
208-
"cloudstack_project.baz", "display_text", "Terraform Test Project with Userid"),
208+
"cloudstack_project.baz", "displaytext", "Terraform Test Project with Userid"),
209209
),
210210
},
211211
{
@@ -216,7 +216,7 @@ func TestAccCloudStackProject_updateUserid(t *testing.T) {
216216
resource.TestCheckResourceAttr(
217217
"cloudstack_project.baz", "name", "terraform-test-project-userid-updated"),
218218
resource.TestCheckResourceAttr(
219-
"cloudstack_project.baz", "display_text", "Terraform Test Project with Userid Updated"),
219+
"cloudstack_project.baz", "displaytext", "Terraform Test Project with Userid Updated"),
220220
),
221221
},
222222
},
@@ -403,51 +403,89 @@ func testAccCheckCloudStackProjectDestroy(s *terraform.State) error {
403403
const testAccCloudStackProject_basic = `
404404
resource "cloudstack_project" "foo" {
405405
name = "terraform-test-project"
406-
display_text = "Terraform Test Project"
406+
displaytext = "Terraform Test Project"
407407
}`
408408

409409
const testAccCloudStackProject_update = `
410410
resource "cloudstack_project" "foo" {
411411
name = "terraform-test-project-updated"
412-
display_text = "Terraform Test Project Updated"
412+
displaytext = "Terraform Test Project Updated"
413413
}`
414414

415415
const testAccCloudStackProject_account = `
416416
resource "cloudstack_project" "bar" {
417417
name = "terraform-test-project-account"
418-
display_text = "Terraform Test Project with Account"
418+
displaytext = "Terraform Test Project with Account"
419419
account = "admin"
420420
domain = "ROOT"
421421
}`
422422

423423
const testAccCloudStackProject_updateAccount = `
424424
resource "cloudstack_project" "bar" {
425425
name = "terraform-test-project-account"
426-
display_text = "Terraform Test Project with Account"
426+
displaytext = "Terraform Test Project with Account"
427427
account = "admin"
428428
domain = "ROOT"
429429
}`
430430

431431
const testAccCloudStackProject_userid = `
432432
resource "cloudstack_project" "baz" {
433433
name = "terraform-test-project-userid"
434-
display_text = "Terraform Test Project with Userid"
434+
displaytext = "Terraform Test Project with Userid"
435435
domain = "ROOT"
436436
}`
437437

438438
const testAccCloudStackProject_updateUserid = `
439439
resource "cloudstack_project" "baz" {
440440
name = "terraform-test-project-userid-updated"
441-
display_text = "Terraform Test Project with Userid Updated"
441+
displaytext = "Terraform Test Project with Userid Updated"
442442
domain = "ROOT"
443443
}`
444444

445445
const testAccCloudStackProject_emptyDisplayText = `
446446
resource "cloudstack_project" "empty" {
447447
name = "terraform-test-project-empty-display"
448-
display_text = "terraform-test-project-empty-display"
448+
displaytext = "terraform-test-project-empty-display"
449449
}`
450450

451+
func TestAccCloudStackProject_updateAccountid(t *testing.T) {
452+
var project cloudstack.Project
453+
454+
resource.Test(t, resource.TestCase{
455+
PreCheck: func() { testAccPreCheck(t) },
456+
Providers: testAccProviders,
457+
CheckDestroy: testAccCheckCloudStackProjectDestroy,
458+
Steps: []resource.TestStep{
459+
{
460+
Config: testAccCloudStackProject_accountid,
461+
Check: resource.ComposeTestCheckFunc(
462+
testAccCheckCloudStackProjectExists(
463+
"cloudstack_project.accountid_test", &project),
464+
resource.TestCheckResourceAttr(
465+
"cloudstack_project.accountid_test", "name", "terraform-test-project-accountid"),
466+
resource.TestCheckResourceAttr(
467+
"cloudstack_project.accountid_test", "displaytext", "Terraform Test Project with Accountid"),
468+
resource.TestCheckResourceAttrSet(
469+
"cloudstack_project.accountid_test", "accountid"),
470+
),
471+
},
472+
{
473+
Config: testAccCloudStackProject_updateAccountid,
474+
Check: resource.ComposeTestCheckFunc(
475+
testAccCheckCloudStackProjectExists(
476+
"cloudstack_project.accountid_test", &project),
477+
resource.TestCheckResourceAttr(
478+
"cloudstack_project.accountid_test", "name", "terraform-test-project-accountid"),
479+
resource.TestCheckResourceAttr(
480+
"cloudstack_project.accountid_test", "displaytext", "Terraform Test Project with Accountid"),
481+
resource.TestCheckResourceAttrSet(
482+
"cloudstack_project.accountid_test", "accountid"),
483+
),
484+
},
485+
},
486+
})
487+
}
488+
451489
func TestAccCloudStackProject_list(t *testing.T) {
452490
resource.Test(t, resource.TestCase{
453491
PreCheck: func() { testAccPreCheck(t) },
@@ -511,13 +549,29 @@ func testAccCheckCloudStackProjectsExist(projectNames ...string) resource.TestCh
511549
}
512550
}
513551

552+
const testAccCloudStackProject_accountid = `
553+
resource "cloudstack_project" "accountid_test" {
554+
name = "terraform-test-project-accountid"
555+
displaytext = "Terraform Test Project with Accountid"
556+
accountid = "1"
557+
domain = "ROOT"
558+
}`
559+
560+
const testAccCloudStackProject_updateAccountid = `
561+
resource "cloudstack_project" "accountid_test" {
562+
name = "terraform-test-project-accountid"
563+
displaytext = "Terraform Test Project with Accountid"
564+
accountid = "2"
565+
domain = "ROOT"
566+
}`
567+
514568
const testAccCloudStackProject_list = `
515569
resource "cloudstack_project" "project1" {
516570
name = "terraform-test-project-list-1"
517-
display_text = "Terraform Test Project List 1"
571+
displaytext = "Terraform Test Project List 1"
518572
}
519573
520574
resource "cloudstack_project" "project2" {
521575
name = "terraform-test-project-list-2"
522-
display_text = "Terraform Test Project List 2"
576+
displaytext = "Terraform Test Project List 2"
523577
}`

0 commit comments

Comments
 (0)