@@ -45,25 +45,22 @@ func NewController(ec2api *awsprovider.EC2, autoscaling *awsprovider.AutoScaling
45
45
}
46
46
47
47
func (c * Controller ) Reconcile (ctx context.Context , dataplane * v1alpha1.DataPlane ) error {
48
- privateSubnets , err := c .getPrivateSubnetsFor (ctx , dataplane .Spec .ClusterName )
49
- if err != nil {
50
- return fmt .Errorf ("getting private subnet for %s, %w" , dataplane .Spec .ClusterName , err )
51
- }
52
- if len (privateSubnets ) == 0 {
53
- return fmt .Errorf ("failed to find private subnets for dataplane" )
54
- }
55
48
asg , err := c .getAutoScalingGroup (ctx , AutoScalingGroupNameFor (dataplane .Spec .ClusterName ))
56
49
if err != nil {
57
50
return fmt .Errorf ("getting auto scaling group for %v, %w" , dataplane .Spec .ClusterName , err )
58
51
}
59
52
if asg == nil {
60
- if err := c .createAutoScalingGroup (ctx , dataplane , privateSubnets ); err != nil {
53
+ if err := c .createAutoScalingGroup (ctx , dataplane ); err != nil {
61
54
return fmt .Errorf ("creating auto scaling group for %v, %w" , dataplane .Spec .ClusterName , err )
62
55
}
63
56
zap .S ().Infof ("[%s] Created autoscaling group" , dataplane .Spec .ClusterName )
64
57
return nil
65
58
}
66
- if err := c .updateAutoScalingGroup (ctx , dataplane , asg , privateSubnets ); err != nil {
59
+ if asg .Status != nil && * asg .Status == "Delete in progress" {
60
+ // there are scenarios if you delete ASG and recreate quickly ASG might still be getting deleted
61
+ return fmt .Errorf ("ASG %v deletion in progress" , asg .AutoScalingGroupName )
62
+ }
63
+ if err := c .updateAutoScalingGroup (ctx , dataplane , asg ); err != nil {
67
64
return fmt .Errorf ("updating auto scaling group %v, %w" , AutoScalingGroupNameFor (dataplane .Spec .ClusterName ), err )
68
65
}
69
66
return nil
@@ -79,31 +76,65 @@ func (c *Controller) Finalize(ctx context.Context, dataplane *v1alpha1.DataPlane
79
76
return nil
80
77
}
81
78
82
- func (c * Controller ) updateAutoScalingGroup (ctx context.Context , dataplane * v1alpha1.DataPlane , asg * autoscaling.Group , subnets []string ) error {
79
+ func (c * Controller ) updateAutoScalingGroup (ctx context.Context , dataplane * v1alpha1.DataPlane , asg * autoscaling.Group ) error {
80
+ subnets , err := c .subnetsFor (ctx , dataplane )
81
+ if err != nil {
82
+ return fmt .Errorf ("getting private subnet for %s, %w" , dataplane .Spec .ClusterName , err )
83
+ }
84
+ if len (subnets ) == 0 {
85
+ return fmt .Errorf ("failed to find private subnets for dataplane" )
86
+ }
83
87
if functional .ValidateAll (
84
88
func () bool { return asg != nil },
85
89
func () bool {
86
90
return functional .StringsMatch (strings .Split (ptr .StringValue (asg .VPCZoneIdentifier ), "," ), subnets )
87
91
},
88
- func () bool { return ptr .Int64Value (asg .DesiredCapacity ) == int64 (dataplane .Spec .NodeCount ) }) {
92
+ func () bool { return ptr .Int64Value (asg .DesiredCapacity ) == int64 (dataplane .Spec .NodeCount ) },
93
+ func () bool {
94
+ return functional .StringsMatch (
95
+ parseOverridesFromASG (asg .MixedInstancesPolicy .LaunchTemplate .Overrides ),
96
+ parseOverridesFromASG (instanceTypes (dataplane .Spec .InstanceTypes )),
97
+ )
98
+ }) {
89
99
return nil
90
100
}
91
- _ , err := c .autoscaling .UpdateAutoScalingGroupWithContext (ctx , & autoscaling.UpdateAutoScalingGroupInput {
101
+ zap .S ().Infof ("[%v] updating ASG %v" , dataplane .Spec .ClusterName , * asg .AutoScalingGroupName )
102
+ _ , err = c .autoscaling .UpdateAutoScalingGroupWithContext (ctx , & autoscaling.UpdateAutoScalingGroupInput {
92
103
AutoScalingGroupName : ptr .String (AutoScalingGroupNameFor (dataplane .Spec .ClusterName )),
93
104
DesiredCapacity : ptr .Int64 (int64 (dataplane .Spec .NodeCount )),
94
105
VPCZoneIdentifier : ptr .String (strings .Join (subnets , "," )),
106
+ MixedInstancesPolicy : & autoscaling.MixedInstancesPolicy {
107
+ LaunchTemplate : & autoscaling.LaunchTemplate {
108
+ Overrides : instanceTypes (dataplane .Spec .InstanceTypes ),
109
+ },
110
+ },
95
111
})
96
112
return err
97
113
}
98
114
99
- func (c * Controller ) createAutoScalingGroup (ctx context.Context , dataplane * v1alpha1.DataPlane , subnets []string ) error {
100
- _ , err := c .autoscaling .CreateAutoScalingGroupWithContext (ctx , & autoscaling.CreateAutoScalingGroupInput {
115
+ func (c * Controller ) createAutoScalingGroup (ctx context.Context , dataplane * v1alpha1.DataPlane ) error {
116
+ subnets , err := c .subnetsFor (ctx , dataplane )
117
+ if err != nil {
118
+ return fmt .Errorf ("getting private subnet for %s, %w" , dataplane .Spec .ClusterName , err )
119
+ }
120
+ if len (subnets ) == 0 {
121
+ return fmt .Errorf ("failed to find private subnets for dataplane" )
122
+ }
123
+ _ , err = c .autoscaling .CreateAutoScalingGroupWithContext (ctx , & autoscaling.CreateAutoScalingGroupInput {
101
124
AutoScalingGroupName : ptr .String (AutoScalingGroupNameFor (dataplane .Spec .ClusterName )),
102
125
DesiredCapacity : ptr .Int64 (int64 (dataplane .Spec .NodeCount )),
103
126
MaxSize : ptr .Int64 (int64 (1000 )),
104
127
MinSize : ptr .Int64 (int64 (0 )),
105
- LaunchTemplate : & autoscaling.LaunchTemplateSpecification {
106
- LaunchTemplateName : ptr .String (launchtemplate .TemplateName (dataplane .Spec .ClusterName )),
128
+ MixedInstancesPolicy : & autoscaling.MixedInstancesPolicy {
129
+ InstancesDistribution : & autoscaling.InstancesDistribution {
130
+ OnDemandAllocationStrategy : ptr .String (dataplane .Spec .AllocationStrategy ),
131
+ },
132
+ LaunchTemplate : & autoscaling.LaunchTemplate {
133
+ LaunchTemplateSpecification : & autoscaling.LaunchTemplateSpecification {
134
+ LaunchTemplateName : ptr .String (launchtemplate .TemplateName (dataplane .Spec .ClusterName )),
135
+ },
136
+ Overrides : instanceTypes (dataplane .Spec .InstanceTypes ),
137
+ },
107
138
},
108
139
VPCZoneIdentifier : ptr .String (strings .Join (subnets , "," )),
109
140
Tags : generateAutoScalingTags (dataplane .Spec .ClusterName ),
@@ -127,14 +158,19 @@ func (c *Controller) getAutoScalingGroup(ctx context.Context, groupName string)
127
158
return output .AutoScalingGroups [0 ], nil
128
159
}
129
160
130
- func (c * Controller ) getPrivateSubnetsFor (ctx context.Context , clusterName string ) ([]string , error ) {
131
- instanceIDs , err := c .instances .ControlPlaneInstancesFor (ctx , clusterName )
161
+ func (c * Controller ) subnetsFor (ctx context.Context , dataplane * v1alpha1.DataPlane ) ([]string , error ) {
162
+ // Discover subnets provided as part of the subnetSelector in DP spec.
163
+ if len (dataplane .Spec .SubnetSelector ) != 0 {
164
+ return c .subnetsForSelector (ctx , dataplane .Spec .SubnetSelector )
165
+ }
166
+ // If subnetSelector is not provided fallback on control plane instance subnets
167
+ instanceIDs , err := c .instances .ControlPlaneInstancesFor (ctx , dataplane .Spec .ClusterName )
132
168
if err != nil {
133
169
return nil , err
134
170
}
135
- subnetIDs , err := c .getSubnetIDsFor (ctx , instanceIDs )
171
+ subnetIDs , err := c .subnetsForInstances (ctx , instanceIDs )
136
172
if err != nil {
137
- return nil , fmt .Errorf ("getting subnet for %s, %w" , clusterName , err )
173
+ return nil , fmt .Errorf ("getting subnet for %s, %w" , dataplane . Spec . ClusterName , err )
138
174
}
139
175
return c .filterPrivateSubnets (ctx , subnetIDs )
140
176
}
@@ -156,7 +192,34 @@ func (c *Controller) filterPrivateSubnets(ctx context.Context, ids []*string) ([
156
192
return result , nil
157
193
}
158
194
159
- func (c * Controller ) getSubnetIDsFor (ctx context.Context , instanceIDs []string ) ([]* string , error ) {
195
+ func (c * Controller ) subnetsForSelector (ctx context.Context , selector map [string ]string ) ([]string , error ) {
196
+ filters := []* ec2.Filter {}
197
+ // Filter by selector
198
+ for key , value := range selector {
199
+ if value == "*" {
200
+ filters = append (filters , & ec2.Filter {
201
+ Name : aws .String ("tag-key" ),
202
+ Values : []* string {aws .String (key )},
203
+ })
204
+ } else {
205
+ filters = append (filters , & ec2.Filter {
206
+ Name : aws .String (fmt .Sprintf ("tag:%s" , key )),
207
+ Values : []* string {aws .String (value )},
208
+ })
209
+ }
210
+ }
211
+ output , err := c .ec2api .DescribeSubnetsWithContext (ctx , & ec2.DescribeSubnetsInput {Filters : filters })
212
+ if err != nil {
213
+ return nil , fmt .Errorf ("describing subnets %+v, %w" , filters , err )
214
+ }
215
+ result := []string {}
216
+ for _ , o := range output .Subnets {
217
+ result = append (result , * o .SubnetId )
218
+ }
219
+ return result , nil
220
+ }
221
+
222
+ func (c * Controller ) subnetsForInstances (ctx context.Context , instanceIDs []string ) ([]* string , error ) {
160
223
requestIds := []* string {}
161
224
for _ , instanceID := range instanceIDs {
162
225
requestIds = append (requestIds , ptr .String (instanceID ))
@@ -191,7 +254,23 @@ func generateAutoScalingTags(clusterName string) []*autoscaling.Tag {
191
254
PropagateAtLaunch : aws .Bool (true ),
192
255
}, {
193
256
Key : aws .String ("Name" ),
194
- Value : aws .String ("auto-scaling-group" ),
257
+ Value : aws .String (fmt . Sprintf ( "%s-dataplane-nodes" , clusterName ) ),
195
258
PropagateAtLaunch : aws .Bool (true ),
196
259
}}
197
260
}
261
+
262
+ func instanceTypes (overrides []string ) []* autoscaling.LaunchTemplateOverrides {
263
+ result := []* autoscaling.LaunchTemplateOverrides {}
264
+ for _ , override := range overrides {
265
+ result = append (result , & autoscaling.LaunchTemplateOverrides {InstanceType : ptr .String (override )})
266
+ }
267
+ return result
268
+ }
269
+
270
+ func parseOverridesFromASG (overrides []* autoscaling.LaunchTemplateOverrides ) []string {
271
+ result := []string {}
272
+ for _ , override := range overrides {
273
+ result = append (result , ptr .StringValue (override .InstanceType ))
274
+ }
275
+ return result
276
+ }
0 commit comments