From 711d027dfba59ef710383d9fc671cd7ad705d16c Mon Sep 17 00:00:00 2001
From: JonasS <jonass@dev.jsje.de>
Date: Wed, 19 Jul 2023 19:41:55 +0200
Subject: [PATCH] bugfix: Make server location, SSH key optional (closes #110,
 thanks @avpnusr) - reduce overly pedantic null checks - indicate nullability
 in getter name

---
 README.md               |  4 ++--
 driver/driver.go        |  4 ++--
 driver/hetzner_query.go | 24 ++++++++++++++++--------
 driver/setup.go         |  2 +-
 driver/ssh_keys.go      |  4 ++--
 5 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/README.md b/README.md
index acee131..1d5aac2 100644
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@ You can find sources and pre-compiled binaries [here](https://github.com/JonasPr
 
 ```bash
 # Download the binary (this example downloads the binary for linux amd64)
-$ wget https://github.com/JonasProgrammer/docker-machine-driver-hetzner/releases/download/4.1.0/docker-machine-driver-hetzner_4.1.0_linux_amd64.tar.gz
-$ tar -xvf docker-machine-driver-hetzner_4.1.0_linux_amd64.tar.gz
+$ wget https://github.com/JonasProgrammer/docker-machine-driver-hetzner/releases/download/4.1.2/docker-machine-driver-hetzner_4.1.2_linux_amd64.tar.gz
+$ tar -xvf docker-machine-driver-hetzner_4.1.2_linux_amd64.tar.gz
 
 # Make it executable and copy the binary in a directory accessible with your $PATH
 $ chmod +x docker-machine-driver-hetzner
diff --git a/driver/driver.go b/driver/driver.go
index ae2181a..1c54f0b 100644
--- a/driver/driver.go
+++ b/driver/driver.go
@@ -425,7 +425,7 @@ func (d *Driver) PreCreateCheck() error {
 		return errors.Wrap(err, "could not get image")
 	}
 
-	if _, err := d.getLocation(); err != nil {
+	if _, err := d.getLocationNullable(); err != nil {
 		return errors.Wrap(err, "could not get location")
 	}
 
@@ -563,7 +563,7 @@ func (d *Driver) Remove() error {
 
 	// failure to remove a server-specific key is a hard error
 	if !d.IsExistingKey && d.KeyID != 0 {
-		key, err := d.getKey()
+		key, err := d.getKeyNullable()
 		if err != nil {
 			return errors.Wrap(err, "could not get ssh key")
 		}
diff --git a/driver/hetzner_query.go b/driver/hetzner_query.go
index 4a50f79..fd36192 100644
--- a/driver/hetzner_query.go
+++ b/driver/hetzner_query.go
@@ -14,10 +14,13 @@ func (d *Driver) getClient() *hcloud.Client {
 	return hcloud.NewClient(hcloud.WithToken(d.AccessToken), hcloud.WithApplication("docker-machine-driver", d.version))
 }
 
-func (d *Driver) getLocation() (*hcloud.Location, error) {
+func (d *Driver) getLocationNullable() (*hcloud.Location, error) {
 	if d.cachedLocation != nil {
 		return d.cachedLocation, nil
 	}
+	if d.Location == "" {
+		return nil, nil
+	}
 
 	location, _, err := d.getClient().Location.GetByName(context.Background(), d.Location)
 	if err != nil {
@@ -95,6 +98,17 @@ func (d *Driver) getImageArchitectureForLookup() (hcloud.Architecture, error) {
 }
 
 func (d *Driver) getKey() (*hcloud.SSHKey, error) {
+	key, err := d.getKeyNullable()
+	if err != nil {
+		return nil, err
+	}
+	if key == nil {
+		return nil, fmt.Errorf("key not found: %v", d.KeyID)
+	}
+	return key, err
+}
+
+func (d *Driver) getKeyNullable() (*hcloud.SSHKey, error) {
 	if d.cachedKey != nil {
 		return d.cachedKey, nil
 	}
@@ -103,14 +117,11 @@ func (d *Driver) getKey() (*hcloud.SSHKey, error) {
 	if err != nil {
 		return nil, errors.Wrap(err, "could not get sshkey by ID")
 	}
-	if key == nil {
-		return nil, fmt.Errorf("key not found: %v", d.KeyID)
-	}
 	d.cachedKey = key
 	return instrumented(key), nil
 }
 
-func (d *Driver) getRemoteKeyWithSameFingerprint(publicKeyBytes []byte) (*hcloud.SSHKey, error) {
+func (d *Driver) getRemoteKeyWithSameFingerprintNullable(publicKeyBytes []byte) (*hcloud.SSHKey, error) {
 	publicKey, _, _, _, err := ssh.ParseAuthorizedKey(publicKeyBytes)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not parse ssh public key")
@@ -122,9 +133,6 @@ func (d *Driver) getRemoteKeyWithSameFingerprint(publicKeyBytes []byte) (*hcloud
 	if err != nil {
 		return remoteKey, errors.Wrap(err, "could not get sshkey by fingerprint")
 	}
-	if remoteKey == nil {
-		return nil, fmt.Errorf("key not found by fingerprint: %v", fp)
-	}
 	return instrumented(remoteKey), nil
 }
 
diff --git a/driver/setup.go b/driver/setup.go
index cabfa00..0601475 100644
--- a/driver/setup.go
+++ b/driver/setup.go
@@ -72,7 +72,7 @@ func (d *Driver) makeCreateServerOptions() (*hcloud.ServerCreateOpts, error) {
 	}
 	srvopts.Volumes = volumes
 
-	if srvopts.Location, err = d.getLocation(); err != nil {
+	if srvopts.Location, err = d.getLocationNullable(); err != nil {
 		return nil, errors.Wrap(err, "could not get location")
 	}
 	if srvopts.ServerType, err = d.getType(); err != nil {
diff --git a/driver/ssh_keys.go b/driver/ssh_keys.go
index 4d60288..76fab96 100644
--- a/driver/ssh_keys.go
+++ b/driver/ssh_keys.go
@@ -70,7 +70,7 @@ func (d *Driver) createRemoteKeys() error {
 			return errors.Wrap(err, "could not read ssh public key")
 		}
 
-		key, err := d.getRemoteKeyWithSameFingerprint(buf)
+		key, err := d.getRemoteKeyWithSameFingerprintNullable(buf)
 		if err != nil {
 			return errors.Wrap(err, "error retrieving potentially existing key")
 		}
@@ -89,7 +89,7 @@ func (d *Driver) createRemoteKeys() error {
 		d.KeyID = key.ID
 	}
 	for i, pubkey := range d.AdditionalKeys {
-		key, err := d.getRemoteKeyWithSameFingerprint([]byte(pubkey))
+		key, err := d.getRemoteKeyWithSameFingerprintNullable([]byte(pubkey))
 		if err != nil {
 			return errors.Wrapf(err, "error checking for existing key for %v", pubkey)
 		}
-- 
GitLab