diff --git a/README.md b/README.md index fb2d6db9e..a3795e3f7 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,14 @@ The Hetzner Cloud controller manager seamlessly integrates your Kubernetes clust ## About the Fork -In the long run, we (Syself) would like to switch to the [upstream ccm](https://github.com/syself/hetzner-cloud-controller-manager/) again. +We plan to support the [upstream hcloud +ccm](https://github.com/hetznercloud/hcloud-cloud-controller-manager/) in +[CAPH](https://github.com/syself/cluster-api-provider-hetzner/). After that, this fork is no longer +needed. + +## About the Fork (old) + +In the long run, we (Syself) would like to switch to the [upstream ccm](https://github.com/hetznercloud/hcloud-cloud-controller-manager/) again. A lot of changes were made in the upstream fork, and we don't plan to merge them into our fork. @@ -62,9 +69,12 @@ See [CAPH docs](https://syself.com/docs/caph/topics/baremetal/creating-workload- ## Usage -We recommend to mount the secret `hetzner` as volume and make it avaiable for the container as `/etc/hetzner-secret`. -Then the credentials are automatically reloaded, when the secret changes. -You see an example in the [ccm helm chart](https://github.com/syself/charts/tree/main/charts/ccm-hetzner) +We recommend to mount the secret `hetzner` as volume and make it avaiable for the container as +`/etc/hetzner-secret`. Then the credentials are automatically reloaded, when the secret changes. +When you use the hot-reloading, be sure that the keys in the secret use these names: "hcloud" (for +the HCLOUD_TOKEN), "robot-user" and "robot-password". For compatibility with the upstream hcloud-ccm +we support the key "token" instead of "hcloud". You see an example in the [ccm helm +chart](https://github.com/syself/charts/tree/main/charts/ccm-hetzner) ## Env Variables diff --git a/hcloud/instances.go b/hcloud/instances.go index 6e10a1977..3545a0be5 100644 --- a/hcloud/instances.go +++ b/hcloud/instances.go @@ -157,6 +157,9 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *corev1.Node) (*c node.Name, errServerNotFound) } return &cloudprovider.InstanceMetadata{ + // It is ok that this code (syself hetzner-ccm) returns the legacy format + // "hcloud://bm-NNNN". We will use the upstream hcloud-ccm in the future. Related PR for + // caph: https://github.com/syself/cluster-api-provider-hetzner/pull/1703 ProviderID: providerid.LegacyFromRobotServerNumber(bmServer.ServerNumber), InstanceType: getInstanceTypeOfRobotServer(bmServer), NodeAddresses: robotNodeAddresses(i.addressFamily, bmServer), diff --git a/internal/credentials/hotreload.go b/internal/credentials/hotreload.go index 90a5340a6..312d8da93 100644 --- a/internal/credentials/hotreload.go +++ b/internal/credentials/hotreload.go @@ -1,6 +1,7 @@ package credentials import ( + "errors" "fmt" "os" "path/filepath" @@ -91,7 +92,7 @@ func handleEvent(credentialsDir, baseName string, hcloudClient *hcloud.Client, r // This case is executed, when the process is running on a local machine. return loadRobotCredentials(credentialsDir, robotClient) - case "hcloud": + case "hcloud", "token": // This case is executed, when the process is running on a local machine. return loadHcloudCredentials(credentialsDir, hcloudClient) @@ -228,12 +229,19 @@ func GetInitialHcloudCredentialsFromDirectory(credentialsDir string) (string, er } func readHcloudCredentials(credentialsDir string) (string, error) { - hcloudTokenFile := filepath.Join(credentialsDir, "hcloud") - data, err := os.ReadFile(hcloudTokenFile) - if err != nil { - return "", fmt.Errorf("reading hcloud token from %q failed: %w", hcloudTokenFile, err) + var allErrors []error + for _, key := range []string{"hcloud", "token"} { + // upstream hcloud ccm expects by defaul the key "token" in the secret. To ease migration + // (back and forward), we support that, too. + hcloudTokenFile := filepath.Join(credentialsDir, key) + data, err := os.ReadFile(hcloudTokenFile) + if err != nil { + allErrors = append(allErrors, fmt.Errorf("reading hcloud token from %q failed: %w", hcloudTokenFile, err)) + continue + } + return strings.TrimSpace(string(data)), nil } - return strings.TrimSpace(string(data)), nil + return "", errors.Join(allErrors...) } // GetDirectory returns the directory where the credentials are stored. diff --git a/internal/providerid/providerid.go b/internal/providerid/providerid.go index cfcda5bdc..634281642 100644 --- a/internal/providerid/providerid.go +++ b/internal/providerid/providerid.go @@ -17,6 +17,8 @@ const ( // // It MUST not be changed, otherwise existing nodes will not be recognized anymore. prefixRobotLegacy = "hcloud://bm-" + + prefixRobotNew = "hrobot://" ) type UnkownPrefixError struct { @@ -40,6 +42,13 @@ func (e *UnkownPrefixError) Error() string { func ToServerID(providerID string) (id int64, isCloudServer bool, err error) { idString := "" switch { + case strings.HasPrefix(providerID, prefixRobotNew): + // If a cluster switched from old-syself-ccm to upstream-hcloud-ccm, and then back again to + // old-syself-ccm, then there might be nodes with the new format. Let's support this + // edge-case, but in the long run the upstream-hcloud-ccm should be used. Related: + // https://github.com/syself/cluster-api-provider-hetzner/pull/1703 + idString = strings.ReplaceAll(providerID, prefixRobotNew, "") + case strings.HasPrefix(providerID, prefixRobotLegacy): // This case needs to be before [prefixCloud], as [prefixCloud] is a superset of [prefixRobotLegacy] idString = strings.ReplaceAll(providerID, prefixRobotLegacy, "") diff --git a/internal/providerid/providerid_test.go b/internal/providerid/providerid_test.go index 57541ce77..8cefede85 100644 --- a/internal/providerid/providerid_test.go +++ b/internal/providerid/providerid_test.go @@ -93,12 +93,19 @@ func TestToServerID(t *testing.T) { wantErr: errors.New("providerID is missing a serverID: hcloud://"), }, { - name: "[robot-syself] simple id", + name: "[robot-syself] simple id (legacy)", providerID: "hcloud://bm-4321", wantID: 4321, wantIsCloudServer: false, wantErr: nil, }, + { + name: "[robot-syself] simple id (new)", + providerID: "hrobot://4321", + wantID: 4321, + wantIsCloudServer: false, + wantErr: nil, + }, { name: "[robot-syself] invalid id", providerID: "hcloud://bm-my-robot",