From 9eaf507a90c095bd1d7a1d65baae429a9e9e0ba9 Mon Sep 17 00:00:00 2001 From: janiskemper <63146658+janiskemper@users.noreply.github.com> Date: Wed, 8 May 2024 10:35:44 +0200 Subject: [PATCH] :sparkles: Add ssh key name via hetzner secret (#1289) Adding the ssh key name via hetzner secret facilitates use cases where a lot of clusters are created with the same ssh key. Instead of having to specify it every time in the HetznerClusterTemplate object, it can be specified in the secret ones. On top, this commit introduces default values for the HetznerSecret to allow use cases where all is hard-coded and doesn't have to be specified e.g. in a ClusterClass or in the templates of the cluster object anymore. --- api/v1beta1/types.go | 8 +++++++ ...ture.cluster.x-k8s.io_hetznerclusters.yaml | 8 +++++++ ...ster.x-k8s.io_hetznerclustertemplates.yaml | 8 +++++++ controllers/hetznercluster_controller.go | 24 +++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index b73b7d1af..7132740cc 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -102,6 +102,7 @@ type HCloudPlacementGroupStatus struct { // HetznerSecretRef defines all the names of the secret and the relevant keys needed to access Hetzner API. type HetznerSecretRef struct { // Name defines the name of the secret. + // +kubebuilder:default=hetzner Name string `json:"name"` // Key defines the keys that are used in the secret. // Need to specify either HCloudToken or both HetznerRobotUser and HetznerRobotPassword. @@ -113,13 +114,20 @@ type HetznerSecretRef struct { type HetznerSecretKeyRef struct { // HCloudToken defines the name of the key where the token for the Hetzner Cloud API is stored. // +optional + // +kubebuilder:default=hcloud-token HCloudToken string `json:"hcloudToken"` // HetznerRobotUser defines the name of the key where the username for the Hetzner Robot API is stored. // +optional + // +kubebuilder:default=hetzner-robot-user HetznerRobotUser string `json:"hetznerRobotUser"` // HetznerRobotPassword defines the name of the key where the password for the Hetzner Robot API is stored. // +optional + // +kubebuilder:default=hetzner-robot-password HetznerRobotPassword string `json:"hetznerRobotPassword"` + // SSHKey defines the name of the ssh key. + // +optional + // +kubebuilder:default=ssh-key + SSHKey string `json:"sshKey"` } // PublicNetworkSpec contains specs about the public network spec of an HCloud server. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclusters.yaml index a85fb7db9..6e1d00adc 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclusters.yaml @@ -242,19 +242,27 @@ spec: Need to specify either HCloudToken or both HetznerRobotUser and HetznerRobotPassword. properties: hcloudToken: + default: hcloud-token description: HCloudToken defines the name of the key where the token for the Hetzner Cloud API is stored. type: string hetznerRobotPassword: + default: hetzner-robot-password description: HetznerRobotPassword defines the name of the key where the password for the Hetzner Robot API is stored. type: string hetznerRobotUser: + default: hetzner-robot-user description: HetznerRobotUser defines the name of the key where the username for the Hetzner Robot API is stored. type: string + sshKey: + default: ssh-key + description: SSHKey defines the name of the ssh key. + type: string type: object name: + default: hetzner description: Name defines the name of the secret. type: string required: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclustertemplates.yaml index d0760a054..fa15cfcd6 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_hetznerclustertemplates.yaml @@ -273,21 +273,29 @@ spec: Need to specify either HCloudToken or both HetznerRobotUser and HetznerRobotPassword. properties: hcloudToken: + default: hcloud-token description: HCloudToken defines the name of the key where the token for the Hetzner Cloud API is stored. type: string hetznerRobotPassword: + default: hetzner-robot-password description: HetznerRobotPassword defines the name of the key where the password for the Hetzner Robot API is stored. type: string hetznerRobotUser: + default: hetzner-robot-user description: HetznerRobotUser defines the name of the key where the username for the Hetzner Robot API is stored. type: string + sshKey: + default: ssh-key + description: SSHKey defines the name of the ssh key. + type: string type: object name: + default: hetzner description: Name defines the name of the secret. type: string required: diff --git a/controllers/hetznercluster_controller.go b/controllers/hetznercluster_controller.go index bec89f93b..8a1e7f89e 100644 --- a/controllers/hetznercluster_controller.go +++ b/controllers/hetznercluster_controller.go @@ -173,6 +173,30 @@ func (r *HetznerClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reque func (r *HetznerClusterReconciler) reconcileNormal(ctx context.Context, clusterScope *scope.ClusterScope) (ctrl.Result, error) { hetznerCluster := clusterScope.HetznerCluster + // write ssh key name from secret to spec of HetznerCluster if it is specified + sshKeyName := clusterScope.HetznerSecret().Data[hetznerCluster.Spec.HetznerSecret.Key.SSHKey] + if len(sshKeyName) > 0 { + // Check if the SSH key name already exists + keyExists := false + for _, key := range hetznerCluster.Spec.SSHKeys.HCloud { + if string(sshKeyName) == key.Name { + keyExists = true + break + } + } + + // If the SSH key name doesn't exist, append it + if !keyExists { + hetznerCluster.Spec.SSHKeys.HCloud = append(hetznerCluster.Spec.SSHKeys.HCloud, infrav1.SSHKey{Name: string(sshKeyName)}) + record.Eventf( + hetznerCluster, + "SSHKeyNameAddedFromHetznerSecret", "added the ssh key %q from the hetzner secret specified under key %q", + string(sshKeyName), + hetznerCluster.Spec.HetznerSecret.Key.SSHKey, + ) + } + } + // If the HetznerCluster doesn't have our finalizer, add it. controllerutil.AddFinalizer(hetznerCluster, infrav1.ClusterFinalizer) if err := clusterScope.PatchObject(ctx); err != nil {