Skip to content

Commit 48a9591

Browse files
committed
feat(workspace/app): the APP server group supports to modify tags
1 parent e7633c6 commit 48a9591

File tree

3 files changed

+214
-10
lines changed

3 files changed

+214
-10
lines changed

docs/resources/workspace_app_server_group.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,8 @@ The following arguments are supported:
106106

107107
* `description` - (Optional, String) Specifies the description of the server group.
108108

109-
* `tags` - (Optional, Map, ForceNew) Specifies the key/value pairs to associate with the server group.
110-
Supports up to 20 tags.
111-
Changing this creates a new resource.
109+
* `tags` - (Optional, Map) Specifies the key/value pairs to associate with the server group.
110+
Supports up to `20` tags.
112111

113112
* `enterprise_project_id` - (Optional, String, ForceNew) Specifies the ID of the enterprise project to which the
114113
server group belong.

huaweicloud/services/acceptance/workspace/resource_huaweicloud_workspace_app_server_group_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,143 @@ resource "huaweicloud_workspace_app_server_group" "test" {
230230
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_ID,
231231
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_PRODUCT_ID)
232232
}
233+
234+
func TestAccResourceAppServerGroup_singleSession(t *testing.T) {
235+
var (
236+
name = acceptance.RandomAccResourceName()
237+
updateName = acceptance.RandomAccResourceName()
238+
239+
obj interface{}
240+
resourceName = "huaweicloud_workspace_app_server_group.test"
241+
rc = acceptance.InitResourceCheck(resourceName, &obj, getResourceAppServerGroupFunc)
242+
)
243+
resource.ParallelTest(t, resource.TestCase{
244+
PreCheck: func() {
245+
acceptance.TestAccPreCheck(t)
246+
acceptance.TestAccPreCheckWorkspaceAppServerGroup(t)
247+
acceptance.TestAccPreCheckEpsID(t)
248+
},
249+
ProviderFactories: acceptance.TestAccProviderFactories,
250+
CheckDestroy: rc.CheckResourceDestroy(),
251+
Steps: []resource.TestStep{
252+
{
253+
Config: testAccResourceAppServerGroup_singleSession_step1(name),
254+
Check: resource.ComposeTestCheckFunc(
255+
rc.CheckResourceExists(),
256+
resource.TestCheckResourceAttr(resourceName, "name", name),
257+
resource.TestCheckResourceAttr(resourceName, "os_type", "Windows"),
258+
resource.TestCheckResourceAttr(resourceName, "flavor_id", acceptance.HW_WORKSPACE_APP_SERVER_GROUP_FLAVOR_ID),
259+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id",
260+
"data.huaweicloud_workspace_service.test", "vpc_id"),
261+
resource.TestCheckResourceAttrPair(resourceName, "subnet_id",
262+
"data.huaweicloud_workspace_service.test", "network_ids.0"),
263+
resource.TestCheckResourceAttr(resourceName, "system_disk_type", "SAS"),
264+
resource.TestCheckResourceAttr(resourceName, "system_disk_size", "90"),
265+
resource.TestCheckResourceAttr(resourceName, "image_id", acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_ID),
266+
resource.TestCheckResourceAttr(resourceName, "image_type", "gold"),
267+
resource.TestCheckResourceAttr(resourceName, "image_product_id",
268+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_PRODUCT_ID),
269+
resource.TestCheckResourceAttr(resourceName, "is_vdi", "true"),
270+
resource.TestCheckResourceAttr(resourceName, "description", "Created by script"),
271+
resource.TestCheckResourceAttr(resourceName, "app_type", "SESSION_DESKTOP_APP"),
272+
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
273+
resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar"),
274+
resource.TestCheckResourceAttr(resourceName, "enterprise_project_id", acceptance.HW_ENTERPRISE_PROJECT_ID_TEST),
275+
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
276+
resource.TestCheckResourceAttr(resourceName, "storage_mount_policy", "USER"),
277+
),
278+
},
279+
{
280+
Config: testAccResourceAppServerGroup_singleSession_step2(updateName),
281+
Check: resource.ComposeTestCheckFunc(
282+
rc.CheckResourceExists(),
283+
resource.TestCheckResourceAttr(resourceName, "name", updateName),
284+
resource.TestCheckResourceAttr(resourceName, "system_disk_type", "SAS"),
285+
resource.TestCheckResourceAttr(resourceName, "system_disk_size", "80"),
286+
resource.TestCheckResourceAttr(resourceName, "description", ""),
287+
resource.TestCheckResourceAttr(resourceName, "app_type", "SESSION_DESKTOP_APP"),
288+
resource.TestCheckResourceAttr(resourceName, "enabled", "false"),
289+
resource.TestCheckResourceAttr(resourceName, "storage_mount_policy", "SHARE"),
290+
resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
291+
resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar_update"),
292+
resource.TestCheckResourceAttr(resourceName, "tags.owner", "terraform"),
293+
),
294+
},
295+
{
296+
ResourceName: resourceName,
297+
ImportState: true,
298+
ImportStateVerify: true,
299+
ImportStateVerifyIgnore: []string{
300+
"vpc_id", "image_type", "image_product_id", "availability_zone",
301+
},
302+
},
303+
},
304+
})
305+
}
306+
307+
func testAccResourceAppServerGroup_singleSession_step1(name string) string {
308+
return fmt.Sprintf(`
309+
data "huaweicloud_workspace_service" "test" {}
310+
311+
resource "huaweicloud_workspace_app_server_group" "test" {
312+
name = "%[1]s"
313+
os_type = "Windows"
314+
flavor_id = "%[2]s"
315+
vpc_id = data.huaweicloud_workspace_service.test.vpc_id
316+
subnet_id = data.huaweicloud_workspace_service.test.network_ids[0]
317+
system_disk_type = "SAS"
318+
system_disk_size = 90
319+
app_type = "SESSION_DESKTOP_APP"
320+
is_vdi = true
321+
image_id = "%[3]s"
322+
image_type = "gold"
323+
image_product_id = "%[4]s"
324+
description = "Created by script"
325+
storage_mount_policy = "USER"
326+
enterprise_project_id = "%[5]s"
327+
328+
tags = {
329+
foo = "bar"
330+
}
331+
}
332+
`, name,
333+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_FLAVOR_ID,
334+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_ID,
335+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_PRODUCT_ID,
336+
acceptance.HW_ENTERPRISE_PROJECT_ID_TEST,
337+
)
338+
}
339+
340+
func testAccResourceAppServerGroup_singleSession_step2(name string) string {
341+
return fmt.Sprintf(`
342+
data "huaweicloud_workspace_service" "test" {}
343+
344+
resource "huaweicloud_workspace_app_server_group" "test" {
345+
name = "%[1]s"
346+
os_type = "Windows"
347+
flavor_id = "%[2]s"
348+
vpc_id = data.huaweicloud_workspace_service.test.vpc_id
349+
subnet_id = data.huaweicloud_workspace_service.test.network_ids[0]
350+
system_disk_type = "SAS"
351+
system_disk_size = 80
352+
app_type = "SESSION_DESKTOP_APP"
353+
is_vdi = true
354+
image_id = "%[3]s"
355+
image_type = "gold"
356+
image_product_id = "%[4]s"
357+
storage_mount_policy = "SHARE"
358+
enabled = false
359+
enterprise_project_id = "%[5]s"
360+
361+
tags = {
362+
foo = "bar_update"
363+
owner = "terraform"
364+
}
365+
}
366+
`, name,
367+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_FLAVOR_ID,
368+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_ID,
369+
acceptance.HW_WORKSPACE_APP_SERVER_GROUP_IMAGE_PRODUCT_ID,
370+
acceptance.HW_ENTERPRISE_PROJECT_ID_TEST,
371+
)
372+
}

huaweicloud/services/workspace/resource_huaweicloud_workspace_app_server_group.go

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ import (
1616
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
1717
)
1818

19-
// @API WORKSPACEAPP POST /v1/{project_id}/app-server-groups
20-
// @API WORKSPACEAPP GET /v1/{project_id}/app-server-group
21-
// @API WORKSPACEAPP PATCH /v1/{project_id}/app-server-groups/{server_group_id}
22-
// @API WORKSPACEAPP POST /v1/{project_id}/app-server-groups/{server_group_id}
19+
// @API Workspace POST /v1/{project_id}/app-server-groups
20+
// @API Workspace GET /v1/{project_id}/app-server-group
21+
// @API Workspace PATCH /v1/{project_id}/app-server-groups/{server_group_id}
22+
// @API Workspace POST /v1/{project_id}/server-group/tags/batch-create
23+
// @API Workspace DELETE /v1/{project_id}/server-group/tags/batch-delete
24+
// @API Workspace POST /v1/{project_id}/server-group/tags/{action}
2325
func ResourceAppServerGroup() *schema.Resource {
2426
return &schema.Resource{
2527
CreateContext: resourceAppServerGroupCreate,
@@ -118,7 +120,7 @@ func ResourceAppServerGroup() *schema.Resource {
118120
Optional: true,
119121
Description: `The description of the server group.`,
120122
},
121-
"tags": common.TagsForceNewSchema("The key/value pairs to associate with the server group."),
123+
"tags": common.TagsSchema("The key/value pairs to associate with the server group."),
122124
"enterprise_project_id": {
123125
Type: schema.TypeString,
124126
Optional: true,
@@ -452,7 +454,10 @@ func flattenAppServerGroupFlavor(flavors []interface{}) []map[string]interface{}
452454
}
453455

454456
func resourceAppServerGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
455-
cfg := meta.(*config.Config)
457+
var (
458+
cfg = meta.(*config.Config)
459+
serverGroupId = d.Id()
460+
)
456461
client, err := cfg.NewServiceClient("appstream", cfg.GetRegion(d))
457462
if err != nil {
458463
return diag.Errorf("error creating Workspace APP client: %s", err)
@@ -461,12 +466,18 @@ func resourceAppServerGroupUpdate(ctx context.Context, d *schema.ResourceData, m
461466
if d.HasChanges("name", "system_disk_type", "system_disk_size", "image_id", "image_type", "image_product_id",
462467
"description", "app_type", "route_policy", "ou_name", "enabled", "storage_mount_policy") {
463468
updateOpt := buildUpdateServerGroupBodyParams(d)
464-
serverGroupId := d.Id()
465469
if err := updateAppServerGroup(client, serverGroupId, updateOpt); err != nil {
466470
return diag.Errorf("error updating server group (%s): %s", serverGroupId, err)
467471
}
468472
}
469473

474+
if d.HasChanges("tags") {
475+
oRaw, nRaw := d.GetChange("tags")
476+
if err := updateServerGroupTags(client, serverGroupId, oRaw, nRaw); err != nil {
477+
return diag.FromErr(err)
478+
}
479+
}
480+
470481
return resourceAppServerGroupRead(ctx, d, meta)
471482
}
472483

@@ -505,6 +516,60 @@ func buildUpdateServerGroupBodyParams(d *schema.ResourceData) map[string]interfa
505516
}
506517
}
507518

519+
func updateServerGroupTags(client *golangsdk.ServiceClient, serverGroupId string, oRaw, nRaw interface{}) error {
520+
removeTags := oRaw.(map[string]interface{})
521+
addTags := nRaw.(map[string]interface{})
522+
if len(removeTags) > 0 {
523+
if err := removeServerGroupTags(client, serverGroupId, removeTags); err != nil {
524+
return fmt.Errorf("error removing tags of server group (%s): %s", serverGroupId, err)
525+
}
526+
}
527+
528+
if len(addTags) > 0 {
529+
if err := addServerGroupTags(client, serverGroupId, addTags); err != nil {
530+
return fmt.Errorf("error adding tags of server group (%s): %s", serverGroupId, err)
531+
}
532+
}
533+
534+
return nil
535+
}
536+
537+
func buildUpdateServerGroupTagsBodyParams(serverGroupId string, tags map[string]interface{}) map[string]interface{} {
538+
return map[string]interface{}{
539+
"items": []map[string]interface{}{
540+
{
541+
"server_group_id": serverGroupId,
542+
"tags": utils.ExpandResourceTags(tags),
543+
},
544+
},
545+
}
546+
}
547+
548+
func addServerGroupTags(client *golangsdk.ServiceClient, serverGroupId string, tags map[string]interface{}) error {
549+
httpUrl := "v1/{project_id}/server-group/tags/batch-create"
550+
path := client.Endpoint + httpUrl
551+
path = strings.ReplaceAll(path, "{project_id}", client.ProjectID)
552+
opt := golangsdk.RequestOpts{
553+
KeepResponseBody: true,
554+
JSONBody: buildUpdateServerGroupTagsBodyParams(serverGroupId, tags),
555+
OkCodes: []int{204},
556+
}
557+
_, err := client.Request("POST", path, &opt)
558+
return err
559+
}
560+
561+
func removeServerGroupTags(client *golangsdk.ServiceClient, serverGroupId string, tags map[string]interface{}) error {
562+
httpUrl := "v1/{project_id}/server-group/tags/batch-delete"
563+
path := client.Endpoint + httpUrl
564+
path = strings.ReplaceAll(path, "{project_id}", client.ProjectID)
565+
opt := golangsdk.RequestOpts{
566+
KeepResponseBody: true,
567+
JSONBody: buildUpdateServerGroupTagsBodyParams(serverGroupId, tags),
568+
}
569+
_, err := client.Request("DELETE", path, &opt)
570+
return err
571+
}
572+
508573
func resourceAppServerGroupDelete(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
509574
cfg := meta.(*config.Config)
510575
httpUrl := "v1/{project_id}/app-server-groups/{server_group_id}"

0 commit comments

Comments
 (0)