Skip to content

Commit 539ff09

Browse files
committed
feat:ZSTAC-75180 Update tag management in go-sdk: create, update, delete, attach and detach tag operations
1 parent 3d06c77 commit 539ff09

File tree

8 files changed

+319
-45
lines changed

8 files changed

+319
-45
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright (c) ZStack.io, Inc.
2+
3+
package client
4+
5+
import (
6+
"encoding/json"
7+
"fmt"
8+
"strings"
9+
10+
"zstack.io/zstack-sdk-go/pkg/param"
11+
"zstack.io/zstack-sdk-go/pkg/view"
12+
)
13+
14+
// CreateUserTag Create a user tag
15+
func (cli *ZSClient) CreateUserTag(params param.CreateTagParam) (view.UserTagInventoryView, error) {
16+
var resp view.UserTagInventoryView
17+
return resp, cli.Post("v1/user-tags", params, &resp)
18+
}
19+
20+
// QueryUserTag Query user tags
21+
func (cli *ZSClient) QueryUserTag(params param.QueryParam) ([]view.UserTagInventoryView, error) {
22+
var tags []view.UserTagInventoryView
23+
return tags, cli.List("v1/user-tags", &params, &tags)
24+
}
25+
26+
// QueryUserTag Query all user tags
27+
func (cli *ZSClient) ListAllUserTags() ([]view.UserTagInventoryView, error) {
28+
params := param.NewQueryParam()
29+
var tags []view.UserTagInventoryView
30+
return tags, cli.ListAll("v1/user-tags", &params, &tags)
31+
}
32+
33+
// GetTag Get tag by uuid
34+
func (cli *ZSClient) GetTag(uuid string) (view.TagInventoryView, error) {
35+
var resp view.TagInventoryView
36+
return resp, cli.Get("v1/tags/", uuid, nil, &resp)
37+
}
38+
39+
// QueryTag
40+
func (cli *ZSClient) QueryTag(params param.QueryParam) ([]view.TagInventoryView, error) {
41+
var tags []view.TagInventoryView
42+
return tags, cli.List("v1/tags", &params, &tags)
43+
}
44+
45+
// QueryTag Query all tags
46+
func (cli *ZSClient) ListAllTags() ([]view.TagInventoryView, error) {
47+
params := param.NewQueryParam()
48+
var tags []view.TagInventoryView
49+
return tags, cli.ListAll("v1/tags", &params, &tags)
50+
}
51+
52+
// CreateTag Create a tag
53+
func (cli *ZSClient) CreateTag(params param.CreateResourceTagParam) (view.TagInventoryView, error) {
54+
var resp view.TagInventoryView
55+
return resp, cli.Post("v1/tags", params, &resp)
56+
}
57+
58+
// UpdateTag updates a tag's properties by its UUID.
59+
// Note: Tags with type 'simple' cannot have their values updated.
60+
// Returns the updated tag inventory and any error encountered.
61+
func (cli *ZSClient) UpdateTag(uuid string, params param.UpdateResourceTagParam) (view.TagInventoryView, error) {
62+
var resp view.TagInventoryView
63+
return resp, cli.Put("v1/tags", uuid, params, &resp)
64+
}
65+
66+
// AttachTagToResource attaches a tag to one or more resources with optional token support.
67+
//
68+
// Parameters:
69+
// - tagUuid: The UUID of the tag to be attached
70+
// - resourceUuids: A slice of resource UUIDs to attach the tag to
71+
// - attachType: Optional parameters:
72+
// - First parameter: "withToken" to enable token support
73+
// - Second parameter: JSON string of tokens (e.g. {"key":"value"})
74+
//
75+
// Returns the result of the attachment operation and any error encountered.
76+
func (cli *ZSClient) AttachTagToResource(tagUuid string, resourceUuids []string, attachType ...string) (view.AttachTagToResourceResult, error) {
77+
params := param.AttachTagToResourceParam{
78+
BaseParam: param.BaseParam{},
79+
Params: param.AttachTagToResourceDetailParam{
80+
ResourceUuids: resourceUuids,
81+
},
82+
}
83+
84+
if len(attachType) > 0 && attachType[0] == "withToken" {
85+
if len(attachType) > 1 {
86+
var tokens map[string]interface{}
87+
tokenStr := attachType[1]
88+
89+
//tokenStr = strings.ReplaceAll(tokenStr, "", "\"")
90+
91+
err := json.Unmarshal([]byte(tokenStr), &tokens)
92+
if err != nil {
93+
return view.AttachTagToResourceResult{}, fmt.Errorf("invalid tokens format: %v", err)
94+
}
95+
params.Params.Tokens = tokens
96+
} else {
97+
return view.AttachTagToResourceResult{}, fmt.Errorf("attachType 'withToken' requires token string")
98+
}
99+
100+
}
101+
102+
var tag view.AttachTagToResourceResult
103+
104+
err := cli.PostWithRespKey(fmt.Sprintf("v1/tags/%s/resources", tagUuid), "", params, &tag)
105+
if err != nil {
106+
return tag, err
107+
}
108+
return tag, nil
109+
}
110+
111+
// DetachTagFromResource detaches a tag from one or more resources.
112+
//
113+
// Parameters:
114+
// - tagUuid: The UUID of the tag to be detached
115+
// - resourceUuids: A slice of resource UUIDs to detach the tag from
116+
//
117+
// Returns an error if the detachment operation fails.
118+
func (cli *ZSClient) DetachTagFromResource(tagUuid string, resourceUuids []string) error {
119+
uuidsStr := strings.Join(resourceUuids, ",")
120+
121+
if err := cli.DeleteWithSpec("v1/tags", tagUuid, "resources", fmt.Sprintf("resourceUuids=%s", uuidsStr), nil); err != nil {
122+
return err
123+
}
124+
125+
return nil
126+
}

zstack-sdk-go/pkg/client/user_tags_actions.go

Lines changed: 0 additions & 27 deletions
This file was deleted.

zstack-sdk-go/pkg/param/tag_param.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,37 @@ type UpdateSystemTagParam struct {
3232
type UpdateTagDetailParam struct {
3333
Tag string `json:"tag"`
3434
}
35+
36+
type CreateResourceTagParam struct {
37+
BaseParam
38+
Params CreateResourceTagDetailParam `json:"params"`
39+
}
40+
type CreateResourceTagDetailParam struct {
41+
Name string `json:"name"`
42+
Value string `json:"value"`
43+
Description string `json:"description"`
44+
Color string `json:"color"`
45+
Type string `json:"type"` // type 为 simple 不允许更新其 validValues = {"simple", "withToken"})
46+
}
47+
48+
type UpdateResourceTagParam struct {
49+
BaseParam
50+
UpdateResourceTag UpdateResourceTagDetailParam `json:"updateTag"`
51+
}
52+
53+
type UpdateResourceTagDetailParam struct {
54+
Name string `json:"name"`
55+
Value string `json:"value"` //不允许更改 simple Pattern 的 value,仅允许更改 withToken Pattern 的 key 值,如果是withToken 那么 name::{key1}::{key2} … ::{keyN}
56+
Description string `json:"description"`
57+
Color string `json:"color"`
58+
}
59+
60+
type AttachTagToResourceParam struct {
61+
BaseParam
62+
Params AttachTagToResourceDetailParam `json:"params"`
63+
}
64+
65+
type AttachTagToResourceDetailParam struct {
66+
ResourceUuids []string `json:"resourceUuids"`
67+
Tokens map[string]interface{} `json:"tokens,omitempty"`
68+
}

zstack-sdk-go/pkg/test1/base_actions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const (
1515
// The ZStack Cloud Basic Edition supports login authentication for AccessKey, super admin, and sub-accounts.
1616
// The ZStack Cloud Enterprise Edition supports login authentication for AccessKey, super admin, sub-accounts, and enterprise users.
1717

18-
accountLoginHostname = "172.30.3.3" //ZStack Cloud API endpoint IP address
18+
accountLoginHostname = "172.24.190.38" //ZStack Cloud API endpoint IP address
1919
accountLoginAccountName = "admin"
2020
accountLoginAccountPassword = "password"
2121

zstack-sdk-go/pkg/test1/user_tags_actions_test.go

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
func TestZSClient_GetUserTag(t *testing.T) {
1414
queryParam := param.NewQueryParam()
15-
queryParam.AddQ("resourceUuid=2758914006f244879ec642a82406f8f3")
15+
queryParam.AddQ("resourceUuid=1e7e24218e314b2b80f3c0e655efc3cf")
1616
tags, err := accountLoginCli.QueryUserTag(queryParam)
1717
if err != nil {
1818
t.Errorf("TestQuerySystemTags %v", err)
@@ -35,3 +35,97 @@ func TestCreateUserTag(t *testing.T) {
3535
}
3636
golog.Info(tag)
3737
}
38+
39+
func TestCreateTag(t *testing.T) {
40+
tag, err := accountLoginCli.CreateTag(param.CreateResourceTagParam{
41+
BaseParam: param.BaseParam{},
42+
Params: param.CreateResourceTagDetailParam{
43+
Name: "performance88",
44+
Value: "performance::{performance1}",
45+
Description: "tag2 for test",
46+
Color: "#000000",
47+
Type: "withToken",
48+
},
49+
})
50+
if err != nil {
51+
t.Errorf("TestCreateTag %v", err)
52+
return
53+
}
54+
golog.Info(tag)
55+
}
56+
57+
func TestUpdateTag(t *testing.T) {
58+
tag, err := accountLoginCli.UpdateTag("0d2dfada733746699cbb2a11276ada17", param.UpdateResourceTagParam{
59+
BaseParam: param.BaseParam{},
60+
UpdateResourceTag: param.UpdateResourceTagDetailParam{
61+
Name: "performance50",
62+
// Value: "performance::{performance222}",
63+
Description: "tag for test yz5",
64+
Color: "#000000",
65+
},
66+
})
67+
if err != nil {
68+
t.Errorf("TestUpdateTag %v", err)
69+
return
70+
}
71+
golog.Info(tag)
72+
}
73+
74+
func TestDeleteTag(t *testing.T) {
75+
err := accountLoginCli.DeleteTag("eed8f45ede5348f3960b9dff1cd55f7c", param.DeleteModePermissive)
76+
if err != nil {
77+
t.Errorf("TestDeleteTag %v", err)
78+
return
79+
}
80+
golog.Info("delete tag success")
81+
}
82+
83+
func TestQueryTag(t *testing.T) {
84+
queryParam := param.NewQueryParam()
85+
queryParam.AddQ("name=test::tag1")
86+
tags, err := accountLoginCli.QueryTag(queryParam)
87+
if err != nil {
88+
t.Errorf("TestQueryResourceTags %v", err)
89+
}
90+
golog.Info(tags)
91+
}
92+
93+
func TestListAllTags(t *testing.T) {
94+
tags, err := accountLoginCli.ListAllTags()
95+
if err != nil {
96+
t.Errorf("TestListAllTags %v", err)
97+
}
98+
golog.Info(tags)
99+
}
100+
101+
func TestGetTag(t *testing.T) {
102+
tag, err := accountLoginCli.GetTag("0b0a50adfcba457db09629b3c365d66f")
103+
if err != nil {
104+
t.Errorf("TestGetTag %v", err)
105+
}
106+
golog.Info(tag)
107+
}
108+
109+
func TestAttachTagToResource(t *testing.T) {
110+
tag, err := accountLoginCli.AttachTagToResource("3d7ae53107994d36a202bdf704c007b5", []string{"1e7e24218e314b2b80f3c0e655efc3cf"})
111+
if err != nil {
112+
t.Errorf("TestAttachTagToResource %v", err)
113+
}
114+
golog.Info(tag)
115+
}
116+
117+
func TestAttachTagToResourceWithToken(t *testing.T) {
118+
tag, err := accountLoginCli.AttachTagToResource("0b0a50adfcba457db09629b3c365d66f", []string{"1e7e24218e314b2b80f3c0e655efc3cf"}, "withToken", `{"performance1":"low"}`)
119+
if err != nil {
120+
t.Errorf("TestAttachTagToResourceWithToken %v", err)
121+
}
122+
golog.Info(tag)
123+
}
124+
125+
func TestDetachTagFromResource(t *testing.T) {
126+
err := accountLoginCli.DetachTagFromResource("0b0a50adfcba457db09629b3c365d66f", []string{"1e7e24218e314b2b80f3c0e655efc3cf"})
127+
if err != nil {
128+
t.Errorf("TestDetachTagFromResource %v", err)
129+
}
130+
golog.Info("detach tag success")
131+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) ZStack.io, Inc.
2+
3+
package view
4+
5+
type UserTagInventoryView struct {
6+
Uuid string `json:"uuid"`
7+
ResourceType string `json:"resourceType"`
8+
ResourceUuid string `json:"resourceUuid"`
9+
Tag string `json:"tag"`
10+
Type string `json:"type"`
11+
CreateDate string `json:"createDate"`
12+
LastOpDate string `json:"lastOpDate"`
13+
}
14+
15+
type TagInventoryView struct {
16+
BaseInfoView
17+
BaseTimeView
18+
Color string `json:"color"`
19+
Type string `json:"type"`
20+
// Note: For simple pattern tags, the value cannot be changed.
21+
// For withToken pattern tags, only the key values can be changed.
22+
// WithToken pattern format: name::{key1}::{key2}...::{keyN}
23+
}
24+
25+
type TagInventory struct {
26+
Uuid string `json:"uuid"`
27+
ResourceType string `json:"resourceType"`
28+
ResourceUuid string `json:"resourceUuid"`
29+
Tag string `json:"tag"`
30+
Type string `json:"type"`
31+
// Note: For simple pattern tags, the value cannot be changed.
32+
// For withToken pattern tags, only the key values can be changed.
33+
// WithToken pattern format: name::{key1}::{key2}...::{keyN}
34+
TagPatternUuid string `json:"tagPatternUuid"`
35+
TagPattern TagPatternView `json:"tagPattern"`
36+
CreateDate string `json:"createDate"`
37+
LastOpDate string `json:"lastOpDate"`
38+
}
39+
40+
type TagPatternView struct {
41+
Uuid string `json:"uuid"` // Tag pattern UUID
42+
Name string `json:"name"` // Name of the tag pattern
43+
Value string `json:"value"` // Actual tag value (e.g. withToken::{xxx})
44+
Description string `json:"description"` // Description of the tag
45+
Color string `json:"color"` // Color associated with the tag
46+
Type string `json:"type"` // Tag type: simple | withToken
47+
CreateDate string `json:"createDate"` // Creation timestamp
48+
LastOpDate string `json:"lastOpDate"` // Last update timestamp
49+
}
50+
51+
type AttachTagToResourceResult struct {
52+
Success bool `json:"success"`
53+
Results []AttachTagToResourceResultItem `json:"results"`
54+
}
55+
56+
type AttachTagToResourceResultItem struct {
57+
Inventory TagInventory `json:"inventory"`
58+
Success bool `json:"success"`
59+
}

zstack-sdk-go/pkg/view/user_tag_views.go

Lines changed: 0 additions & 13 deletions
This file was deleted.

zstack/provider/data_source_zstack_instance_guest_tools.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,10 @@ func (d *guestToolsDataSource) Read(ctx context.Context, req datasource.ReadRequ
9393
guest_tools, err := d.client.GetVmGuestToolsInfo(state.InstanceUuid.ValueString())
9494

9595
if err != nil {
96-
resp.Diagnostics.AddError(
97-
"Unable to Read Guest Tools Info",
98-
err.Error(),
96+
resp.Diagnostics.AddWarning(
97+
"Unable to read guest tools info",
98+
fmt.Sprintf("Failed to read guest tools info for instance UUID: %s, error: %s",
99+
state.InstanceUuid.ValueString(), err.Error()),
99100
)
100101
return
101102
}

0 commit comments

Comments
 (0)