@@ -19,12 +19,16 @@ package cloud
19
19
import (
20
20
"strings"
21
21
22
+ "github.com/hashicorp/go-multierror"
23
+
22
24
infrav1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
25
+ "github.com/pkg/errors"
23
26
)
24
27
25
28
type TagIface interface {
26
- AddClusterTag (ResourceType , string , * infrav1.CloudStackCluster , bool ) error
29
+ AddClusterTag (ResourceType , string , * infrav1.CloudStackCluster ) error
27
30
DeleteClusterTag (ResourceType , string , * infrav1.CloudStackCluster ) error
31
+ AddCreatedByCAPCTag (ResourceType , string ) error
28
32
DeleteCreatedByCAPCTag (ResourceType , string ) error
29
33
DoClusterTagsAllowDisposal (ResourceType , string ) (bool , error )
30
34
AddTags (ResourceType , string , map [string ]string ) error
@@ -41,62 +45,37 @@ const (
41
45
ResourceTypeIPAddress ResourceType = "PublicIpAddress"
42
46
)
43
47
44
- // AddClusterTag adds cluster-related tags to a resource. One tag indicates that the resource is used by a given
45
- // cluster. The other tag, if applied, indicates that CAPC created the resource and may dispose of it later.
46
- func (c * client ) AddClusterTag (
47
- resourceType ResourceType ,
48
- resourceID string ,
49
- csCluster * infrav1.CloudStackCluster ,
50
- addCreatedByCAPCTag bool ,
51
- ) error {
52
-
53
- clusterTagName := generateClusterTagName (csCluster )
54
- newTags := map [string ]string {}
55
-
56
- existingTags , err := c .GetTags (resourceType , resourceID )
57
- if err != nil {
48
+ // ignoreAlreadyPresentErrors returns nil if the error is an already present tag error.
49
+ func ignoreAlreadyPresentErrors (err error , rType ResourceType , rID string ) error {
50
+ matchSubString := strings .ToLower ("already on " + string (rType ) + " with id " + rID )
51
+ if err != nil && ! strings .Contains (strings .ToLower (err .Error ()), matchSubString ) {
58
52
return err
59
53
}
60
-
61
- if existingTags [clusterTagName ] == "" {
62
- newTags [clusterTagName ] = "1"
63
- }
64
-
65
- if len (newTags ) > 0 {
66
- return c .AddTags (resourceType , resourceID , newTags )
67
- }
68
-
69
54
return nil
70
55
}
71
56
72
- // DeleteClusterTag deletes the tag that associates the resource with a given cluster.
73
- func (c * client ) DeleteClusterTag (resourceType ResourceType , resourceID string , csCluster * infrav1.CloudStackCluster ) error {
74
- tags , err := c .GetTags (resourceType , resourceID )
75
- if err != nil {
76
- return err
77
- }
57
+ // AddClusterTag adds cluster tag to a resource. This tag indicates the resource is used by a given the cluster.
58
+ func (c * client ) AddClusterTag (rType ResourceType , rID string , csCluster * infrav1.CloudStackCluster ) error {
59
+ clusterTagName := generateClusterTagName (csCluster )
60
+ return c .AddTags (rType , rID , map [string ]string {clusterTagName : "1" })
61
+ }
78
62
63
+ // DeleteClusterTag deletes the tag that associates the resource with a given cluster.
64
+ func (c * client ) DeleteClusterTag (rType ResourceType , rID string , csCluster * infrav1.CloudStackCluster ) error {
79
65
clusterTagName := generateClusterTagName (csCluster )
80
- if tagValue := tags [clusterTagName ]; tagValue != "" {
81
- return c .DeleteTags (resourceType , resourceID , map [string ]string {clusterTagName : tagValue })
82
- }
66
+ return c .DeleteTags (rType , rID , map [string ]string {clusterTagName : "1" })
67
+ }
83
68
84
- return nil
69
+ // AddCreatedByCAPCTag deletes the tag that indicates that the resource was created by CAPC. This is useful when a
70
+ // resource is disassociated instead of deleted. That way the tag won't cause confusion if the resource is reused later.
71
+ func (c * client ) AddCreatedByCAPCTag (rType ResourceType , rID string ) error {
72
+ return c .AddTags (rType , rID , map [string ]string {createdByCAPCTagName : "1" })
85
73
}
86
74
87
75
// DeleteCreatedByCAPCTag deletes the tag that indicates that the resource was created by CAPC. This is useful when a
88
76
// resource is disassociated instead of deleted. That way the tag won't cause confusion if the resource is reused later.
89
- func (c * client ) DeleteCreatedByCAPCTag (resourceType ResourceType , resourceID string ) error {
90
- tags , err := c .GetTags (resourceType , resourceID )
91
- if err != nil {
92
- return err
93
- }
94
-
95
- if tagValue := tags [createdByCAPCTagName ]; tagValue != "" {
96
- return c .DeleteTags (resourceType , resourceID , map [string ]string {createdByCAPCTagName : tagValue })
97
- }
98
-
99
- return nil
77
+ func (c * client ) DeleteCreatedByCAPCTag (rType ResourceType , rID string ) error {
78
+ return c .DeleteTags (rType , rID , map [string ]string {createdByCAPCTagName : "1" })
100
79
}
101
80
102
81
// DoClusterTagsAllowDisposal checks to see if the resource is in a state that makes it eligible for disposal. CAPC can
@@ -121,7 +100,7 @@ func (c *client) DoClusterTagsAllowDisposal(resourceType ResourceType, resourceI
121
100
func (c * client ) AddTags (resourceType ResourceType , resourceID string , tags map [string ]string ) error {
122
101
p := c .cs .Resourcetags .NewCreateTagsParams ([]string {resourceID }, string (resourceType ), tags )
123
102
_ , err := c .cs .Resourcetags .CreateTags (p )
124
- return err
103
+ return ignoreAlreadyPresentErrors ( err , resourceType , resourceID )
125
104
}
126
105
127
106
// GetTags gets all of a resource's tags.
@@ -141,13 +120,23 @@ func (c *client) GetTags(resourceType ResourceType, resourceID string) (map[stri
141
120
return tags , nil
142
121
}
143
122
144
- // DeleteTags deletes the given tags from a resource. If the tags don't exist, or if the values don't match, it will
145
- // result in an error .
123
+ // DeleteTags deletes the given tags from a resource.
124
+ // Ignores errors if the tag is not present .
146
125
func (c * client ) DeleteTags (resourceType ResourceType , resourceID string , tagsToDelete map [string ]string ) error {
147
- p := c .cs .Resourcetags .NewDeleteTagsParams ([]string {resourceID }, string (resourceType ))
148
- p .SetTags (tagsToDelete )
149
- _ , err := c .cs .Resourcetags .DeleteTags (p )
150
- return err
126
+ for tagkey , tagval := range tagsToDelete {
127
+ p := c .cs .Resourcetags .NewDeleteTagsParams ([]string {resourceID }, string (resourceType ))
128
+ p .SetTags (tagsToDelete )
129
+ if _ , err1 := c .cs .Resourcetags .DeleteTags (p ); err1 != nil { // Error in deletion attempt. Check for tag.
130
+ currTag := map [string ]string {tagkey : tagval }
131
+ if tags , err2 := c .GetTags (resourceType , resourceID ); len (tags ) != 0 {
132
+ if _ , foundTag := tags [tagkey ]; foundTag {
133
+ return errors .Wrapf (multierror .Append (err1 , err2 ),
134
+ "could not remove tag %s from %s with ID %s" , currTag , resourceType , resourceID )
135
+ }
136
+ }
137
+ }
138
+ }
139
+ return nil
151
140
}
152
141
153
142
func generateClusterTagName (csCluster * infrav1.CloudStackCluster ) string {
0 commit comments