diff --git a/hypershift-operator/controllers/nodepool/nodepool_controller.go b/hypershift-operator/controllers/nodepool/nodepool_controller.go index 73c5bf2b4fe9..fb0ba5e6dda4 100644 --- a/hypershift-operator/controllers/nodepool/nodepool_controller.go +++ b/hypershift-operator/controllers/nodepool/nodepool_controller.go @@ -726,6 +726,9 @@ func isAutoscalingEnabled(nodePool *hyperv1.NodePool) bool { } func defaultNodePoolAMI(region string, specifiedArch string, releaseImage *releaseinfo.ReleaseImage) (string, error) { + if releaseImage.StreamMetadata == nil { + return "", fmt.Errorf("release image stream metadata is nil") + } arch, foundArch := releaseImage.StreamMetadata.Architectures[hyperv1.ArchAliases[specifiedArch]] if !foundArch { return "", fmt.Errorf("couldn't find OS metadata for architecture %q", specifiedArch) diff --git a/hypershift-operator/controllers/nodepool/nodepool_controller_test.go b/hypershift-operator/controllers/nodepool/nodepool_controller_test.go index 4ef9d7d6e47d..6da1240148ab 100644 --- a/hypershift-operator/controllers/nodepool/nodepool_controller_test.go +++ b/hypershift-operator/controllers/nodepool/nodepool_controller_test.go @@ -576,6 +576,15 @@ func TestDefaultNodePoolAMI(t *testing.T) { specifiedArch: "arm64", expectedImage: "", }, + { + name: "fail because stream metadata is nil", + region: "us-east-1", + specifiedArch: "amd64", + releaseImage: &releaseinfo.ReleaseImage{ + StreamMetadata: nil, + }, + expectedImage: "", + }, } for _, tc := range testCases { @@ -605,7 +614,9 @@ func TestDefaultNodePoolAMI(t *testing.T) { } ctx := t.Context() - tc.releaseImage = fakereleaseprovider.GetReleaseImage(ctx, hc, client, releaseProvider) + if tc.releaseImage == nil { + tc.releaseImage = fakereleaseprovider.GetReleaseImage(ctx, hc, client, releaseProvider) + } tc.image, tc.err = defaultNodePoolAMI(tc.region, tc.specifiedArch, tc.releaseImage) if strings.Contains(tc.name, "successfully") { @@ -617,6 +628,9 @@ func TestDefaultNodePoolAMI(t *testing.T) { } else if strings.Contains(tc.name, "fail because architecture") { g.Expect(tc.image).To(BeEmpty()) g.Expect(tc.err.Error()).To(Equal("couldn't find OS metadata for architecture \"" + tc.specifiedArch + "\"")) + } else if strings.Contains(tc.name, "stream metadata is nil") { + g.Expect(tc.image).To(BeEmpty()) + g.Expect(tc.err.Error()).To(Equal("release image stream metadata is nil")) } else { g.Expect(tc.image).To(BeEmpty()) g.Expect(tc.err.Error()).To(Equal("release image metadata has no image for region \"" + tc.region + "\"")) diff --git a/hypershift-operator/controllers/nodepool/token.go b/hypershift-operator/controllers/nodepool/token.go index b7cddf4acff5..bee4207a19f3 100644 --- a/hypershift-operator/controllers/nodepool/token.go +++ b/hypershift-operator/controllers/nodepool/token.go @@ -67,7 +67,6 @@ type userData struct { caCert []byte ignitionServerEndpoint string proxy *configv1.Proxy - ami string } // NewToken is the contract to create a new Token struct. @@ -134,19 +133,10 @@ func NewToken(ctx context.Context, configGenerator *ConfigGenerator, cpoCapabili proxy := globalconfig.ProxyConfig() globalconfig.ReconcileProxyConfigWithStatusFromHostedCluster(proxy, configGenerator.hostedCluster) - ami := "" - if configGenerator.hostedCluster.Spec.Platform.AWS != nil { - ami, err = defaultNodePoolAMI(configGenerator.hostedCluster.Spec.Platform.AWS.Region, configGenerator.nodePool.Spec.Arch, configGenerator.releaseImage) - if err != nil { - return nil, err - } - } - token.userData = &userData{ ignitionServerEndpoint: ignEndpoint, caCert: caCert, proxy: proxy, - ami: ami, } return token, nil @@ -377,7 +367,11 @@ func (t *Token) reconcileUserDataSecret(userDataSecret *corev1.Secret, token str if karpenterutil.IsKarpenterEnabled(t.hostedCluster.Spec.AutoNode) { npLabels := t.nodePool.GetLabels() if npLabels != nil && npLabels[karpenterutil.ManagedByKarpenterLabel] == "true" { - userDataSecret.Labels[hyperkarpenterv1.UserDataAMILabel] = t.userData.ami + ami, err := defaultNodePoolAMI(t.hostedCluster.Spec.Platform.AWS.Region, t.nodePool.Spec.Arch, t.releaseImage) + if err != nil { + return fmt.Errorf("failed to get default node pool AMI: %w", err) + } + userDataSecret.Labels[hyperkarpenterv1.UserDataAMILabel] = ami userDataSecret.Labels[karpenterutil.ManagedByKarpenterLabel] = "true" } }