Skip to content

Commit

Permalink
Create management cluster using controller bootstrap task
Browse files Browse the repository at this point in the history
  • Loading branch information
mitalipaygude committed Jan 23, 2024
1 parent 2c646d0 commit b7d3bfc
Show file tree
Hide file tree
Showing 14 changed files with 587 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ mocks: ## Generate mocks
${MOCKGEN} -destination=pkg/bootstrapper/mocks/bootstrapper.go -package=mocks "github.com/aws/eks-anywhere/pkg/bootstrapper" ClusterClient
${MOCKGEN} -destination=pkg/git/providers/github/mocks/github.go -package=mocks "github.com/aws/eks-anywhere/pkg/git/providers/github" GithubClient
${MOCKGEN} -destination=pkg/git/mocks/git.go -package=mocks "github.com/aws/eks-anywhere/pkg/git" Client,ProviderClient
${MOCKGEN} -destination=pkg/workflows/interfaces/mocks/clients.go -package=mocks "github.com/aws/eks-anywhere/pkg/workflows/interfaces" Bootstrapper,ClusterManager,GitOpsManager,Validator,CAPIManager,EksdInstaller,EksdUpgrader,PackageInstaller,ClusterUpgrader,ClusterCreator,ClientFactory
${MOCKGEN} -destination=pkg/workflows/interfaces/mocks/clients.go -package=mocks "github.com/aws/eks-anywhere/pkg/workflows/interfaces" Bootstrapper,ClusterManager,GitOpsManager,Validator,CAPIManager,EksdInstaller,EksdUpgrader,PackageInstaller,ClusterUpgrader,ClusterCreator,ClientFactory,EksaInstaller
${MOCKGEN} -destination=pkg/git/gogithub/mocks/client.go -package=mocks "github.com/aws/eks-anywhere/pkg/git/gogithub" Client
${MOCKGEN} -destination=pkg/git/gitclient/mocks/client.go -package=mocks "github.com/aws/eks-anywhere/pkg/git/gitclient" GoGit
${MOCKGEN} -destination=pkg/validations/mocks/docker.go -package=mocks "github.com/aws/eks-anywhere/pkg/validations" DockerExecutable
Expand Down
1 change: 1 addition & 0 deletions pkg/clustermanager/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type KubernetesClient interface {
WaitForDeployment(ctx context.Context, cluster *types.Cluster, timeout string, condition string, target string, namespace string) error
UpdateAnnotationInNamespace(ctx context.Context, resourceType, objectName string, annotations map[string]string, cluster *types.Cluster, namespace string) error
RemoveAnnotationInNamespace(ctx context.Context, resourceType, objectName, key string, cluster *types.Cluster, namespace string) error
CreateNamespaceIfNotPresent(ctx context.Context, kubeconfig string, namespace string) error
}

type clusterManagerClient struct {
Expand Down
83 changes: 67 additions & 16 deletions pkg/clustermanager/eksa_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/yaml"

anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
"github.com/aws/eks-anywhere/pkg/cluster"
Expand Down Expand Up @@ -58,26 +59,19 @@ func WithEKSAInstallerNoTimeouts() EKSAInstallerOpt {

// Install configures and applies eks-a components in a cluster accordingly to a spec.
func (i *EKSAInstaller) Install(ctx context.Context, log logr.Logger, cluster *types.Cluster, spec *cluster.Spec) error {
generator := EKSAComponentGenerator{log: log, reader: i.reader}
components, err := generator.buildEKSAComponentsSpec(spec)
err := i.createEKSAComponents(ctx, log, cluster, spec)
if err != nil {
return err
return fmt.Errorf("applying EKSA components: %v", err)
}

objs := make([]runtime.Object, 0, len(components.rest)+1)
objs = append(objs, components.deployment)
for _, o := range components.rest {
objs = append(objs, o)
}

for _, o := range objs {
if err = i.client.Apply(ctx, cluster.KubeconfigFile, o); err != nil {
return fmt.Errorf("applying eksa components: %v", err)
}
err = i.applyBundles(ctx, log, cluster, spec)
if err != nil {
return fmt.Errorf("applying EKSA bundles: %v", err)
}

if err := i.client.WaitForDeployment(ctx, cluster, i.deploymentWaitTimeout.String(), "Available", constants.EksaControllerManagerDeployment, constants.EksaSystemNamespace); err != nil {
return fmt.Errorf("waiting for eksa-controller-manager: %v", err)
err = i.applyReleases(ctx, log, cluster, spec)
if err != nil {
return fmt.Errorf("applying EKSA releases: %v", err)
}

return nil
Expand All @@ -101,13 +95,70 @@ func (i *EKSAInstaller) Upgrade(ctx context.Context, log logr.Logger, c *types.C
newVersionsBundle := newSpec.RootVersionsBundle()
oldVersion := oldVersionsBundle.Eksa.Version
newVersion := newVersionsBundle.Eksa.Version
if err := i.Install(ctx, log, c, newSpec); err != nil {
if err := i.createEKSAComponents(ctx, log, c, newSpec); err != nil {
return nil, fmt.Errorf("upgrading EKS-A components from version %v to version %v: %v", oldVersion, newVersion, err)
}

return changeDiff, nil
}

// createEKSAComponents creates eksa components and applies the objects to the cluster.
func (i *EKSAInstaller) createEKSAComponents(ctx context.Context, log logr.Logger, cluster *types.Cluster, spec *cluster.Spec) error {
generator := EKSAComponentGenerator{log: log, reader: i.reader}
components, err := generator.buildEKSAComponentsSpec(spec)
if err != nil {
return err
}

objs := make([]runtime.Object, 0, len(components.rest)+1)
objs = append(objs, components.deployment)
for _, o := range components.rest {
objs = append(objs, o)
}

for _, o := range objs {
if err = i.client.Apply(ctx, cluster.KubeconfigFile, o); err != nil {
return fmt.Errorf("applying eksa components: %v", err)
}
}

if err := i.client.WaitForDeployment(ctx, cluster, i.deploymentWaitTimeout.String(), "Available", constants.EksaControllerManagerDeployment, constants.EksaSystemNamespace); err != nil {
return fmt.Errorf("waiting for eksa-controller-manager: %v", err)
}

return nil
}

// applyBundles applies the bundles to the cluster.
func (i *EKSAInstaller) applyBundles(ctx context.Context, log logr.Logger, cluster *types.Cluster, spec *cluster.Spec) error {
bundleObj, err := yaml.Marshal(spec.Bundles)
if err != nil {
return fmt.Errorf("outputting bundle yaml: %v", err)
}

log.V(1).Info("Applying Bundles to cluster")
if err := i.client.ApplyKubeSpecFromBytes(ctx, cluster, bundleObj); err != nil {
return fmt.Errorf("applying bundle spec: %v", err)
}

return nil
}

// applyReleases applies the releases to the cluster.
func (i *EKSAInstaller) applyReleases(ctx context.Context, log logr.Logger, cluster *types.Cluster, spec *cluster.Spec) error {
releaseObj, err := yaml.Marshal(spec.EKSARelease)
if err != nil {
return fmt.Errorf("outputting release yaml: %v", err)
}

log.V(1).Info("Applying EKSA Release to cluster")
if err := i.client.ApplyKubeSpecFromBytes(ctx, cluster, releaseObj); err != nil {
return fmt.Errorf("applying release spec: %v", err)
}

return nil
}

// EKSAComponentGenerator generates and configures eks-a components.
type EKSAComponentGenerator struct {
log logr.Logger
Expand Down
14 changes: 14 additions & 0 deletions pkg/clustermanager/mocks/client_and_networking.go

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

34 changes: 34 additions & 0 deletions pkg/dependencies/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type Dependencies struct {
CiliumTemplater *cilium.Templater
AwsIamAuth *awsiamauth.Installer
ClusterManager *clustermanager.ClusterManager
EksaInstaller *clustermanager.EKSAInstaller
Bootstrapper *bootstrapper.Bootstrapper
GitOpsFlux *flux.Flux
Git *gitfactory.GitTools
Expand Down Expand Up @@ -1103,6 +1104,39 @@ func (f *Factory) WithClusterManager(clusterConfig *v1alpha1.Cluster, timeoutOpt
return f
}

// WithEKSAInstaller builds a cluster manager based on the cluster config and timeout options.
func (f *Factory) WithEKSAInstaller(clusterConfig *v1alpha1.Cluster, timeoutOpts *ClusterManagerTimeoutOptions) *Factory {
f.WithClusterctl().WithKubectl().WithFileReader()

f.buildSteps = append(f.buildSteps, func(ctx context.Context) error {
if f.dependencies.EksaInstaller != nil {
return nil
}

var r *retrier.Retrier
if f.config.noTimeouts {
r = retrier.NewWithNoTimeout()
} else {
r = clustermanager.DefaultRetrier()
}

client := clustermanager.NewRetrierClient(
&clusterManagerClient{
f.dependencies.Clusterctl,
f.dependencies.Kubectl,
},
r,
)

installer := clustermanager.NewEKSAInstaller(client, f.dependencies.FileReader, f.eksaInstallerOpts()...)

f.dependencies.EksaInstaller = installer
return nil
})

return f
}

// WithNoTimeouts injects no timeouts to all the dependencies with configurable timeout.
// Calling this method sets no timeout for the waits and retries in all the
// cluster operations, i.e. cluster manager, eksa installer, networking installer.
Expand Down
1 change: 1 addition & 0 deletions pkg/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type CommandContext struct {
EksdInstaller interfaces.EksdInstaller
PackageInstaller interfaces.PackageInstaller
EksdUpgrader interfaces.EksdUpgrader
EksaInstaller interfaces.EksaInstaller
ClusterUpgrader interfaces.ClusterUpgrader
ClusterCreator interfaces.ClusterCreator
CAPIManager interfaces.CAPIManager
Expand Down
7 changes: 7 additions & 0 deletions pkg/workflows/interfaces/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package interfaces
import (
"context"

"github.com/go-logr/logr"

"github.com/aws/eks-anywhere/pkg/bootstrapper"
"github.com/aws/eks-anywhere/pkg/clients/kubernetes"
"github.com/aws/eks-anywhere/pkg/cluster"
Expand Down Expand Up @@ -99,3 +101,8 @@ type ClusterCreator interface {
Run(ctx context.Context, spec *cluster.Spec, managementCluster types.Cluster) error
CreateSync(ctx context.Context, spec *cluster.Spec, managementCluster *types.Cluster) (*types.Cluster, error)
}

// EksaInstaller exposes the EKSA installer methods.
type EksaInstaller interface {
Install(ctx context.Context, log logr.Logger, cluster *types.Cluster, spec *cluster.Spec) error
}
40 changes: 39 additions & 1 deletion pkg/workflows/interfaces/mocks/clients.go

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

5 changes: 4 additions & 1 deletion pkg/workflows/management/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ type Create struct {
eksdInstaller interfaces.EksdInstaller
packageInstaller interfaces.PackageInstaller
clusterCreator interfaces.ClusterCreator
eksaInstaller interfaces.EksaInstaller
}

// NewCreate builds a new create construct.
func NewCreate(bootstrapper interfaces.Bootstrapper, provider providers.Provider,
clusterManager interfaces.ClusterManager, gitOpsManager interfaces.GitOpsManager,
writer filewriter.FileWriter, eksdInstaller interfaces.EksdInstaller,
packageInstaller interfaces.PackageInstaller,
clusterCreator interfaces.ClusterCreator,
clusterCreator interfaces.ClusterCreator, eksaInstaller interfaces.EksaInstaller,
) *Create {
return &Create{
bootstrapper: bootstrapper,
Expand All @@ -38,6 +39,7 @@ func NewCreate(bootstrapper interfaces.Bootstrapper, provider providers.Provider
eksdInstaller: eksdInstaller,
packageInstaller: packageInstaller,
clusterCreator: clusterCreator,
eksaInstaller: eksaInstaller,
}
}

Expand All @@ -54,6 +56,7 @@ func (c *Create) Run(ctx context.Context, clusterSpec *cluster.Spec, validator i
EksdInstaller: c.eksdInstaller,
PackageInstaller: c.packageInstaller,
ClusterCreator: c.clusterCreator,
EksaInstaller: c.eksaInstaller,
}

return task.NewTaskRunner(&setupAndValidateCreate{}, c.writer).RunTask(ctx, commandContext)
Expand Down
41 changes: 41 additions & 0 deletions pkg/workflows/management/create_bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package management

import (
"context"

"github.com/aws/eks-anywhere/pkg/logger"
"github.com/aws/eks-anywhere/pkg/task"
)

type createBootStrapClusterTask struct{}

func (s *createBootStrapClusterTask) Run(ctx context.Context, commandContext *task.CommandContext) task.Task {
logger.Info("Creating new bootstrap cluster")

bootstrapOptions, err := commandContext.Provider.BootstrapClusterOpts(commandContext.ClusterSpec)
if err != nil {
commandContext.SetError(err)
return nil
}

bootstrapCluster, err := commandContext.Bootstrapper.CreateBootstrapCluster(ctx, commandContext.ClusterSpec, bootstrapOptions...)
if err != nil {
commandContext.SetError(err)
return nil
}
commandContext.BootstrapCluster = bootstrapCluster

return &installCAPIComponentsTask{}
}

func (s *createBootStrapClusterTask) Name() string {
return "bootstrap-cluster-init"
}

func (s *createBootStrapClusterTask) Restore(ctx context.Context, commandContext *task.CommandContext, completedTask *task.CompletedTask) (task.Task, error) {
return nil, nil
}

func (s *createBootStrapClusterTask) Checkpoint() *task.CompletedTask {
return nil
}
Loading

0 comments on commit b7d3bfc

Please sign in to comment.