Skip to content

Commit

Permalink
validate eksarelease exists
Browse files Browse the repository at this point in the history
  • Loading branch information
tatlat committed Dec 22, 2023
1 parent c1479be commit 7744f4f
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 5 deletions.
5 changes: 4 additions & 1 deletion pkg/cluster/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/aws/eks-anywhere/pkg/api/v1alpha1"
"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/manifests/bundles"
Expand Down Expand Up @@ -125,7 +126,9 @@ func (b FileSpecBuilder) Build(clusterConfigURL string) (*Spec, error) {
}

releaseVersion := v1alpha1.EksaVersion(release.Version)
config.Cluster.Spec.EksaVersion = &releaseVersion
if config.Cluster.IsSelfManaged() || (config.Cluster.IsManaged() && !features.OverrideEksaVersion().IsActive()) {
config.Cluster.Spec.EksaVersion = &releaseVersion
}
eksaRelease := buildEKSARelease(release, bundlesManifest)

return NewSpec(config, bundlesManifest, eksdReleases, eksaRelease)
Expand Down
18 changes: 18 additions & 0 deletions pkg/executables/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ var (
eksaPackageBundlesType = fmt.Sprintf("packagebundles.%s", packagesv1.GroupVersion.Group)
kubectlConnectionRefusedRegex = regexp.MustCompile("The connection to the server .* was refused")
kubectlConnectionTimeoutRegex = regexp.MustCompile("Unable to connect to the server.*timeout.*")
eksaReleaseType = fmt.Sprintf("eksareleases.%s", releasev1alpha1.GroupVersion.Group)
)

type Kubectl struct {
Expand Down Expand Up @@ -2535,3 +2536,20 @@ func (k *Kubectl) DeleteCRD(ctx context.Context, crd, kubeconfig string) error {

return nil
}

// GetEKSARelease returns an eksareleases CR on the cluster.
func (k *Kubectl) GetEKSARelease(ctx context.Context, releaseName string, kubeconfigFile string) (*releasev1alpha1.EKSARelease, error) {
params := []string{"get", eksaReleaseType, releaseName, "-o", "json", "--kubeconfig", kubeconfigFile, "--namespace", constants.EksaSystemNamespace}
stdOut, err := k.Execute(ctx, params...)
if err != nil {
return nil, fmt.Errorf("getting eksarelease %v", err)
}

Check warning on line 2546 in pkg/executables/kubectl.go

View check run for this annotation

Codecov / codecov/patch

pkg/executables/kubectl.go#L2541-L2546

Added lines #L2541 - L2546 were not covered by tests

response := &releasev1alpha1.EKSARelease{}
err = json.Unmarshal(stdOut.Bytes(), response)
if err != nil {
return nil, fmt.Errorf("parsing get eksarelease response: %v", err)
}

Check warning on line 2552 in pkg/executables/kubectl.go

View check run for this annotation

Codecov / codecov/patch

pkg/executables/kubectl.go#L2548-L2552

Added lines #L2548 - L2552 were not covered by tests

return response, nil

Check warning on line 2554 in pkg/executables/kubectl.go

View check run for this annotation

Codecov / codecov/patch

pkg/executables/kubectl.go#L2554

Added line #L2554 was not covered by tests
}
9 changes: 9 additions & 0 deletions pkg/features/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const (
UseNewWorkflowsEnvVar = "USE_NEW_WORKFLOWS"
UseControllerForCli = "USE_CONTROLLER_FOR_CLI"
K8s129SupportEnvVar = "K8S_1_29_SUPPORT"
OverrideEksaVersionEnvVar = "OVERRIDE_EKSA_VERSION"
)

func FeedGates(featureGates []string) {
Expand Down Expand Up @@ -63,3 +64,11 @@ func K8s129Support() Feature {
IsActive: globalFeatures.isActiveForEnvVar(K8s129SupportEnvVar),
}
}

// OverrideEksaVersion is the feature flag to allow users to use their own value for eksaVersion for workload clusters.
func OverrideEksaVersion() Feature {
return Feature{
Name: "Allow users to provide their own eksaVersion value for workload clusters",
IsActive: globalFeatures.isActiveForEnvVar(OverrideEksaVersionEnvVar),
}
}
8 changes: 8 additions & 0 deletions pkg/features/features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,11 @@ func TestWithK8s129FeatureFlag(t *testing.T) {
g.Expect(os.Setenv(K8s129SupportEnvVar, "true")).To(Succeed())
g.Expect(IsActive(K8s129Support())).To(BeTrue())
}

func TestOverrideEksaVersionTrue(t *testing.T) {
g := NewWithT(t)
setupContext(t)

t.Setenv(OverrideEksaVersionEnvVar, "true")
g.Expect(OverrideEksaVersion().IsActive()).To(BeTrue())
}
18 changes: 16 additions & 2 deletions pkg/validations/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ func ValidateEksaVersion(ctx context.Context, cliVersion string, workload *clust
return fmt.Errorf("parsing eksa cli version: %v", err)
}

if !parsedVersion.SamePatch(parsedCLIVersion) {
return fmt.Errorf("cluster's eksaVersion does not match EKS-A CLI's version")
if features.OverrideEksaVersion().IsActive() && workload.Cluster.IsManaged() && parsedVersion.GreaterThan(parsedCLIVersion) {
return fmt.Errorf("workload cluster's eksaVersion cannot be greater than EKS-Anywhere CLI's version")

Check warning on line 116 in pkg/validations/cluster.go

View check run for this annotation

Codecov / codecov/patch

pkg/validations/cluster.go#L116

Added line #L116 was not covered by tests
} else if !parsedVersion.SamePatch(parsedCLIVersion) {
return fmt.Errorf("cluster's eksaVersion does not match EKS-Anywhere CLI's version")

Check warning on line 118 in pkg/validations/cluster.go

View check run for this annotation

Codecov / codecov/patch

pkg/validations/cluster.go#L118

Added line #L118 was not covered by tests
}

return nil
Expand Down Expand Up @@ -215,3 +217,15 @@ func ValidateK8s129Support(clusterSpec *cluster.Spec) error {
}
return nil
}

// ValidateEksaReleaseExistOnManagement checks if there is a corresponding eksareleases CR for workload's eksaVersion on the mgmt cluster.
func ValidateEksaReleaseExistOnManagement(ctx context.Context, k KubectlClient, mgmtCluster *types.Cluster, workload *cluster.Spec) error {
v := workload.Cluster.Spec.EksaVersion
if v == nil {
return fmt.Errorf("cluster has nil EksaVersion")
}
if release, err := k.GetEKSARelease(ctx, string(*workload.Cluster.Spec.EksaVersion), mgmtCluster.KubeconfigFile); err != nil || release == nil {
return fmt.Errorf("management cluster does have components for eksaVersion installed")
}
return nil

Check warning on line 230 in pkg/validations/cluster.go

View check run for this annotation

Codecov / codecov/patch

pkg/validations/cluster.go#L222-L230

Added lines #L222 - L230 were not covered by tests
}
7 changes: 7 additions & 0 deletions pkg/validations/createvalidations/preflightvalidations.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ func (v *CreateValidations) PreflightValidations(ctx context.Context) []validati
Err: validations.ValidateManagementClusterEksaVersion(ctx, k, v.Opts.ManagementCluster, v.Opts.Spec),
}
},
func() *validations.ValidationResult {
return &validations.ValidationResult{
Name: "validate eksa release components exist on management cluster",
Remediation: fmt.Sprintf("check eksaVersion field for workload cluster %s matches release previously used to upgrade maangement cluster %s", v.Opts.WorkloadCluster.Name, v.Opts.ManagementCluster.Name),
Err: validations.ValidateEksaReleaseExistOnManagement(ctx, k, v.Opts.ManagementCluster, v.Opts.Spec),
}
},
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,13 @@ func TestPreFlightValidationsWorkloadCluster(t *testing.T) {
},
}

testRelease := test.EKSARelease()

tt.k.EXPECT().GetClusters(tt.ctx, tt.c.Opts.WorkloadCluster).Return(nil, nil)
tt.k.EXPECT().ValidateClustersCRD(tt.ctx, tt.c.Opts.WorkloadCluster).Return(nil)
tt.k.EXPECT().ValidateEKSAClustersCRD(tt.ctx, tt.c.Opts.WorkloadCluster).Return(nil)
tt.k.EXPECT().GetEksaCluster(tt.ctx, tt.c.Opts.ManagementCluster, mgmtClusterName).Return(mgmt, nil).MaxTimes(3)
tt.k.EXPECT().GetEKSARelease(tt.ctx, string(version), tt.c.Opts.ManagementCluster.KubeconfigFile).Return(testRelease, nil)

tt.Expect(validations.ProcessValidationResults(tt.c.PreflightValidations(tt.ctx))).To(Succeed())
}
1 change: 1 addition & 0 deletions pkg/validations/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type KubectlClient interface {
GetEksaGitOpsConfig(ctx context.Context, gitOpsConfigName string, kubeconfigFile string, namespace string) (*v1alpha1.GitOpsConfig, error)
GetEksaFluxConfig(ctx context.Context, fluxConfigName string, kubeconfigFile string, namespace string) (*v1alpha1.FluxConfig, error)
GetEksaOIDCConfig(ctx context.Context, oidcConfigName string, kubeconfigFile string, namespace string) (*v1alpha1.OIDCConfig, error)
GetEKSARelease(ctx context.Context, releaseName string, kubeconfigFile string) (*releasev1alpha1.EKSARelease, error)
GetEksaVSphereDatacenterConfig(ctx context.Context, vsphereDatacenterConfigName string, kubeconfigFile string, namespace string) (*v1alpha1.VSphereDatacenterConfig, error)
GetEksaTinkerbellDatacenterConfig(ctx context.Context, tinkerbellDatacenterConfigName string, kubeconfigFile string, namespace string) (*v1alpha1.TinkerbellDatacenterConfig, error)
GetEksaTinkerbellMachineConfig(ctx context.Context, tinkerbellMachineConfigName string, kubeconfigFile string, namespace string) (*v1alpha1.TinkerbellMachineConfig, error)
Expand Down
15 changes: 15 additions & 0 deletions pkg/validations/mocks/kubectl.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions pkg/validations/upgradevalidations/preflightvalidations.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ func (u *UpgradeValidations) PreflightValidations(ctx context.Context) []validat
},
func() *validations.ValidationResult {
return &validations.ValidationResult{
Name: "validate cluster's eksaVersion matches EKS-A Version",
Remediation: "ensure EksaVersion matches the EKS-A release or omit the value from the cluster config",
Name: "validate cluster's eksaVersion matches EKS-Anywhere Version",
Remediation: "ensure eksaVersion matches the EKS-Anywhere release or omit the value from the cluster config",
Err: validations.ValidateEksaVersion(ctx, u.Opts.CliVersion, u.Opts.Spec),
}
},
Expand All @@ -134,6 +134,13 @@ func (u *UpgradeValidations) PreflightValidations(ctx context.Context) []validat
Err: validations.ValidateManagementClusterEksaVersion(ctx, k, u.Opts.ManagementCluster, u.Opts.Spec),
}
},
func() *validations.ValidationResult {
return &validations.ValidationResult{
Name: "validate eksa release components exist on management cluster",
Remediation: fmt.Sprintf("check eksaVersion field for workload cluster %s matches release previously used to upgrade maangement cluster %s", u.Opts.WorkloadCluster.Name, u.Opts.ManagementCluster.Name),
Err: validations.ValidateEksaReleaseExistOnManagement(ctx, k, u.Opts.ManagementCluster, u.Opts.Spec),
}
},
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,7 @@ func TestPreflightValidationsVsphere(t *testing.T) {
k.EXPECT().GetEksaCluster(ctx, workloadCluster, clusterSpec.Cluster.Name).Return(existingClusterSpec.Cluster, nil).MaxTimes(4)
if opts.Spec.Cluster.IsManaged() {
k.EXPECT().GetEksaCluster(ctx, workloadCluster, workloadCluster.Name).Return(existingClusterSpec.Cluster, nil).MaxTimes(4)
k.EXPECT().GetEKSARelease(ctx, string(ver), workloadCluster.KubeconfigFile).Return(test.EKSARelease(), nil)
}
k.EXPECT().GetEksaGitOpsConfig(ctx, clusterSpec.Cluster.Spec.GitOpsRef.Name, gomock.Any(), gomock.Any()).Return(existingClusterSpec.GitOpsConfig, nil).MaxTimes(1)
k.EXPECT().GetEksaOIDCConfig(ctx, clusterSpec.Cluster.Spec.IdentityProviderRefs[1].Name, gomock.Any(), gomock.Any()).Return(existingClusterSpec.OIDCConfig, nil).MaxTimes(1)
Expand Down

0 comments on commit 7744f4f

Please sign in to comment.