Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 38 additions & 38 deletions bootstrap/eks/controllers/eksconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,20 @@ package controllers
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"os"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/eks"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/source"

eksbootstrapv1 "sigs.k8s.io/cluster-api-provider-aws/v2/bootstrap/eks/api/v1beta2"
"sigs.k8s.io/cluster-api-provider-aws/v2/bootstrap/eks/internal/userdata"
ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/eks/api/v1beta2"
Expand All @@ -53,8 +46,14 @@ import (
"sigs.k8s.io/cluster-api/feature"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/conditions"
kubeconfigutil "sigs.k8s.io/cluster-api/util/kubeconfig"
"sigs.k8s.io/cluster-api/util/patch"
"sigs.k8s.io/cluster-api/util/predicates"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/source"
)

const (
Expand Down Expand Up @@ -323,36 +322,19 @@ func (r *EKSConfigReconciler) joinWorker(ctx context.Context, cluster *clusterv1
log.Info("Using mock CA certificate for test environment")
nodeInput.CACert = "mock-ca-certificate-for-testing"
} else {
// Fetch CA cert from EKS API
sess, err := session.NewSession(&aws.Config{Region: aws.String(controlPlane.Spec.Region)})
if err != nil {
log.Error(err, "Failed to create AWS session for EKS API")
conditions.MarkFalse(config, eksbootstrapv1.DataSecretAvailableCondition,
eksbootstrapv1.DataSecretGenerationFailedReason,
clusterv1.ConditionSeverityWarning,
"Failed to create AWS session: %v", err)
return ctrl.Result{}, err
// Fetch CA cert from KubeConfig secret
// We already have the cluster object passed to this function
obj := client.ObjectKey{
Namespace: cluster.Namespace,
Name: cluster.Name,
}
eksClient := eks.New(sess)
describeInput := &eks.DescribeClusterInput{Name: aws.String(controlPlane.Spec.EKSClusterName)}
clusterOut, err := eksClient.DescribeCluster(describeInput)
ca, err := r.extractCAFromSecret(ctx, obj)
if err != nil {
log.Error(err, "Failed to describe EKS cluster for CA cert fetch")
conditions.MarkFalse(config, eksbootstrapv1.DataSecretAvailableCondition,
eksbootstrapv1.DataSecretGenerationFailedReason,
clusterv1.ConditionSeverityWarning,
"Failed to describe EKS cluster: %v", err)
log.Error(err, "Failed to extract CA from kubeconfig secret")
conditions.MarkFalse(config, eksbootstrapv1.DataSecretAvailableCondition, eksbootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, "Failed to extract CA from kubeconfig secret: %v", err)
return ctrl.Result{}, err
} else if clusterOut.Cluster != nil && clusterOut.Cluster.CertificateAuthority != nil && clusterOut.Cluster.CertificateAuthority.Data != nil {
nodeInput.CACert = *clusterOut.Cluster.CertificateAuthority.Data
} else {
log.Error(nil, "CA certificate not found in EKS cluster response")
conditions.MarkFalse(config, eksbootstrapv1.DataSecretAvailableCondition,
eksbootstrapv1.DataSecretGenerationFailedReason,
clusterv1.ConditionSeverityWarning,
"CA certificate not found in EKS cluster response")
return ctrl.Result{}, fmt.Errorf("CA certificate not found in EKS cluster response")
}
nodeInput.CACert = ca
}

// Get AMI ID from AWSManagedMachinePool's launch template if specified
Expand All @@ -377,9 +359,7 @@ func (r *EKSConfigReconciler) joinWorker(ctx context.Context, cluster *clusterv1
}
}

log.Info("Generating AL2023 userdata",
"cluster", controlPlane.Spec.EKSClusterName,
"endpoint", nodeInput.APIServerEndpoint)
log.Info("Generating AL2023 userdata", "cluster", controlPlane.Spec.EKSClusterName, "endpoint", nodeInput.APIServerEndpoint)
} else {
nodeInput.AMIFamilyType = userdata.AMIFamilyAL2
log.Info("Generating standard userdata for node type", "type", config.Spec.NodeType)
Expand Down Expand Up @@ -581,3 +561,23 @@ func (r *EKSConfigReconciler) updateBootstrapSecret(ctx context.Context, secret
}
return false, nil
}

func (r *EKSConfigReconciler) extractCAFromSecret(ctx context.Context, obj client.ObjectKey) (string, error) {
data, err := kubeconfigutil.FromSecret(ctx, r.Client, obj)
if err != nil {
return "", errors.Wrapf(err, "failed to get kubeconfig secret %s", obj.Name)
}
config, err := clientcmd.Load(data)
if err != nil {
return "", errors.Wrapf(err, "failed to parse kubeconfig data from secret %s", obj.Name)
}

// Iterate through all clusters in the kubeconfig and use the first one with CA data
for _, cluster := range config.Clusters {
if len(cluster.CertificateAuthorityData) > 0 {
return base64.StdEncoding.EncodeToString(cluster.CertificateAuthorityData), nil
}
}

return "", fmt.Errorf("no cluster with CA data found in kubeconfig")
}
Loading