6
6
"os"
7
7
"sort"
8
8
9
+ "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
9
10
"github.com/IBM/vpc-go-sdk/vpcv1"
10
11
"gopkg.in/yaml.v3"
11
12
)
@@ -15,6 +16,11 @@ const (
15
16
maxPowerConnectionsPerZone = 2
16
17
)
17
18
19
+ type GetTestRegionOptions struct {
20
+ // exclude a region if it contains an Activity Tracker
21
+ ExcludeActivityTrackerRegions bool
22
+ }
23
+
18
24
// GetAvailableVpcRegions is a method for receiver CloudInfoService that will query the caller account
19
25
// for all regions that support the VPC resource type and are available in the account.
20
26
// Returns an array of vpcv1.Region and error.
@@ -44,12 +50,34 @@ func (infoSvc *CloudInfoService) GetAvailableVpcRegions() ([]vpcv1.Region, error
44
50
}
45
51
46
52
// GetLeastVpcTestRegion is a method for receiver CloudInfoService that will determine a region available
53
+ // to the caller account that currently contains the least amount of deployed VPCs, using default options.
54
+ // Returns a string representing an IBM Cloud region name, and error.
55
+ func (infoSvc * CloudInfoService ) GetLeastVpcTestRegion () (string , error ) {
56
+ // Set up default
57
+ options := NewGetTestRegionOptions ()
58
+ return infoSvc .GetLeastVpcTestRegionO (* options )
59
+ }
60
+
61
+ // GetLeastVpcTestRegionWithoutActivityTracker is a method for receiver CloudInfoService that will determine a
62
+ // region available to the caller account that currently contains the least amount of deployed VPCs and does
63
+ // not currently contain an active Activity Tracker instance (can only have one per region).
64
+ // Returns a string representing an IBM Cloud region name, and error.
65
+ func (infoSvc * CloudInfoService ) GetLeastVpcTestRegionWithoutActivityTracker () (string , error ) {
66
+ // get default options
67
+ options := NewGetTestRegionOptions ()
68
+ // change activity tracker setting
69
+ options .ExcludeActivityTrackerRegions = true
70
+
71
+ return infoSvc .GetLeastVpcTestRegionO (* options )
72
+ }
73
+
74
+ // GetLeastVpcTestRegionO is a method for receiver CloudInfoService that will determine a region available
47
75
// to the caller account that currently contains the least amount of deployed VPCs.
48
- // The determination can be influenced by specifying CloudInfoService.regionsData.
76
+ // The determination can be influenced by specifying CloudInfoService.regionsData and supplying appropriate options .
49
77
// If no CloudInfoService.regionsData exists, it will simply loop through all available regions for the caller account
50
78
// and choose a region with lowest VPC count.
51
79
// Returns a string representing an IBM Cloud region name, and error.
52
- func (infoSvc * CloudInfoService ) GetLeastVpcTestRegion ( ) (string , error ) {
80
+ func (infoSvc * CloudInfoService ) GetLeastVpcTestRegionO ( options GetTestRegionOptions ) (string , error ) {
53
81
54
82
var bestregion RegionData
55
83
@@ -58,7 +86,27 @@ func (infoSvc *CloudInfoService) GetLeastVpcTestRegion() (string, error) {
58
86
return "" , err
59
87
}
60
88
61
- for i , region := range regions {
89
+ // if we need to filter out regions by activity tracker existence, prepare a list of those regions
90
+ // NOTE: we only want to do this once at beginning and then use results below
91
+ var atInstanceList []resourcecontrollerv2.ResourceInstance
92
+ var atListErr error
93
+ if options .ExcludeActivityTrackerRegions {
94
+ atInstanceList , atListErr = infoSvc .ListResourcesByCrnServiceName ("logdnaat" )
95
+ if atListErr != nil {
96
+ log .Println ("WARNING: Error retrieving Activity Tracker instances! Ignoring when selecting." )
97
+ atInstanceList = []resourcecontrollerv2.ResourceInstance {}
98
+ }
99
+ }
100
+
101
+ for _ , region := range regions {
102
+ // if option is set, ignore region if there is existing activity tracker
103
+ if options .ExcludeActivityTrackerRegions {
104
+ if regionHasActivityTracker (region .Name , atInstanceList ) {
105
+ log .Println ("Region" , region .Name , "skipped due to Activity Tracker present" )
106
+ continue // ignore and move to next region
107
+ }
108
+ }
109
+
62
110
setErr := infoSvc .vpcService .SetServiceURL (region .Endpoint )
63
111
if setErr != nil {
64
112
log .Println ("Failed to set a service url in vpc service" )
@@ -78,8 +126,8 @@ func (infoSvc *CloudInfoService) GetLeastVpcTestRegion() (string, error) {
78
126
bestregion = region
79
127
log .Println ("--- new best region is" , bestregion .Name )
80
128
break
81
- } else if i == 0 {
82
- bestregion = region // always use first region in list
129
+ } else if len ( bestregion . Name ) == 0 {
130
+ bestregion = region // always use first valid region in list
83
131
log .Println ("--- new best region is" , bestregion .Name )
84
132
} else if region .ResourceCount < bestregion .ResourceCount {
85
133
bestregion = region // use if lower count
@@ -100,6 +148,25 @@ func (infoSvc *CloudInfoService) GetLeastVpcTestRegion() (string, error) {
100
148
return bestregion .Name , nil
101
149
}
102
150
151
+ // regionHasActivityTracker is a helper function to determine if a given region is represented in an array
152
+ // of existing ActivityTracker resource instances.
153
+ // Returns boolean true if region found
154
+ func regionHasActivityTracker (region string , activityTrackerList []resourcecontrollerv2.ResourceInstance ) bool {
155
+
156
+ // don't bother looping if empty
157
+ if len (activityTrackerList ) == 0 {
158
+ return false
159
+ }
160
+
161
+ for _ , at := range activityTrackerList {
162
+ if * at .RegionID == region {
163
+ return true
164
+ }
165
+ }
166
+
167
+ return false
168
+ }
169
+
103
170
// GetTestRegionsByPriority is a method for receiver CloudInfoService that will use the service regionsData
104
171
// to determine a priorty order and region eligibility for test resources to be deployed.
105
172
// The returned array will then be used by various methods to determine best region to use for different test scenarios.
@@ -216,22 +283,24 @@ func (infoSvc *CloudInfoService) GetLeastPowerConnectionZone() (string, error) {
216
283
217
284
for _ , region := range regions {
218
285
219
- connCount := countPowerConnectionsInZone (region .Name , connections )
220
- region .ResourceCount = connCount
221
- log .Println ("Region" , region .Name , "Resource count:" , region .ResourceCount )
222
-
223
- // region list is sorted by priority, so if resource count is zero then short circuit and return, it is the best region
224
- // NOTE: we will also make sure each region is not at total limit of connections, if it is we will move on to next
225
- if region .ResourceCount == 0 {
226
- bestregion = region
227
- log .Println ("--- new best region is" , bestregion .Name )
228
- break
229
- } else if region .ResourceCount < maxPowerConnectionsPerZone && len (bestregion .Name ) == 0 {
230
- bestregion = region // always use first VALID region found in list
231
- log .Println ("--- new best region is" , bestregion .Name )
232
- } else if region .ResourceCount < maxPowerConnectionsPerZone && region .ResourceCount < bestregion .ResourceCount {
233
- bestregion = region // use if valid AND lower count than previous best
234
- log .Println ("--- new best region is" , bestregion .Name )
286
+ if region .UseForTest {
287
+ connCount := countPowerConnectionsInZone (region .Name , connections )
288
+ region .ResourceCount = connCount
289
+ log .Println ("Region" , region .Name , "Resource count:" , region .ResourceCount )
290
+
291
+ // region list is sorted by priority, so if resource count is zero then short circuit and return, it is the best region
292
+ // NOTE: we will also make sure each region is not at total limit of connections, if it is we will move on to next
293
+ if region .ResourceCount == 0 {
294
+ bestregion = region
295
+ log .Println ("--- new best region is" , bestregion .Name )
296
+ break
297
+ } else if region .ResourceCount < maxPowerConnectionsPerZone && len (bestregion .Name ) == 0 {
298
+ bestregion = region // always use first VALID region found in list
299
+ log .Println ("--- new best region is" , bestregion .Name )
300
+ } else if region .ResourceCount < maxPowerConnectionsPerZone && region .ResourceCount < bestregion .ResourceCount {
301
+ bestregion = region // use if valid AND lower count than previous best
302
+ log .Println ("--- new best region is" , bestregion .Name )
303
+ }
235
304
}
236
305
}
237
306
@@ -243,6 +312,28 @@ func (infoSvc *CloudInfoService) GetLeastPowerConnectionZone() (string, error) {
243
312
return bestregion .Name , nil
244
313
}
245
314
315
+ // HasRegionData is a method for receiver CloudInfoService that will respond with a boolean to verify that the service instance
316
+ // has region data loaded. You can use this method to determine if you need to load preference data.
317
+ func (infoSvc * CloudInfoService ) HasRegionData () bool {
318
+ if len (infoSvc .regionsData ) > 0 {
319
+ return true
320
+ } else {
321
+ return false
322
+ }
323
+ }
324
+
325
+ // RemoveRegionForTest is a method for receiver CloudInfoService that will remove a given region for use in test considerations
326
+ // by setting the UseForTest property for the region to false
327
+ func (infoSvc * CloudInfoService ) RemoveRegionForTest (regionID string ) {
328
+ // loop through region data looking for given region
329
+ for i , regionData := range infoSvc .regionsData {
330
+ if regionData .Name == regionID {
331
+ infoSvc .regionsData [i ].UseForTest = false
332
+ break
333
+ }
334
+ }
335
+ }
336
+
246
337
// countPowerConnectionsInZone is a private helper function that will return a count of occurances of
247
338
// the provided zone in a list of existing Powercloud connections.
248
339
func countPowerConnectionsInZone (zone string , connections []* PowerCloudConnectionDetail ) int {
@@ -256,3 +347,10 @@ func countPowerConnectionsInZone(zone string, connections []*PowerCloudConnectio
256
347
257
348
return count
258
349
}
350
+
351
+ // NewGetTestRegionOptions will return the option struct with defaults
352
+ func NewGetTestRegionOptions () * GetTestRegionOptions {
353
+ return & GetTestRegionOptions {
354
+ ExcludeActivityTrackerRegions : false ,
355
+ }
356
+ }
0 commit comments