Skip to content

Commit

Permalink
Add extended kubernetes version support validations for create and up…
Browse files Browse the repository at this point in the history
…grade CLI operations
  • Loading branch information
panktishah26 committed Feb 6, 2025
1 parent 30fa933 commit e8a5369
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 138 deletions.
1 change: 1 addition & 0 deletions cmd/eksctl-anywhere/cmd/createcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ func (cc *createClusterOptions) createCluster(cmd *cobra.Command, _ []string) er
CliConfig: cliConfig,
SkippedValidations: skippedValidations,
KubeClient: deps.UnAuthKubeClient.KubeconfigClient(mgmt.KubeconfigFile),
ManifestReader: deps.ManifestReader,

Check warning on line 226 in cmd/eksctl-anywhere/cmd/createcluster.go

View check run for this annotation

Codecov / codecov/patch

cmd/eksctl-anywhere/cmd/createcluster.go#L226

Added line #L226 was not covered by tests
}
createValidations := createvalidations.New(validationOpts)

Expand Down
1 change: 1 addition & 0 deletions cmd/eksctl-anywhere/cmd/upgradecluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ func (uc *upgradeClusterOptions) upgradeCluster(cmd *cobra.Command, args []strin
CliConfig: cliConfig,
SkippedValidations: skippedValidations,
KubeClient: deps.UnAuthKubeClient.KubeconfigClient(managementCluster.KubeconfigFile),
ManifestReader: deps.ManifestReader,

Check warning on line 202 in cmd/eksctl-anywhere/cmd/upgradecluster.go

View check run for this annotation

Codecov / codecov/patch

cmd/eksctl-anywhere/cmd/upgradecluster.go#L202

Added line #L202 was not covered by tests
}

upgradeValidations := upgradevalidations.New(validationOpts)
Expand Down
3 changes: 2 additions & 1 deletion cmd/eksctl-anywhere/cmd/validatecreatecluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (valOpt *validateOptions) validateCreateCluster(cmd *cobra.Command, _ []str
WithGitOpsFlux(clusterSpec.Cluster, clusterSpec.FluxConfig, cliConfig).
WithUnAuthKubeClient().
WithValidatorClients().
WithManifestReader().

Check warning on line 91 in cmd/eksctl-anywhere/cmd/validatecreatecluster.go

View check run for this annotation

Codecov / codecov/patch

cmd/eksctl-anywhere/cmd/validatecreatecluster.go#L91

Added line #L91 was not covered by tests
Build(ctx)
if err != nil {
cleanupDirectory(tmpPath)
Expand All @@ -105,8 +106,8 @@ func (valOpt *validateOptions) validateCreateCluster(cmd *cobra.Command, _ []str
ManagementCluster: getManagementCluster(clusterSpec),
Provider: deps.Provider,
CliConfig: cliConfig,
ManifestReader: deps.ManifestReader,

Check warning on line 109 in cmd/eksctl-anywhere/cmd/validatecreatecluster.go

View check run for this annotation

Codecov / codecov/patch

cmd/eksctl-anywhere/cmd/validatecreatecluster.go#L109

Added line #L109 was not covered by tests
}

createValidations := createvalidations.New(validationOpts)

commandVal := createcluster.NewValidations(clusterSpec, deps.Provider, deps.GitOpsFlux, createValidations, deps.DockerClient)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ spec:
description: HookImagesURLPath can be used to override the default
Hook images path to pull from a local server.
type: string
hookIsoURL:
description: HookIsoURL is the URL of ISO image that will be used
to provision the hardware during one time boot process. It can be
used to override the default Hook OS ISO image to pull from a local
server.
type: string
isoBoot:
description: IsoBoot can be used to indicate that the hardware must
description: IsoBoot can be used to indicate that the hardware should
boot using an ISO.
type: boolean
hookIsoURL:
description: HookIsoURL is the URL of ISO image that will one time boot.
It can be used to override the default Hook OS ISO image to pull
from a local server.
type: string
loadBalancerInterface:
description: LoadBalancerInterface can be used to configure a load
balancer interface for the Tinkerbell stack.
Expand Down Expand Up @@ -92,4 +93,4 @@ status:
kind: ""
plural: ""
conditions: []
storedVersions: []
storedVersions: []
9 changes: 4 additions & 5 deletions config/prod/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../default

- ../default
images:
- name: controller
newName: public.ecr.aws/l0g8r8j6/eks-anywhere-cluster-controller
newTag: v0.0.0-eks-a-v0.0.0-dev-build.251
- name: controller
newName: public.ecr.aws/y8b4r0e8/eks-anywhere-cluster-controller
newTag: v0.21.5-c4a0a4c8e4f5cd43545cd9cb06a684dbc9f8603d
2 changes: 1 addition & 1 deletion pkg/providers/tinkerbell/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ func (p *Provider) ValidateNewSpec(ctx context.Context, cluster *types.Cluster,
// for any operation other than k8s version change, hookImageURL is immutable
if currentClstr.Spec.KubernetesVersion == desiredClstrSpec.Cluster.Spec.KubernetesVersion {
if desiredDCCfgSpec.HookImagesURLPath != currentDCCfg.Spec.HookImagesURLPath {
return fmt.Errorf("spec.hookImagesURLPath is immutable. previoius = %s, new = %s",
return fmt.Errorf("spec.hookImagesURLPath is immutable. previous = %s, new = %s",

Check warning on line 344 in pkg/providers/tinkerbell/upgrade.go

View check run for this annotation

Codecov / codecov/patch

pkg/providers/tinkerbell/upgrade.go#L344

Added line #L344 was not covered by tests
currentDCCfg.Spec.HookImagesURLPath, desiredDCCfgSpec.HookImagesURLPath)
}
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/validations/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/aws/eks-anywhere/pkg/constants"
"github.com/aws/eks-anywhere/pkg/features"
"github.com/aws/eks-anywhere/pkg/logger"
"github.com/aws/eks-anywhere/pkg/manifests"
"github.com/aws/eks-anywhere/pkg/providers"
"github.com/aws/eks-anywhere/pkg/providers/common"
"github.com/aws/eks-anywhere/pkg/semver"
Expand Down Expand Up @@ -297,3 +298,17 @@ func ValidateK8s132Support(clusterSpec *cluster.Spec) error {
}
return nil
}

// ValidateExtendedKubernetesSupport validates the extended kubernetes version support for create and upgrade operations.
func ValidateExtendedKubernetesSupport(ctx context.Context, clusterSpec v1alpha1.Cluster, reader *manifests.Reader, k kubernetes.Client) error {
eksaVersion := clusterSpec.Spec.EksaVersion
if eksaVersion == nil {
return nil
}

bundles, err := reader.ReadBundlesForVersion(string(*eksaVersion))
if err != nil {
return fmt.Errorf("getting bundle for existing cluster : %w", err)
}
return ValidateExtendedK8sVersionSupport(ctx, clusterSpec, bundles, k)
}
97 changes: 97 additions & 0 deletions pkg/validations/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/aws/eks-anywhere/internal/test"
internalmocks "github.com/aws/eks-anywhere/internal/test/mocks"
"github.com/aws/eks-anywhere/pkg/api/v1alpha1"
anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
"github.com/aws/eks-anywhere/pkg/cluster"
"github.com/aws/eks-anywhere/pkg/features"
"github.com/aws/eks-anywhere/pkg/manifests"
"github.com/aws/eks-anywhere/pkg/manifests/releases"
"github.com/aws/eks-anywhere/pkg/providers"
providermocks "github.com/aws/eks-anywhere/pkg/providers/mocks"
"github.com/aws/eks-anywhere/pkg/types"
Expand Down Expand Up @@ -853,3 +857,96 @@ func TestValidateK8s132SupportActive(t *testing.T) {
os.Setenv(features.K8s132SupportEnvVar, "true")
tt.Expect(validations.ValidateK8s132Support(tt.clusterSpec)).To(Succeed())
}

func TestValidateExtendedKubernetesVersionSupportCLINoError(t *testing.T) {
ctx := context.Background()

cluster := &v1alpha1.Cluster{
Spec: v1alpha1.ClusterSpec{
EksaVersion: nil,
},
}
objs := []client.Object{}
objs = append(objs, cluster)
fakeClient := test.NewFakeKubeClient(objs...)

ctrl := gomock.NewController(t)
reader := internalmocks.NewMockReader(ctrl)

err := validations.ValidateExtendedKubernetesSupport(ctx, *cluster, manifests.NewReader(reader), fakeClient)
if err != nil {
t.Errorf("got = %v, \nwant nil", err)
}
}

func TestValidateExtendedKubernetesVersionSupportCLIError(t *testing.T) {
ctx := context.Background()
version := test.DevEksaVersion()
cluster := &v1alpha1.Cluster{
Spec: v1alpha1.ClusterSpec{
EksaVersion: &version,
},
}

objs := []client.Object{}
objs = append(objs, cluster)
fakeClient := test.NewFakeKubeClient(objs...)

ctrl := gomock.NewController(t)
reader := internalmocks.NewMockReader(ctrl)
releasesURL := releases.ManifestURL()
reader.EXPECT().ReadFile(releasesURL)

err := validations.ValidateExtendedKubernetesSupport(ctx, *cluster, manifests.NewReader(reader), fakeClient)
if err == nil {
t.Errorf("got = nil, \nwant error: getting bundle for existing cluster")
}
}

func TestValidateExtendedKubernetesVersionSupportCLICheckExtendedSupport(t *testing.T) {
ctx := context.Background()
version := test.DevEksaVersion()
cluster := &v1alpha1.Cluster{
Spec: v1alpha1.ClusterSpec{
EksaVersion: &version,
KubernetesVersion: anywherev1.Kube130,
},
}

objs := []client.Object{}
objs = append(objs, cluster)
fakeClient := test.NewFakeKubeClient(objs...)

ctrl := gomock.NewController(t)
reader := internalmocks.NewMockReader(ctrl)
releasesURL := releases.ManifestURL()
releasesManifest := fmt.Sprintf(`apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Release
metadata:
name: release-1
spec:
releases:
- bundleManifestUrl: "https://bundles/bundles.yaml"
version: %s`, string(version))
reader.EXPECT().ReadFile(releasesURL).Return([]byte(releasesManifest), nil)

bundlesManifest := `apiVersion: anywhere.eks.amazonaws.com/v1alpha1
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Bundles
metadata:
annotations:
anywhere.eks.amazonaws.com/signature: MEYCIQDgmE8oY9xUyFO3uOHRkpRWjTxoej8Wf7Ty5HQcbs9ouQIhANV2kylPXjcpLY2xu7vD6ktXqm7yrnLUgiehSdbL8JUJ
name: bundles-1
spec:
number: 1
versionsBundles:
- kubeversion: "1.30"
endOfStandardSupport: "2026-12-31"`

reader.EXPECT().ReadFile("https://bundles/bundles.yaml").Return([]byte(bundlesManifest), nil)

err := validations.ValidateExtendedKubernetesSupport(ctx, *cluster, manifests.NewReader(reader), fakeClient)
if err != nil {
t.Errorf("got = %v, \nwant nil", err)
}
}
7 changes: 7 additions & 0 deletions pkg/validations/createvalidations/preflightvalidations.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ func (v *CreateValidations) PreflightValidations(ctx context.Context) []validati
Silent: true,
}
},
func() *validations.ValidationResult {
return &validations.ValidationResult{
Name: "validate extended kubernetes version support is supported",
Remediation: "ensure you have a valid license for extended Kubernetes version support",
Err: validations.ValidateExtendedKubernetesSupport(ctx, *v.Opts.Spec.Cluster, v.Opts.ManifestReader, v.Opts.KubeClient),
}
},
}

if len(v.Opts.Spec.VSphereMachineConfigs) != 0 {
Expand Down
60 changes: 55 additions & 5 deletions pkg/validations/createvalidations/preflightvalidations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package createvalidations_test

import (
"context"
"fmt"
"testing"

"github.com/golang/mock/gomock"
Expand All @@ -11,9 +12,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/aws/eks-anywhere/internal/test"
internalmocks "github.com/aws/eks-anywhere/internal/test/mocks"
anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
"github.com/aws/eks-anywhere/pkg/cluster"
"github.com/aws/eks-anywhere/pkg/constants"
"github.com/aws/eks-anywhere/pkg/manifests"
"github.com/aws/eks-anywhere/pkg/manifests/releases"
"github.com/aws/eks-anywhere/pkg/types"
"github.com/aws/eks-anywhere/pkg/validations"
"github.com/aws/eks-anywhere/pkg/validations/createvalidations"
Expand All @@ -30,22 +34,32 @@ type preflightValidationsTest struct {
func newPreflightValidationsTest(t *testing.T) *preflightValidationsTest {
ctrl := gomock.NewController(t)
k := mocks.NewMockKubectlClient(ctrl)

version := test.DevEksaVersion()

c := &types.Cluster{
KubeconfigFile: "kubeconfig",
}

clusterSpec := test.NewClusterSpec(func(s *cluster.Spec) {
s.Cluster.Spec.GitOpsRef = &anywherev1.Ref{
Name: "gitops",
s.Cluster = &anywherev1.Cluster{
Spec: anywherev1.ClusterSpec{
KubernetesVersion: "1.30",
GitOpsRef: &anywherev1.Ref{
Name: "gitops",
},
EksaVersion: &version,
},
}
})
version := "v0.19.0-dev+latest"

objects := []client.Object{test.EKSARelease()}
opts := &validations.Opts{
Kubectl: k,
Spec: clusterSpec,
WorkloadCluster: c,
ManagementCluster: c,
CliVersion: version,
CliVersion: string(version),
KubeClient: test.NewFakeKubeClient(objects...),
}
return &preflightValidationsTest{
Expand All @@ -56,8 +70,42 @@ func newPreflightValidationsTest(t *testing.T) *preflightValidationsTest {
}
}

func addManifestReaderMock(t *testing.T, version anywherev1.EksaVersion) *manifests.Reader {
ctrl := gomock.NewController(t)
reader := internalmocks.NewMockReader(ctrl)
releasesURL := releases.ManifestURL()

releasesManifest := fmt.Sprintf(`apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Release
metadata:
name: release-1
spec:
releases:
- bundleManifestUrl: "https://bundles/bundles.yaml"
version: %s`, string(version))
reader.EXPECT().ReadFile(releasesURL).Return([]byte(releasesManifest), nil)

bundlesManifest := `apiVersion: anywhere.eks.amazonaws.com/v1alpha1
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Bundles
metadata:
annotations:
anywhere.eks.amazonaws.com/signature: MEYCIQDgmE8oY9xUyFO3uOHRkpRWjTxoej8Wf7Ty5HQcbs9ouQIhANV2kylPXjcpLY2xu7vD6ktXqm7yrnLUgiehSdbL8JUJ
name: bundles-1
spec:
number: 1
versionsBundles:
- kubeversion: "1.30"
endOfStandardSupport: "2026-12-31"`

reader.EXPECT().ReadFile("https://bundles/bundles.yaml").Return([]byte(bundlesManifest), nil)

return manifests.NewReader(reader)
}

func TestPreFlightValidationsGitProvider(t *testing.T) {
tt := newPreflightValidationsTest(t)
tt.c.Opts.ManifestReader = addManifestReaderMock(t, anywherev1.EksaVersion(tt.c.Opts.CliVersion))
tt.Expect(validations.ProcessValidationResults(tt.c.PreflightValidations(tt.ctx))).To(Succeed())
}

Expand All @@ -67,13 +115,15 @@ func TestPreFlightValidationsWorkloadCluster(t *testing.T) {
tt.c.Opts.Spec.Cluster.SetManagedBy(mgmtClusterName)
tt.c.Opts.Spec.Cluster.Spec.ManagementCluster.Name = mgmtClusterName
tt.c.Opts.ManagementCluster.Name = mgmtClusterName
version := test.DevEksaVersion()
version := anywherev1.EksaVersion(tt.c.Opts.CliVersion)
tt.c.Opts.ManifestReader = addManifestReaderMock(t, version)

mgmt := &anywherev1.Cluster{
ObjectMeta: v1.ObjectMeta{
Name: "mgmt-cluster",
},
Spec: anywherev1.ClusterSpec{
KubernetesVersion: "1.30",
ManagementCluster: anywherev1.ManagementCluster{
Name: "mgmt-cluster",
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/validations/extendedversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func validateBundleSignature(bundle *v1alpha1.Bundles) error {
return err
}
if !valid {
return fmt.Errorf("signature on the bundle is invalid, error: %w", err)
return errors.New("signature on the bundle is invalid")

Check warning on line 53 in pkg/validations/extendedversion.go

View check run for this annotation

Codecov / codecov/patch

pkg/validations/extendedversion.go#L53

Added line #L53 was not covered by tests
}
return nil
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/validations/upgradevalidations/preflightvalidations.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ func (u *UpgradeValidations) PreflightValidations(ctx context.Context) []validat
Silent: true,
}
},
func() *validations.ValidationResult {
return &validations.ValidationResult{
Name: "validate extended kubernetes version support is supported",
Remediation: "ensure you have a valid license for extended Kubernetes version support",
Err: validations.ValidateExtendedKubernetesSupport(ctx, *u.Opts.Spec.Cluster, u.Opts.ManifestReader, u.Opts.KubeClient),
}
},
}

if len(u.Opts.Spec.VSphereMachineConfigs) != 0 {
Expand Down
Loading

0 comments on commit e8a5369

Please sign in to comment.