Skip to content

Commit

Permalink
🌱 copy HV API Key to target cluster.
Browse files Browse the repository at this point in the history
  • Loading branch information
guettli committed May 23, 2023
1 parent 1a3fe58 commit d98c309
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
99 changes: 99 additions & 0 deletions controllers/hivelocitycluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package controllers
import (
"context"
"fmt"
"strconv"
"strings"
"time"

Expand All @@ -29,8 +30,10 @@ import (
hvclient "github.com/hivelocity/cluster-api-provider-hivelocity/pkg/services/hivelocity/client"
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/kubernetes"
"k8s.io/klog/v2"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util"
Expand Down Expand Up @@ -123,6 +126,7 @@ func (r *HivelocityClusterReconciler) Reconcile(ctx context.Context, req ctrl.Re

clusterScope, err := scope.NewClusterScope(ctx, scope.ClusterScopeParams{
Client: r.Client,
APIReader: r.APIReader,
Logger: log,
Cluster: cluster,
HivelocityCluster: hvCluster,
Expand Down Expand Up @@ -177,6 +181,10 @@ func (r *HivelocityClusterReconciler) reconcileNormal(ctx context.Context, clust
return reconcile.Result{}, fmt.Errorf("failed to reconcile target cluster manager: %w", err)
}

if err := reconcileTargetSecret(ctx, clusterScope); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to reconcile target secret: %w", err)
}

log.V(1).Info("Reconciling finished")
return reconcile.Result{}, nil
}
Expand Down Expand Up @@ -328,6 +336,97 @@ func hvAPIKeyErrorResult(
return res, err
}

func reconcileTargetSecret(ctx context.Context, clusterScope *scope.ClusterScope) error {

clientConfig, err := clusterScope.ClientConfig(ctx)
if err != nil {
clusterScope.V(1).Info("failed to get clientconfig with api endpoint")
return err
}

if err := scope.IsControlPlaneReady(ctx, clientConfig); err != nil {
clusterScope.V(1).Info("Workload Control plane not ready - reconcile target secret again")
return err
}

// Workload control plane ready, so we can check if the secret exists already

// getting client set
restConfig, err := clientConfig.ClientConfig()
if err != nil {
return fmt.Errorf("failed to get rest config: %w", err)
}

targetClientSet, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return fmt.Errorf("failed to get client set: %w", err)
}

secretName := clusterScope.HivelocityCluster.Spec.HivelocitySecret.Name
targetNS := metav1.NamespaceSystem
sourceNS := clusterScope.HivelocityCluster.Namespace

if _, err := targetClientSet.CoreV1().Secrets(targetNS).Get(
ctx,
secretName,
metav1.GetOptions{},
); err == nil {
// Secret exists. Nothing to do.
return nil
}

if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get secret: %w", err)
}

apiKeySecretName := types.NamespacedName{
Namespace: sourceNS,
Name: secretName,
}
secretManager := secretutil.NewSecretManager(clusterScope.Logger, clusterScope.Client, clusterScope.APIReader)
apiKeySecret, err := secretManager.AcquireSecret(ctx, apiKeySecretName, clusterScope.HivelocityCluster, false, clusterScope.HivelocityCluster.DeletionTimestamp.IsZero())
if err != nil {
return fmt.Errorf("failed to acquire secret: %w", err)
}

key := clusterScope.HivelocityCluster.Spec.HivelocitySecret.Key

apiKey, keyExists := apiKeySecret.Data[key]
if !keyExists {
return fmt.Errorf(
"error key %s does not exist in secret/%s: %w",
key,
apiKeySecretName,
err,
)
}

var immutable bool
data := make(map[string][]byte)
data[key] = apiKey

// Save api server information
data["apiserver-host"] = []byte(clusterScope.HivelocityCluster.Spec.ControlPlaneEndpoint.Host)
data["apiserver-port"] = []byte(strconv.Itoa(int(clusterScope.HivelocityCluster.Spec.ControlPlaneEndpoint.Port)))

newSecret := corev1.Secret{
Immutable: &immutable,
Data: data,
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: targetNS,
},
}

// create secret in cluster
if _, err := targetClientSet.CoreV1().Secrets(targetNS).Create(ctx, &newSecret, metav1.CreateOptions{}); err != nil {
return fmt.Errorf("failed to create secret: %w", err)
}

return nil
}

func (r *HivelocityClusterReconciler) reconcileTargetClusterManager(ctx context.Context, clusterScope *scope.ClusterScope) error {
/* question targetClusterManagersLock.Lock()
r.targetClusterManagersLock.Lock()
Expand Down
1 change: 1 addition & 0 deletions controllers/hivelocitymachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func (r *HivelocityMachineReconciler) Reconcile(ctx context.Context, req ctrl.Re
Cluster: cluster,
HivelocityCluster: hvCluster,
HVClient: hvClient,
APIReader: r.APIReader,
},
Machine: machine,
HivelocityMachine: hivelocityMachine,
Expand Down
5 changes: 4 additions & 1 deletion pkg/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
// ClusterScopeParams defines the input parameters used to create a new scope.
type ClusterScopeParams struct {
Client client.Client
APIReader client.Reader
Logger logr.Logger
HVClient hvclient.Client
Cluster *clusterv1.Cluster
Expand Down Expand Up @@ -64,6 +65,7 @@ func NewClusterScope(ctx context.Context, params ClusterScopeParams) (*ClusterSc
return &ClusterScope{
Logger: params.Logger,
Client: params.Client,
APIReader: params.APIReader,
Cluster: params.Cluster,
HivelocityCluster: params.HivelocityCluster,
HVClient: params.HVClient,
Expand All @@ -75,6 +77,7 @@ func NewClusterScope(ctx context.Context, params ClusterScopeParams) (*ClusterSc
type ClusterScope struct {
logr.Logger
Client client.Client
APIReader client.Reader
patchHelper *patch.Helper
HVClient hvclient.Client

Expand Down Expand Up @@ -183,7 +186,7 @@ func (s *ClusterScope) ListMachines(ctx context.Context) ([]*clusterv1.Machine,
return machineList, hivelocityMachineList, nil
}

// IsControlPlaneReady returns if a machine is a control-plane.
// IsControlPlaneReady returns nil if the control plane is ready.
func IsControlPlaneReady(ctx context.Context, c clientcmd.ClientConfig) error {
restConfig, err := c.ClientConfig()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion test/hvapi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ write_files:
path: /opt/test.txt
`
opts := hv.BareMetalDeviceUpdate{
Hostname: "my-host-name.example.com",
Hostname: "my-host-name.example.com",
OsName: "Ubuntu 20.x",
PublicSshKeyId: 918,
Script: script,
Expand Down

0 comments on commit d98c309

Please sign in to comment.