@@ -26,11 +26,13 @@ import (
26
26
"github.com/aws/aws-sdk-go/aws/awserr"
27
27
"github.com/aws/aws-sdk-go/aws/request"
28
28
"github.com/aws/aws-sdk-go/service/eks"
29
+ "github.com/blang/semver"
29
30
"github.com/go-logr/logr"
30
31
"github.com/pkg/errors"
31
32
"k8s.io/apimachinery/pkg/util/sets"
32
33
"k8s.io/apimachinery/pkg/util/version"
33
34
"k8s.io/klog/v2"
35
+ "k8s.io/utils/ptr"
34
36
35
37
infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
36
38
ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/eks/api/v1beta2"
@@ -140,7 +142,54 @@ func (s *Service) reconcileCluster(ctx context.Context) error {
140
142
return nil
141
143
}
142
144
145
+ // computeCurrentStatusVersion returns the computed current EKS cluster kubernetes version.
146
+ // The computation has awareness of the fact that EKS clusters only return a major.minor kubernetes version,
147
+ // and returns a compatible version for te status according to the one the user specified in the spec.
148
+ func computeCurrentStatusVersion (specV * string , clusterV * string ) * string {
149
+ specVersion := ""
150
+ if specV != nil {
151
+ specVersion = * specV
152
+ }
153
+
154
+ clusterVersion := ""
155
+ if clusterV != nil {
156
+ clusterVersion = * clusterV
157
+ }
158
+
159
+ // Ignore parsing errors as these are already validated by the kubebuilder validation and the AWS API.
160
+ // Also specVersion might not be specified in the spec.Version for AWSManagedControlPlane, this results in a "0.0.0" version.
161
+ // Also clusterVersion might not yet be returned by the AWS EKS API, as the cluster might still be initializing, this results in a "0.0.0" version.
162
+ specSemverVersion , _ := semver .ParseTolerant (specVersion )
163
+ currentSemverVersion , _ := semver .ParseTolerant (clusterVersion )
164
+
165
+ // If AWS EKS API is not returning a version, set the status.Version to empty string.
166
+ if currentSemverVersion .String () == "0.0.0" {
167
+ return ptr .To ("" )
168
+ }
169
+
170
+ if currentSemverVersion .Major == specSemverVersion .Major &&
171
+ currentSemverVersion .Minor == specSemverVersion .Minor &&
172
+ specSemverVersion .Patch != 0 {
173
+ // Treat this case differently as we want it to exactly match the spec.Version,
174
+ // including its Patch, in the status.Version.
175
+ currentSemverVersion .Patch = specSemverVersion .Patch
176
+
177
+ return ptr .To (currentSemverVersion .String ())
178
+ }
179
+
180
+ // For all the other cases it doesn't matter to have a patch version, as EKS ignores it internally.
181
+ // So set the current cluster.Version (this always is a major.minor version format (e.g. "1.31")) in the status.Version.
182
+ // Even in the event where in the spec.Version a zero patch version is specified (e.g. "1.31.0"),
183
+ // the call to semver.ParseTolerant on the consumer side
184
+ // will make sure the version with and without the trailing zero actually result in a match.
185
+ return clusterV
186
+ }
187
+
143
188
func (s * Service ) setStatus (cluster * eks.Cluster ) error {
189
+ // Set the current Kubernetes control plane version in the status.
190
+ s .scope .ControlPlane .Status .Version = computeCurrentStatusVersion (s .scope .ControlPlane .Spec .Version , cluster .Version )
191
+
192
+ // Set the current cluster status in the control plane status.
144
193
switch * cluster .Status {
145
194
case eks .ClusterStatusDeleting :
146
195
s .scope .ControlPlane .Status .Ready = false
@@ -168,6 +217,8 @@ func (s *Service) setStatus(cluster *eks.Cluster) error {
168
217
default :
169
218
return errors .Errorf ("unexpected EKS cluster status %s" , * cluster .Status )
170
219
}
220
+
221
+ // Persists the control plane configuration and status.
171
222
if err := s .scope .PatchObject (); err != nil {
172
223
return errors .Wrap (err , "failed to update control plane" )
173
224
}
0 commit comments