Repository: hetznercloud/hcloud-go
Pull request #20 (2018-01-04 17:10:26)

Implement get by name


Patch:
diff --git a/hcloud/image.go b/hcloud/image.go
index 4fa7617..9af2890 100644
--- a/hcloud/image.go
+++ b/hcloud/image.go
@@ -3,6 +3,7 @@ package hcloud
 import (
 	"context"
 	"fmt"
+	"net/url"
 	"time"
 
 	"github.com/hetznercloud/hcloud-go/hcloud/schema"
@@ -69,6 +70,26 @@ func (c *ImageClient) GetByID(ctx context.Context, id int) (*Image, *Response, e
 	return ImageFromSchema(body.Image), resp, nil
 }
 
+// GetByName retrieves an image by its name.
+func (c *ImageClient) GetByName(ctx context.Context, name string) (*Image, *Response, error) {
+	path := "/images?name=" + url.QueryEscape(name)
+	req, err := c.client.NewRequest(ctx, "GET", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var body schema.ImageListResponse
+	resp, err := c.client.Do(req, &body)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	if len(body.Images) == 0 {
+		return nil, resp, nil
+	}
+	return ImageFromSchema(body.Images[0]), resp, nil
+}
+
 // ImageListOpts specifies options for listing images.
 type ImageListOpts struct {
 	ListOpts
diff --git a/hcloud/server.go b/hcloud/server.go
index dfc82d1..b979d2a 100644
--- a/hcloud/server.go
+++ b/hcloud/server.go
@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"net/url"
 	"strconv"
 	"time"
 
@@ -102,6 +103,26 @@ func (c *ServerClient) GetByID(ctx context.Context, id int) (*Server, *Response,
 	return ServerFromSchema(body.Server), resp, nil
 }
 
+// GetByName retreives a server by its name.
+func (c *ServerClient) GetByName(ctx context.Context, name string) (*Server, *Response, error) {
+	path := "/servers?name=" + url.QueryEscape(name)
+	req, err := c.client.NewRequest(ctx, "GET", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var body schema.ServerListResponse
+	resp, err := c.client.Do(req, &body)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	if len(body.Servers) == 0 {
+		return nil, resp, nil
+	}
+	return ServerFromSchema(body.Servers[0]), resp, nil
+}
+
 // ServerListOpts specifies options for listing servers.
 type ServerListOpts struct {
 	ListOpts
diff --git a/hcloud/ssh_key.go b/hcloud/ssh_key.go
index 7cc83b2..29726df 100644
--- a/hcloud/ssh_key.go
+++ b/hcloud/ssh_key.go
@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"net/url"
 
 	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
@@ -41,6 +42,26 @@ func (c *SSHKeyClient) GetByID(ctx context.Context, id int) (*SSHKey, *Response,
 	return SSHKeyFromSchema(body.SSHKey), resp, nil
 }
 
+// GetByName retrieves a SSH key by its name.
+func (c *SSHKeyClient) GetByName(ctx context.Context, name string) (*SSHKey, *Response, error) {
+	path := "/ssh_keys?name=" + url.QueryEscape(name)
+	req, err := c.client.NewRequest(ctx, "GET", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var body schema.SSHKeyListResponse
+	resp, err := c.client.Do(req, &body)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	if len(body.SSHKeys) == 0 {
+		return nil, resp, nil
+	}
+	return SSHKeyFromSchema(body.SSHKeys[0]), resp, nil
+}
+
 // SSHKeyListOpts specifies options for listing SSH keys.
 type SSHKeyListOpts struct {
 	ListOpts


Test patch:
diff --git a/hcloud/image_test.go b/hcloud/image_test.go
index 362d5aa..aafc6cd 100644
--- a/hcloud/image_test.go
+++ b/hcloud/image_test.go
@@ -59,6 +59,59 @@ func TestImageClient(t *testing.T) {
 		}
 	})
 
+	t.Run("GetByName", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/images", func(w http.ResponseWriter, r *http.Request) {
+			if r.URL.RawQuery != "name=my+image" {
+				t.Fatal("missing name query")
+			}
+			json.NewEncoder(w).Encode(schema.ImageListResponse{
+				Images: []schema.Image{
+					{
+						ID: 1,
+					},
+				},
+			})
+		})
+
+		ctx := context.Background()
+		image, _, err := env.Client.Image.GetByName(ctx, "my image")
+		if err != nil {
+			t.Fatal(err)
+		}
+		if image == nil {
+			t.Fatal("no image")
+		}
+		if image.ID != 1 {
+			t.Errorf("unexpected image ID: %v", image.ID)
+		}
+	})
+
+	t.Run("GetByName (not found)", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/images", func(w http.ResponseWriter, r *http.Request) {
+			if r.URL.RawQuery != "name=my+image" {
+				t.Fatal("missing name query")
+			}
+			json.NewEncoder(w).Encode(schema.ImageListResponse{
+				Images: []schema.Image{},
+			})
+		})
+
+		ctx := context.Background()
+		image, _, err := env.Client.Image.GetByName(ctx, "my image")
+		if err != nil {
+			t.Fatal(err)
+		}
+		if image != nil {
+			t.Fatal("unexpected image")
+		}
+	})
+
 	t.Run("List", func(t *testing.T) {
 		env := newTestEnv()
 		defer env.Teardown()
diff --git a/hcloud/server_test.go b/hcloud/server_test.go
index 45a8ba2..78507eb 100644
--- a/hcloud/server_test.go
+++ b/hcloud/server_test.go
@@ -58,6 +58,60 @@ func TestServerClientGetByIDNotFound(t *testing.T) {
 	}
 }
 
+func TestServerClientGetByName(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.RawQuery != "name=myserver" {
+			t.Fatal("missing name query")
+		}
+		json.NewEncoder(w).Encode(schema.ServerListResponse{
+			Servers: []schema.Server{
+				{
+					ID:   1,
+					Name: "myserver",
+				},
+			},
+		})
+	})
+
+	ctx := context.Background()
+	server, _, err := env.Client.Server.GetByName(ctx, "myserver")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if server == nil {
+		t.Fatal("no server")
+	}
+	if server.ID != 1 {
+		t.Errorf("unexpected server ID: %v", server.ID)
+	}
+}
+
+func TestServerClientGetByNameNotFound(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers", func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.RawQuery != "name=myserver" {
+			t.Fatal("missing name query")
+		}
+		json.NewEncoder(w).Encode(schema.ServerListResponse{
+			Servers: []schema.Server{},
+		})
+	})
+
+	ctx := context.Background()
+	server, _, err := env.Client.Server.GetByName(ctx, "myserver")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if server != nil {
+		t.Fatal("unexpected server")
+	}
+}
+
 func TestServersList(t *testing.T) {
 	env := newTestEnv()
 	defer env.Teardown()
diff --git a/hcloud/ssh_key_test.go b/hcloud/ssh_key_test.go
index 400c238..b464870 100644
--- a/hcloud/ssh_key_test.go
+++ b/hcloud/ssh_key_test.go
@@ -28,7 +28,7 @@ func TestSSHKeyClientGetByID(t *testing.T) {
 	ctx := context.Background()
 	sshKey, _, err := env.Client.SSHKey.GetByID(ctx, 1)
 	if err != nil {
-		t.Fatalf("SSHKey.Get failed: %s", err)
+		t.Fatalf("SSHKey.GetByID failed: %s", err)
 	}
 	if sshKey == nil {
 		t.Fatal("no SSH key")
@@ -55,13 +55,67 @@ func TestSSHKeyClientGetByIDNotFound(t *testing.T) {
 	ctx := context.Background()
 	sshKey, _, err := env.Client.SSHKey.GetByID(ctx, 1)
 	if err != nil {
-		t.Fatalf("SSHKey.Get failed: %s", err)
+		t.Fatalf("SSHKey.GetByID failed: %s", err)
 	}
 	if sshKey != nil {
 		t.Fatal("expected no SSH key")
 	}
 }
 
+func TestSSHKeyClientGetByName(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/ssh_keys", func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.RawQuery != "name=My+Key" {
+			t.Fatal("missing name query")
+		}
+		fmt.Fprint(w, `{
+			"ssh_keys": [{
+				"id": 1,
+				"name": "My Key",
+				"fingerprint": "b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2c",
+				"public_key": "ssh-rsa AAAjjk76kgf...Xt"
+			}]
+		}`)
+	})
+
+	ctx := context.Background()
+	sshKey, _, err := env.Client.SSHKey.GetByName(ctx, "My Key")
+	if err != nil {
+		t.Fatalf("SSHKey.GetByName failed: %s", err)
+	}
+	if sshKey == nil {
+		t.Fatal("no SSH key")
+	}
+	if sshKey.ID != 1 {
+		t.Errorf("unexpected SSH key ID: %v", sshKey.ID)
+	}
+}
+
+func TestSSHKeyClientGetByNameNotFound(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/ssh_keys", func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.RawQuery != "name=My+Key" {
+			t.Fatal("missing name query")
+		}
+		fmt.Fprint(w, `{
+			"ssh_keys": []
+		}`)
+	})
+
+	ctx := context.Background()
+	sshKey, _, err := env.Client.SSHKey.GetByName(ctx, "My Key")
+	if err != nil {
+		t.Fatalf("SSHKey.GetByName failed: %s", err)
+	}
+	if sshKey != nil {
+		t.Fatal("unexpected SSH key")
+	}
+}
+
 func TestSSHKeyClientList(t *testing.T) {
 	env := newTestEnv()
 	defer env.Teardown()