@@ -34,6 +34,7 @@ import (
34
34
cosSession "github.com/IBM/ibm-cos-sdk-go/aws/session"
35
35
"github.com/IBM/ibm-cos-sdk-go/service/s3"
36
36
tgapiv1 "github.com/IBM/networking-go-sdk/transitgatewayapisv1"
37
+ "github.com/IBM/platform-services-go-sdk/globaltaggingv1"
37
38
"github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
38
39
"github.com/IBM/platform-services-go-sdk/resourcemanagerv2"
39
40
"github.com/IBM/vpc-go-sdk/vpcv1"
@@ -51,6 +52,7 @@ import (
51
52
infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
52
53
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator"
53
54
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/cos"
55
+ "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/globaltagging"
54
56
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs"
55
57
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller"
56
58
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcemanager"
@@ -80,6 +82,7 @@ const (
80
82
// vpcSubnetIPAddressCount is the total IP Addresses for the subnet.
81
83
// Support for custom address prefixes will be added at a later time. Currently, we use the ip count for subnet creation.
82
84
vpcSubnetIPAddressCount int64 = 256
85
+ tagKey = "powervs.cluster.x-k8s.io-resource-owner:"
83
86
)
84
87
85
88
// PowerVSClusterScopeParams defines the input parameters used to create a new PowerVSClusterScope.
@@ -102,6 +105,7 @@ type ClientFactory struct {
102
105
TransitGatewayFactory func () (transitgateway.TransitGateway , error )
103
106
ResourceControllerFactory func () (resourcecontroller.ResourceController , error )
104
107
ResourceManagerFactory func () (resourcemanager.ResourceManager , error )
108
+ GlobalTaggingFactory func () (globaltagging.GlobalTagging , error )
105
109
}
106
110
107
111
// PowerVSClusterScope defines a scope defined around a Power VS Cluster.
@@ -110,6 +114,7 @@ type PowerVSClusterScope struct {
110
114
patchHelper * patch.Helper
111
115
112
116
IBMPowerVSClient powervs.PowerVS
117
+ GlobalTaggingClient globaltagging.GlobalTagging
113
118
IBMVPCClient vpc.Vpc
114
119
TransitGatewayClient transitgateway.TransitGateway
115
120
ResourceClient resourcecontroller.ResourceController
@@ -253,6 +258,18 @@ func NewPowerVSClusterScope(params PowerVSClusterScopeParams) (*PowerVSClusterSc
253
258
Authenticator : auth ,
254
259
}
255
260
261
+ // Create Global Tagging client.
262
+ gtOptions := globaltagging.ServiceOptions {
263
+ GlobalTaggingV1Options : & globaltaggingv1.GlobalTaggingV1Options {
264
+ Authenticator : auth ,
265
+ },
266
+ }
267
+
268
+ globalTaggingClient , err := params .getGlobalTaggingClient (gtOptions )
269
+ if err != nil {
270
+ return nil , fmt .Errorf ("failed to create global tagging client: %w" , err )
271
+ }
272
+
256
273
rmClient , err := params .getResourceManagerClient (rcManagerOptions )
257
274
if err != nil {
258
275
return nil , fmt .Errorf ("failed to create resource manager client: %w" , err )
@@ -267,6 +284,7 @@ func NewPowerVSClusterScope(params PowerVSClusterScopeParams) (*PowerVSClusterSc
267
284
IBMPowerVSClient : powerVSClient ,
268
285
IBMVPCClient : vpcClient ,
269
286
TransitGatewayClient : tgClient ,
287
+ GlobalTaggingClient : globalTaggingClient ,
270
288
ResourceClient : resourceClient ,
271
289
ResourceManagerClient : rmClient ,
272
290
}
@@ -294,6 +312,18 @@ func (params PowerVSClusterScopeParams) getPowerVSClient(options powervs.Service
294
312
return powervs .NewService (options )
295
313
}
296
314
315
+ func (params PowerVSClusterScopeParams ) getGlobalTaggingClient (gtOptions globaltagging.ServiceOptions ) (globaltagging.GlobalTagging , error ) {
316
+ if params .GlobalTaggingFactory != nil {
317
+ return params .GlobalTaggingFactory ()
318
+ }
319
+
320
+ if gtEndpoint := endpoints .FetchEndpoints (string (endpoints .GlobalTagging ), params .ServiceEndpoint ); gtEndpoint != "" {
321
+ params .Logger .V (3 ).Info ("Overriding the default global tagging endpoint" , "GlobaTaggingEndpoint" , gtEndpoint )
322
+ gtOptions .URL = gtEndpoint
323
+ }
324
+ return globaltagging .NewService (gtOptions )
325
+ }
326
+
297
327
func (params PowerVSClusterScopeParams ) getVPCClient () (vpc.Vpc , error ) {
298
328
if params .Logger .V (DEBUGLEVEL ).Enabled () {
299
329
core .SetLoggingLevel (core .LevelDebug )
@@ -859,10 +889,13 @@ func (s *PowerVSClusterScope) createServiceInstance(ctx context.Context) (*resou
859
889
if zone == nil {
860
890
return nil , fmt .Errorf ("PowerVS zone is not set" )
861
891
}
892
+
893
+ tag := tagKey + s .Name ()
862
894
serviceInstance , _ , err := s .ResourceClient .CreateResourceInstance (& resourcecontrollerv2.CreateResourceInstanceOptions {
863
895
Name : s .GetServiceName (infrav1beta2 .ResourceTypeServiceInstance ),
864
896
Target : zone ,
865
897
ResourceGroup : & resourceGroupID ,
898
+ Tags : append (make ([]string , 0 ), tag ),
866
899
ResourcePlanID : ptr .To (resourcecontroller .PowerVSResourcePlanID ),
867
900
})
868
901
if err != nil {
@@ -1084,6 +1117,24 @@ func (s *PowerVSClusterScope) createDHCPServer(ctx context.Context) (*string, er
1084
1117
return dhcpServer .ID , nil
1085
1118
}
1086
1119
1120
+ // TagResource will attach a user Tag to a resource.
1121
+ func (s * PowerVSClusterScope ) TagResource (tagName string , resourceCRN * string ) error {
1122
+ tagOptions := & globaltaggingv1.AttachTagOptions {}
1123
+ tagOptions .SetResources ([]globaltaggingv1.Resource {
1124
+ {
1125
+ ResourceID : resourceCRN ,
1126
+ },
1127
+ })
1128
+
1129
+ tagOptions .SetTagName (tagName )
1130
+ tagOptions .SetTagType (globaltaggingv1 .AttachTagOptionsTagTypeUserConst )
1131
+ if _ , _ , err := s .GlobalTaggingClient .AttachTag (tagOptions ); err != nil {
1132
+ return fmt .Errorf ("failure tagging resource: %w" , err )
1133
+ }
1134
+
1135
+ return nil
1136
+ }
1137
+
1087
1138
// ReconcileVPC reconciles VPC.
1088
1139
func (s * PowerVSClusterScope ) ReconcileVPC (ctx context.Context ) (bool , error ) {
1089
1140
log := ctrl .LoggerFrom (ctx )
@@ -1124,7 +1175,7 @@ func (s *PowerVSClusterScope) ReconcileVPC(ctx context.Context) (bool, error) {
1124
1175
1125
1176
// create VPC
1126
1177
log .Info ("Creating a VPC" )
1127
- vpcID , err = s .createVPC ()
1178
+ vpcID , err = s .createVPC (ctx )
1128
1179
if err != nil {
1129
1180
return false , fmt .Errorf ("failed to create VPC: %w" , err )
1130
1181
}
@@ -1168,7 +1219,8 @@ func (s *PowerVSClusterScope) getVPCByName() (*vpcv1.VPC, error) {
1168
1219
}
1169
1220
1170
1221
// createVPC creates VPC.
1171
- func (s * PowerVSClusterScope ) createVPC () (* string , error ) {
1222
+ func (s * PowerVSClusterScope ) createVPC (ctx context.Context ) (* string , error ) {
1223
+ log := ctrl .LoggerFrom (ctx )
1172
1224
resourceGroupID := s .GetResourceGroupID ()
1173
1225
if resourceGroupID == "" {
1174
1226
return nil , fmt .Errorf ("failed to fetch resource group ID for resource group %v, ID is empty" , s .ResourceGroup ())
@@ -1184,6 +1236,11 @@ func (s *PowerVSClusterScope) createVPC() (*string, error) {
1184
1236
return nil , err
1185
1237
}
1186
1238
1239
+ tag := tagKey + s .Name ()
1240
+ if err = s .TagResource (tag , vpcDetails .CRN ); err != nil {
1241
+ log .Error (err , "failed to tag vpc" )
1242
+ }
1243
+
1187
1244
// set security group for vpc
1188
1245
options := & vpcv1.CreateSecurityGroupRuleOptions {}
1189
1246
options .SetSecurityGroupID (* vpcDetails .DefaultSecurityGroup .ID )
@@ -1270,7 +1327,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSubnets(ctx context.Context) (bool, er
1270
1327
subnet .Zone = & vpcZones [index % len (vpcZones )]
1271
1328
}
1272
1329
log .Info ("Creating VPC subnet" )
1273
- subnetID , err = s .createVPCSubnet (subnet )
1330
+ subnetID , err = s .createVPCSubnet (ctx , subnet )
1274
1331
if err != nil {
1275
1332
return false , fmt .Errorf ("error creating VPC subnet: %w" , err )
1276
1333
}
@@ -1299,7 +1356,8 @@ func (s *PowerVSClusterScope) checkVPCSubnet(ctx context.Context, subnetName str
1299
1356
}
1300
1357
1301
1358
// createVPCSubnet creates a VPC subnet.
1302
- func (s * PowerVSClusterScope ) createVPCSubnet (subnet infrav1beta2.Subnet ) (* string , error ) {
1359
+ func (s * PowerVSClusterScope ) createVPCSubnet (ctx context.Context , subnet infrav1beta2.Subnet ) (* string , error ) {
1360
+ log := ctrl .LoggerFrom (ctx )
1303
1361
// TODO(karthik-k-n): consider moving to clusterscope
1304
1362
// fetch resource group id
1305
1363
resourceGroupID := s .GetResourceGroupID ()
@@ -1338,6 +1396,12 @@ func (s *PowerVSClusterScope) createVPCSubnet(subnet infrav1beta2.Subnet) (*stri
1338
1396
if subnetDetails == nil {
1339
1397
return nil , fmt .Errorf ("created VPC subnet is nil" )
1340
1398
}
1399
+
1400
+ tag := tagKey + s .Name ()
1401
+ err = s .TagResource (tag , subnetDetails .CRN )
1402
+ if err != nil {
1403
+ log .Error (err , "failed to tag subnet" )
1404
+ }
1341
1405
return subnetDetails .ID , nil
1342
1406
}
1343
1407
@@ -1560,7 +1624,12 @@ func (s *PowerVSClusterScope) createVPCSecurityGroup(ctx context.Context, spec i
1560
1624
if err != nil {
1561
1625
return nil , fmt .Errorf ("error creating VPC security group: %w" , err )
1562
1626
}
1563
- // To-Do: Add tags to VPC security group, need to implement the client for "github.com/IBM/platform-services-go-sdk/globaltaggingv1".
1627
+
1628
+ tag := tagKey + s .Name ()
1629
+ err = s .TagResource (tag , securityGroup .CRN )
1630
+ if err != nil {
1631
+ log .Error (err , "failed to tag security group" )
1632
+ }
1564
1633
return securityGroup .ID , nil
1565
1634
}
1566
1635
@@ -1987,6 +2056,7 @@ func (s *PowerVSClusterScope) createTransitGatewayConnections(ctx context.Contex
1987
2056
1988
2057
// createTransitGateway creates transit gateway and sets the transit gateway status.
1989
2058
func (s * PowerVSClusterScope ) createTransitGateway (ctx context.Context ) error {
2059
+ log := ctrl .LoggerFrom (ctx )
1990
2060
// fetch resource group id
1991
2061
resourceGroupID := s .GetResourceGroupID ()
1992
2062
if resourceGroupID == "" {
@@ -2023,6 +2093,12 @@ func (s *PowerVSClusterScope) createTransitGateway(ctx context.Context) error {
2023
2093
return err
2024
2094
}
2025
2095
2096
+ tag := tagKey + s .Name ()
2097
+ err = s .TagResource (tag , tg .Crn )
2098
+ if err != nil {
2099
+ log .Error (err , "failed to tag transitGateway" )
2100
+ }
2101
+
2026
2102
s .SetTransitGatewayStatus (tg .ID , ptr .To (true ))
2027
2103
2028
2104
vpcCRN , err := s .fetchVPCCRN ()
@@ -2243,6 +2319,12 @@ func (s *PowerVSClusterScope) createLoadBalancer(ctx context.Context, lb infrav1
2243
2319
if err != nil {
2244
2320
return nil , fmt .Errorf ("failed to create load balancer: %w" , err )
2245
2321
}
2322
+
2323
+ tag := tagKey + s .Name ()
2324
+ if err = s .TagResource (tag , loadBalancer .CRN ); err != nil {
2325
+ log .Error (err , "failed to tag load balancer" )
2326
+ }
2327
+
2246
2328
lbState := infrav1beta2 .VPCLoadBalancerState (* loadBalancer .ProvisioningStatus )
2247
2329
return & infrav1beta2.VPCLoadBalancerStatus {
2248
2330
ID : loadBalancer .ID ,
@@ -2398,12 +2480,14 @@ func (s *PowerVSClusterScope) createCOSServiceInstance() (*resourcecontrollerv2.
2398
2480
return nil , fmt .Errorf ("failed to fetch resource group ID for resource group %v, ID is empty" , s .ResourceGroup ())
2399
2481
}
2400
2482
2483
+ tag := tagKey + s .Name ()
2401
2484
target := "Global"
2402
2485
// create service instance
2403
2486
serviceInstance , _ , err := s .ResourceClient .CreateResourceInstance (& resourcecontrollerv2.CreateResourceInstanceOptions {
2404
2487
Name : s .GetServiceName (infrav1beta2 .ResourceTypeCOSInstance ),
2405
2488
Target : & target ,
2406
2489
ResourceGroup : & resourceGroupID ,
2490
+ Tags : append (make ([]string , 0 ), tag ),
2407
2491
ResourcePlanID : ptr .To (resourcecontroller .CosResourcePlanID ),
2408
2492
})
2409
2493
if err != nil {
0 commit comments