pkg/bootstrapper/client.go (115 lines of code) (raw):
package bootstrapper
import (
"context"
"time"
"github.com/aws/eks-anywhere/pkg/cluster"
"github.com/aws/eks-anywhere/pkg/retrier"
"github.com/aws/eks-anywhere/pkg/types"
)
// KindClient is a Kind client.
type KindClient interface {
CreateBootstrapCluster(ctx context.Context, clusterSpec *cluster.Spec, opts ...BootstrapClusterClientOption) (kubeconfig string, err error)
DeleteBootstrapCluster(ctx context.Context, cluster *types.Cluster) error
WithExtraDockerMounts() BootstrapClusterClientOption
WithExtraPortMappings([]int) BootstrapClusterClientOption
WithEnv(env map[string]string) BootstrapClusterClientOption
GetKubeconfig(ctx context.Context, clusterName string) (string, error)
ClusterExists(ctx context.Context, clusterName string) (bool, error)
}
// KubernetesClient is a Kubernetes client.
type KubernetesClient interface {
ApplyKubeSpecFromBytes(ctx context.Context, cluster *types.Cluster, data []byte) error
GetClusters(ctx context.Context, cluster *types.Cluster) ([]types.CAPICluster, error)
ValidateClustersCRD(ctx context.Context, cluster *types.Cluster) error
CreateNamespaceIfNotPresent(ctx context.Context, kubeconfig string, namespace string) error
}
// RetrierClientOpt allows to customize a RetrierClient
// on construction.
type RetrierClientOpt func(*RetrierClient)
// WithRetrierClientRetrier allows to use a custom retrier.
func WithRetrierClientRetrier(retrier retrier.Retrier) RetrierClientOpt {
return func(u *RetrierClient) {
u.retrier = retrier
}
}
// RetrierClient wraps kind and kubernetes APIs around a retrier.
type RetrierClient struct {
KindClient
k8s KubernetesClient
retrier retrier.Retrier
}
// NewRetrierClient constructs a new RetrierClient.
func NewRetrierClient(kind KindClient, k8s KubernetesClient, opts ...RetrierClientOpt) RetrierClient {
c := &RetrierClient{
k8s: k8s,
KindClient: kind,
retrier: *retrier.NewWithMaxRetries(10, 5*time.Second),
}
for _, opt := range opts {
opt(c)
}
return *c
}
// Apply creates/updates the data objects for a cluster.
func (c RetrierClient) Apply(ctx context.Context, cluster *types.Cluster, data []byte) error {
return c.retrier.Retry(
func() error {
return c.k8s.ApplyKubeSpecFromBytes(ctx, cluster, data)
},
)
}
// CreateNamespace creates a namespace if the namespace does not exist.
func (c RetrierClient) CreateNamespace(ctx context.Context, kubeconfig, namespace string) error {
return c.retrier.Retry(
func() error {
return c.k8s.CreateNamespaceIfNotPresent(ctx, kubeconfig, namespace)
},
)
}
// GetCAPIClusterCRD gets the capi cluster crd in a K8s cluster.
func (c RetrierClient) GetCAPIClusterCRD(ctx context.Context, cluster *types.Cluster) error {
return c.retrier.Retry(
func() error {
return c.k8s.ValidateClustersCRD(ctx, cluster)
},
)
}
// GetCAPIClusters gets all the capi clusters in a K8s cluster.
func (c RetrierClient) GetCAPIClusters(ctx context.Context, cluster *types.Cluster) ([]types.CAPICluster, error) {
clusters := []types.CAPICluster{}
err := c.retrier.Retry(
func() error {
var err error
clusters, err = c.k8s.GetClusters(ctx, cluster)
return err
},
)
if err != nil {
return nil, err
}
return clusters, nil
}
// KindClusterExists checks whether a kind cluster exists by a cluster name.
func (c RetrierClient) KindClusterExists(ctx context.Context, clusterName string) (bool, error) {
var exists bool
err := c.retrier.Retry(
func() error {
var err error
exists, err = c.KindClient.ClusterExists(ctx, clusterName)
return err
},
)
if err != nil {
return false, err
}
return exists, nil
}
// GetKindClusterKubeconfig gets the kubeconfig for a kind cluster by cluster name.
func (c RetrierClient) GetKindClusterKubeconfig(ctx context.Context, clusterName string) (string, error) {
var kubeconfig string
err := c.retrier.Retry(
func() error {
var err error
kubeconfig, err = c.KindClient.GetKubeconfig(ctx, clusterName)
return err
},
)
if err != nil {
return "", err
}
return kubeconfig, nil
}
// DeleteKindCluster deletes a kind cluster by cluster name.
func (c RetrierClient) DeleteKindCluster(ctx context.Context, cluster *types.Cluster) error {
return c.retrier.Retry(
func() error {
return c.KindClient.DeleteBootstrapCluster(ctx, cluster)
},
)
}