@@ -41,7 +41,7 @@ func (s *Service) ensureGateways(ctx context.Context, delete bool) ([]*vpcgw.Gat
4141 }
4242
4343 drle := & common.ResourceEnsurer [infrav1.PublicGatewaySpec , * vpcgw.Gateway ]{
44- ResourceReconciler : & desiredResourceListManager {s .Cluster },
44+ ResourceReconciler : & desiredResourceListManager {s .Cluster , make ( map [scw. Zone ][] string ) },
4545 }
4646 return drle .Do (ctx , desired )
4747}
@@ -106,6 +106,8 @@ func (s *Service) Delete(ctx context.Context) error {
106106
107107type desiredResourceListManager struct {
108108 * scope.Cluster
109+
110+ gatewayTypesCache map [scw.Zone ][]string
109111}
110112
111113func (d * desiredResourceListManager ) ListResources (ctx context.Context ) ([]* vpcgw.Gateway , error ) {
@@ -132,6 +134,18 @@ func (d *desiredResourceListManager) UpdateResource(
132134 resource * vpcgw.Gateway ,
133135 desired infrav1.PublicGatewaySpec ,
134136) (* vpcgw.Gateway , error ) {
137+ if desired .Type != nil && * desired .Type != resource .Type {
138+ canUpgradeType , err := d .canUpgradeType (ctx , resource .Zone , resource .Type , * desired .Type )
139+ if err != nil {
140+ return nil , err
141+ }
142+
143+ if canUpgradeType {
144+ logf .FromContext (ctx ).Info ("Upgrading Gateway" , "gatewayName" , resource .Name , "zone" , resource .Zone )
145+ return d .ScalewayClient .UpgradeGateway (ctx , resource .Zone , resource .ID , * desired .Type )
146+ }
147+ }
148+
135149 return resource , nil
136150}
137151
@@ -148,27 +162,35 @@ func (d *desiredResourceListManager) GetDesiredZone(desired infrav1.PublicGatewa
148162}
149163
150164func (d * desiredResourceListManager ) ShouldKeepResource (
165+ ctx context.Context ,
151166 resource * vpcgw.Gateway ,
152167 desired infrav1.PublicGatewaySpec ,
153- ) bool {
168+ ) ( bool , error ) {
154169 // Gateway has no IPv4, remove it and recreate it.
155170 if resource .IPv4 == nil {
156- return false
171+ return false , nil
157172 }
158173
159174 if desired .Type != nil && * desired .Type != resource .Type {
160- return false
175+ canUpgradeType , err := d .canUpgradeType (ctx , resource .Zone , resource .Type , * desired .Type )
176+ if err != nil {
177+ return false , err
178+ }
179+
180+ if ! canUpgradeType {
181+ return false , nil
182+ }
161183 }
162184
163185 if desired .IP == nil && ! slices .Contains (resource .Tags , capsManagedIPTag ) {
164- return false
186+ return false , nil
165187 }
166188
167189 if desired .IP != nil && resource .IPv4 .Address .String () != * desired .IP {
168- return false
190+ return false , nil
169191 }
170192
171- return true
193+ return true , nil
172194}
173195
174196func (d * desiredResourceListManager ) GetDesiredResourceName (i int ) string {
@@ -213,3 +235,25 @@ func (d *desiredResourceListManager) CreateResource(
213235
214236 return gateway , nil
215237}
238+
239+ func (d * desiredResourceListManager ) canUpgradeType (ctx context.Context , zone scw.Zone , current , desired string ) (bool , error ) {
240+ types , ok := d .gatewayTypesCache [zone ]
241+ if ! ok {
242+ var err error
243+ types , err = d .ScalewayClient .ListGatewayTypes (ctx , zone )
244+ if err != nil {
245+ return false , err
246+ }
247+
248+ d .gatewayTypesCache [zone ] = types
249+ }
250+
251+ return canUpgradeTypes (types , current , desired ), nil
252+ }
253+
254+ func canUpgradeTypes (types []string , current , desired string ) bool {
255+ desiredIndex := slices .Index (types , desired )
256+ currentIndex := slices .Index (types , current )
257+
258+ return currentIndex != - 1 && desiredIndex > currentIndex
259+ }
0 commit comments