@@ -21,21 +21,21 @@ import (
21
21
"strings"
22
22
23
23
"github.com/apache/cloudstack-go/v2/cloudstack"
24
- infrav1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
24
+ capcv1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1"
25
25
"github.com/hashicorp/go-multierror"
26
26
"github.com/pkg/errors"
27
27
)
28
28
29
29
type NetworkIface interface {
30
- ResolveNetworkStatuses (* infrav1 .CloudStackCluster ) error
31
- ResolveNetwork (* infrav1 .CloudStackCluster , * infrav1 .Network ) error
32
- CreateIsolatedNetwork (* infrav1 .CloudStackCluster ) error
33
- OpenFirewallRules (* infrav1 .CloudStackCluster ) error
34
- ResolvePublicIPDetails (* infrav1 .CloudStackCluster ) (* cloudstack.PublicIpAddress , error )
35
- ResolveLoadBalancerRuleDetails (* infrav1 .CloudStackCluster ) error
36
- GetOrCreateLoadBalancerRule (* infrav1 .CloudStackCluster ) error
37
- GetOrCreateIsolatedNetwork (* infrav1 .CloudStackCluster ) error
38
- AssociatePublicIPAddress (* infrav1 .CloudStackCluster ) error
30
+ ResolveNetworkStatuses (* capcv1 .CloudStackCluster ) error
31
+ ResolveNetwork (* capcv1 .CloudStackCluster , * capcv1 .Network ) error
32
+ CreateIsolatedNetwork (* capcv1 .CloudStackCluster ) error
33
+ OpenFirewallRules (* capcv1 .CloudStackCluster ) error
34
+ ResolvePublicIPDetails (* capcv1 .CloudStackCluster ) (* cloudstack.PublicIpAddress , error )
35
+ ResolveLoadBalancerRuleDetails (* capcv1 .CloudStackCluster ) error
36
+ GetOrCreateLoadBalancerRule (* capcv1 .CloudStackCluster ) error
37
+ GetOrCreateIsolatedNetwork (* capcv1 .CloudStackCluster ) error
38
+ AssociatePublicIPAddress (* capcv1 .CloudStackCluster ) error
39
39
}
40
40
41
41
const (
@@ -48,12 +48,10 @@ const (
48
48
49
49
// usesIsolatedNetwork returns true if this cluster is specs an isolated network.
50
50
// Assumes that the a fetch has been done on network statuses prior.
51
- func usesIsolatedNetwork (csCluster * infrav1 .CloudStackCluster ) bool {
51
+ func UsesIsolatedNetwork (csCluster * capcv1 .CloudStackCluster ) bool {
52
52
// Check for Isolated network use case.
53
- if len (csCluster .Spec .Zones ) == 1 { // Where the only specced network
54
- zoneStatus := infrav1.Zone {}
55
- for _ , zoneStatus = range csCluster .Status .Zones {
56
- }
53
+ if len (csCluster .Status .Zones ) == 1 { // Where the only specced network
54
+ zoneStatus := csCluster .Status .Zones .GetOne ()
57
55
if zoneStatus .Network .Type == "" || // doesn't exist or
58
56
zoneStatus .Network .Type == NetworkTypeIsolated { // exists and is an isolated network.
59
57
return true
@@ -62,17 +60,19 @@ func usesIsolatedNetwork(csCluster *infrav1.CloudStackCluster) bool {
62
60
return false
63
61
}
64
62
65
- // networkExists checks that the network already exists based on the presence of all fields.
63
+ // NetworkExists checks that the network already exists based on the presence of all fields.
66
64
// Assumes that the a fetch has been done on network statuses prior.
67
- func networkExists (net infrav1 .Network ) bool {
65
+ func NetworkExists (net capcv1 .Network ) bool {
68
66
if net .Name != "" && net .Type != "" && net .ID != "" {
69
67
return true
70
68
}
71
69
return false
72
70
}
73
71
74
72
// ResolveNetwork fetches networks' ID, Name, and Type.
75
- func (c * client ) ResolveNetwork (csCluster * infrav1.CloudStackCluster , net * infrav1.Network ) (retErr error ) {
73
+ func (c * client ) ResolveNetwork (csCluster * capcv1.CloudStackCluster , net * capcv1.Network ) (retErr error ) {
74
+ // TODO rebuild this to consider cases with networks in many zones.
75
+ // Use ListNetworks instead.
76
76
netName := net .Name
77
77
netDetails , count , err := c .cs .Network .GetNetworkByName (netName )
78
78
if err != nil {
@@ -89,19 +89,17 @@ func (c *client) ResolveNetwork(csCluster *infrav1.CloudStackCluster, net *infra
89
89
// Now get network details.
90
90
netDetails , count , err = c .cs .Network .GetNetworkByID (net .ID )
91
91
if err != nil {
92
- return multierror .Append (retErr , errors .Wrapf (
93
- err , "could not get Network by ID %s" , net .ID ))
92
+ return multierror .Append (retErr , errors .Wrapf (err , "could not get Network by ID %s" , net .ID ))
94
93
} else if count != 1 {
95
- return multierror .Append (retErr , errors .Errorf (
96
- "expected 1 Network with UUID %s, but got %d" , net .ID , count ))
94
+ return multierror .Append (retErr , errors .Errorf ("expected 1 Network with UUID %s, but got %d" , net .ID , count ))
97
95
}
98
96
net .Name = netDetails .Name
99
97
net .ID = netDetails .Id
100
98
net .Type = netDetails .Type
101
99
return nil
102
100
}
103
101
104
- func generateNetworkTagName (csCluster * infrav1 .CloudStackCluster ) string {
102
+ func generateNetworkTagName (csCluster * capcv1 .CloudStackCluster ) string {
105
103
return clusterTagNamePrefix + string (csCluster .UID )
106
104
}
107
105
@@ -118,8 +116,8 @@ func (c *client) getOfferingID() (string, error) {
118
116
119
117
// CreateIsolatedNetwork creates an isolated network in the relevant Zone.
120
118
// Assumes that there is only the one zone in the cluster.
121
- func (c * client ) CreateIsolatedNetwork (csCluster * infrav1 .CloudStackCluster ) (retErr error ) {
122
- zoneStatus := csCluster .Status .Zones [ csCluster . Spec . Zones [ 0 ]. Network . Name ]
119
+ func (c * client ) CreateIsolatedNetwork (csCluster * capcv1 .CloudStackCluster ) (retErr error ) {
120
+ zoneStatus := * csCluster .Status .Zones . GetOne () // Should only be the one...
123
121
netStatus := zoneStatus .Network
124
122
125
123
// Fetch offering ID.
@@ -153,12 +151,7 @@ func (c *client) CreateIsolatedNetwork(csCluster *infrav1.CloudStackCluster) (re
153
151
}
154
152
155
153
// ResolveNetworkStatuses fetches details on all networks specced, but will not modify ACS settings.
156
- func (c * client ) ResolveNetworkStatuses (csCluster * infrav1.CloudStackCluster ) (retErr error ) {
157
- // Copy network spec to status in preparation for network resolution or creation.
158
- for _ , specZone := range csCluster .Spec .Zones {
159
- csCluster .Status .Zones [specZone .ID ] = specZone
160
- }
161
-
154
+ func (c * client ) ResolveNetworkStatuses (csCluster * capcv1.CloudStackCluster ) (retErr error ) {
162
155
// At this point network status should have been populated (copied) from the spec.
163
156
for _ , zoneStatus := range csCluster .Status .Zones {
164
157
if retErr = c .ResolveNetwork (csCluster , & zoneStatus .Network ); retErr == nil { // Found network
@@ -171,13 +164,12 @@ func (c *client) ResolveNetworkStatuses(csCluster *infrav1.CloudStackCluster) (r
171
164
return nil
172
165
}
173
166
174
- func (c * client ) RemoveClusterTagFromNetwork (csCluster * infrav1 .CloudStackCluster , net infrav1 .Network ) (retError error ) {
167
+ func (c * client ) RemoveClusterTagFromNetwork (csCluster * capcv1 .CloudStackCluster , net capcv1 .Network ) (retError error ) {
175
168
176
169
tags , err := c .GetTags (ResourceTypeNetwork , net .ID )
177
170
if err != nil {
178
171
return err
179
172
}
180
- // sourceNAT := publicIP != nil && publicIP.Issourcenat
181
173
182
174
clusterTagName := generateNetworkTagName (csCluster )
183
175
if tagValue := tags [clusterTagName ]; tagValue != "" {
@@ -189,7 +181,7 @@ func (c *client) RemoveClusterTagFromNetwork(csCluster *infrav1.CloudStackCluste
189
181
return nil
190
182
}
191
183
192
- func (c * client ) DeleteNetworkIfNotInUse (csCluster * infrav1 .CloudStackCluster , net infrav1 .Network ) (retError error ) {
184
+ func (c * client ) DeleteNetworkIfNotInUse (csCluster * capcv1 .CloudStackCluster , net capcv1 .Network ) (retError error ) {
193
185
tags , err := c .GetTags (ResourceTypeNetwork , net .ID )
194
186
if err != nil {
195
187
return err
@@ -209,11 +201,14 @@ func (c *client) DeleteNetworkIfNotInUse(csCluster *infrav1.CloudStackCluster, n
209
201
return nil
210
202
}
211
203
212
- func (c * client ) ResolvePublicIPDetails (csCluster * infrav1 .CloudStackCluster ) (* cloudstack.PublicIpAddress , error ) {
204
+ func (c * client ) ResolvePublicIPDetails (csCluster * capcv1 .CloudStackCluster ) (* cloudstack.PublicIpAddress , error ) {
213
205
ip := csCluster .Spec .ControlPlaneEndpoint .Host
214
206
207
+ zoneStatus := csCluster .Status .Zones .GetOne ()
208
+
215
209
p := c .cs .Address .NewListPublicIpAddressesParams ()
216
210
p .SetAllocatedonly (false )
211
+ p .SetZoneid (zoneStatus .ID )
217
212
setIfNotEmpty (csCluster .Spec .Account , p .SetAccount )
218
213
setIfNotEmpty (csCluster .Status .DomainID , p .SetDomainid )
219
214
if ip != "" {
@@ -238,7 +233,7 @@ func (c *client) ResolvePublicIPDetails(csCluster *infrav1.CloudStackCluster) (*
238
233
}
239
234
240
235
// AssociatePublicIPAddress Gets a PublicIP and associates it.
241
- func (c * client ) AssociatePublicIPAddress (csCluster * infrav1 .CloudStackCluster ) (retErr error ) {
236
+ func (c * client ) AssociatePublicIPAddress (csCluster * capcv1 .CloudStackCluster ) (retErr error ) {
242
237
publicAddress , err := c .ResolvePublicIPDetails (csCluster )
243
238
if err != nil {
244
239
return err
@@ -247,24 +242,24 @@ func (c *client) AssociatePublicIPAddress(csCluster *infrav1.CloudStackCluster)
247
242
csCluster .Spec .ControlPlaneEndpoint .Host = publicAddress .Ipaddress
248
243
csCluster .Status .PublicIPID = publicAddress .Id
249
244
250
- if publicAddress .Allocated != "" { // Address already allocated. Allocated is a timestamp -- not a boolean.
251
- return c .AddClusterTag (ResourceTypeIPAddress , publicAddress .Id , csCluster )
252
- } // Address not yet allocated. Allocate now.
245
+ zoneStatus := csCluster .Status .Zones .GetOne ()
253
246
254
247
// Public IP found, but not yet allocated to network.
255
248
p := c .cs .Address .NewAssociateIpAddressParams ()
256
249
p .SetIpaddress (csCluster .Spec .ControlPlaneEndpoint .Host )
250
+ p .SetNetworkid (zoneStatus .Network .ID )
257
251
setIfNotEmpty (csCluster .Spec .Account , p .SetAccount )
258
252
setIfNotEmpty (csCluster .Status .DomainID , p .SetDomainid )
259
- resp , err := c .cs .Address .AssociateIpAddress (p )
260
- if err != nil {
253
+ if _ , err := c .cs .Address .AssociateIpAddress (p ); err != nil {
254
+ return err
255
+ }
256
+ if err := c .AddClusterTag (ResourceTypeIPAddress , publicAddress .Id , csCluster ); err != nil {
261
257
return err
262
258
}
263
- csCluster .Status .PublicIPNetworkID = resp .Networkid
264
259
return nil
265
260
}
266
261
267
- func (c * client ) OpenFirewallRules (csCluster * infrav1 .CloudStackCluster ) (retErr error ) {
262
+ func (c * client ) OpenFirewallRules (csCluster * capcv1 .CloudStackCluster ) (retErr error ) {
268
263
p := c .cs .Firewall .NewCreateEgressFirewallRuleParams (csCluster .Status .PublicIPNetworkID , NetworkProtocolTCP )
269
264
_ , retErr = c .cs .Firewall .CreateEgressFirewallRule (p )
270
265
if retErr != nil && strings .Contains (strings .ToLower (retErr .Error ()), "there is already" ) { // Already a firewall rule here.
@@ -273,7 +268,7 @@ func (c *client) OpenFirewallRules(csCluster *infrav1.CloudStackCluster) (retErr
273
268
return retErr
274
269
}
275
270
276
- func (c * client ) DisassociatePublicIPAddress (csCluster * infrav1 .CloudStackCluster ) (retErr error ) {
271
+ func (c * client ) DisassociatePublicIPAddress (csCluster * capcv1 .CloudStackCluster ) (retErr error ) {
277
272
// Remove the CAPC creation tag, so it won't be there the next time this address is associated.
278
273
retErr = c .DeleteCreatedByCAPCTag (ResourceTypeIPAddress , csCluster .Status .PublicIPID )
279
274
if retErr != nil {
@@ -285,7 +280,7 @@ func (c *client) DisassociatePublicIPAddress(csCluster *infrav1.CloudStackCluste
285
280
return retErr
286
281
}
287
282
288
- func (c * client ) DisassociatePublicIPAddressIfNotInUse (csCluster * infrav1 .CloudStackCluster ) (retError error ) {
283
+ func (c * client ) DisassociatePublicIPAddressIfNotInUse (csCluster * capcv1 .CloudStackCluster ) (retError error ) {
289
284
tagsAllowDisposal , err := c .DoClusterTagsAllowDisposal (ResourceTypeIPAddress , csCluster .Status .PublicIPID )
290
285
if err != nil {
291
286
return err
@@ -305,7 +300,7 @@ func (c *client) DisassociatePublicIPAddressIfNotInUse(csCluster *infrav1.CloudS
305
300
return nil
306
301
}
307
302
308
- func (c * client ) ResolveLoadBalancerRuleDetails (csCluster * infrav1 .CloudStackCluster ) (retErr error ) {
303
+ func (c * client ) ResolveLoadBalancerRuleDetails (csCluster * capcv1 .CloudStackCluster ) (retErr error ) {
309
304
p := c .cs .LoadBalancer .NewListLoadBalancerRulesParams ()
310
305
p .SetPublicipid (csCluster .Status .PublicIPID )
311
306
setIfNotEmpty (csCluster .Spec .Account , p .SetAccount )
@@ -324,7 +319,7 @@ func (c *client) ResolveLoadBalancerRuleDetails(csCluster *infrav1.CloudStackClu
324
319
}
325
320
326
321
// GetOrCreateLoadBalancerRule Create a load balancer rule that can be assigned to instances.
327
- func (c * client ) GetOrCreateLoadBalancerRule (csCluster * infrav1 .CloudStackCluster ) (retErr error ) {
322
+ func (c * client ) GetOrCreateLoadBalancerRule (csCluster * capcv1 .CloudStackCluster ) (retErr error ) {
328
323
// Check if rule exists.
329
324
if err := c .ResolveLoadBalancerRuleDetails (csCluster ); err == nil ||
330
325
! strings .Contains (strings .ToLower (err .Error ()), "no load balancer rule found" ) {
@@ -333,7 +328,8 @@ func (c *client) GetOrCreateLoadBalancerRule(csCluster *infrav1.CloudStackCluste
333
328
334
329
p := c .cs .LoadBalancer .NewCreateLoadBalancerRuleParams (
335
330
"roundrobin" , "Kubernetes_API_Server" , K8sDefaultAPIPort , K8sDefaultAPIPort )
336
- p .SetNetworkid (csCluster .Status .PublicIPNetworkID )
331
+
332
+ p .SetNetworkid (csCluster .Status .Zones .GetOne ().Network .ID )
337
333
if csCluster .Spec .ControlPlaneEndpoint .Port != 0 { // Override default public port if endpoint port specified.
338
334
p .SetPublicport (int (csCluster .Spec .ControlPlaneEndpoint .Port ))
339
335
}
@@ -349,12 +345,12 @@ func (c *client) GetOrCreateLoadBalancerRule(csCluster *infrav1.CloudStackCluste
349
345
return nil
350
346
}
351
347
352
- func (c * client ) DestroyNetwork (net infrav1 .Network ) (retErr error ) {
348
+ func (c * client ) DestroyNetwork (net capcv1 .Network ) (retErr error ) {
353
349
_ , retErr = c .cs .Network .DeleteNetwork (c .cs .Network .NewDeleteNetworkParams (net .ID ))
354
350
return retErr
355
351
}
356
352
357
- func (c * client ) AssignVMToLoadBalancerRule (csCluster * infrav1 .CloudStackCluster , instanceID string ) (retErr error ) {
353
+ func (c * client ) AssignVMToLoadBalancerRule (csCluster * capcv1 .CloudStackCluster , instanceID string ) (retErr error ) {
358
354
359
355
// Check that the instance isn't already in LB rotation.
360
356
lbRuleInstances , retErr := c .cs .LoadBalancer .ListLoadBalancerRuleInstances (
@@ -376,9 +372,9 @@ func (c *client) AssignVMToLoadBalancerRule(csCluster *infrav1.CloudStackCluster
376
372
}
377
373
378
374
// GetOrCreateIsolatedNetwork fetches or builds out the necessary structures for isolated network use.
379
- func (c * client ) GetOrCreateIsolatedNetwork (csCluster * infrav1 .CloudStackCluster ) error {
380
- onlyNetStatus := csCluster .Status .Zones [ csCluster . Spec . Zones [ 0 ]. Network . Name ] .Network
381
- if ! networkExists (onlyNetStatus ) { // create isolated network.
375
+ func (c * client ) GetOrCreateIsolatedNetwork (csCluster * capcv1 .CloudStackCluster ) error {
376
+ onlyNetStatus := csCluster .Status .Zones . GetOne () .Network
377
+ if ! NetworkExists (onlyNetStatus ) { // create isolated network.
382
378
if err := c .CreateIsolatedNetwork (csCluster ); err != nil {
383
379
return err
384
380
}
0 commit comments