Commit Diff


commit - 9ab732cda40be5693e3f1ddba1a5ebf7de9e1bd5
commit + 6e415953de07ac11e0f54ac397d156b23f384a15
blob - c7f730409869f703b332b37ba6f706015bb6e09b
blob + 288e822520bdd2fc700aaa803244e7e0b422362a
--- http.go
+++ http.go
@@ -1,12 +1,40 @@
 package icinga
 
 import (
+	"fmt"
 	"io"
 	"net/http"
+	"strings"
 )
 
 const versionPrefix = "/v1"
 
+type results struct {
+	Results []result
+}
+
+type result struct {
+	Attrs  interface{}
+	Code   int
+	Errors []string
+	Name   string
+	Type   string
+}
+
+var ErrNoObject = errors.New("no such object")
+
+func (res results) Error() string {
+	var s []string
+	for _, r := range res.Results {
+		s = append(s, r.Error())
+	}
+	return strings.Join(s, ", ")
+}
+
+func (r result) Error() string {
+	return strings.Join(r.Errors, ", ")
+}
+
 func newRequest(method, host, path string, body io.Reader) (*http.Request, error) {
 	url := "https://" + host + versionPrefix + path
 	req, err := http.NewRequest(method, url, body)
@@ -51,12 +79,26 @@ func (c *Client) put(path string, body io.Reader) (*ht
 	return c.do(req)
 }
 
-func (c *Client) delete(path string, body io.Reader) (*http.Response, error) {
+func (c *Client) delete(path string) error {
 	req, err := newRequest(http.MethodDelete, c.host, path, nil)
 	if err != nil {
 		return nil, err
 	}
-	return c.do(req)
+	resp, err := c.do(req)
+	if err != nil {
+		return err
+	}
+	if resp.StatusCode == http.StatusOK {
+		return nil
+	} else if resp.StatusCode == http.StatusNotFound {
+		return ErrNoObject
+	}
+	defer resp.Body.Close()
+	var results results
+	if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
+		return fmt.Errorf("decode response: %w", err)
+	}
+	return results
 }
 
 func (c *Client) do(req *http.Request) (*http.Response, error) {
blob - /dev/null
blob + 89a3a5d5f479418d18c6e8b14503b9e41263a13a (mode 644)
--- /dev/null
+++ host.go
@@ -0,0 +1,34 @@
+package icinga
+
+type Host struct {
+	Name  string
+	State int
+}
+
+var ErrNoHost = errors.New("no such host")
+
+func (c *Client) Hosts() ([]Host, error) {
+	_, err := c.get("/objects/hosts")
+	if err != nil {
+		return nil, err
+	}
+	return nil, err
+}
+
+func (c *Client) LookupHost(name string) (Host, error) {
+	resp, err := c.get("/objects/hosts/" + name)
+	if err != nil {
+		return Host{}, err
+	}
+	if resp.StatusCode == http.StatusNotFound {
+		return Host{}, fmt.Errorf("lookup %s: %w", name, ErrNoHost)
+	}
+	return Host{}, err
+}
+
+func (c *Client) DeleteHost(name string) error {
+	if err := c.delete("/objects/hosts/" + name); err != nil {
+		return fmt.Errorf("delete host %s: %w", name, err)
+	}
+	return nil
+}
blob - 0afa410559a68ae012d13520f47e74a6b29fa0d9 (mode 644)
blob + /dev/null
--- users.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package icinga
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"net/http"
-)
-
-type User struct {
-	Name  string
-	Type  string
-	Attrs struct {
-		Email string
-	}
-}
-
-var testUser = User{
-	Name: "Olly",
-	Type: "User",
-	Attrs: struct {
-		Email string
-	}{Email: "olly@example.com"},
-}
-
-func (c *Client) Users() ([]User, error) {
-	resp, err := c.get("/objects/users")
-	if err != nil {
-		return nil, err
-	}
-	if resp.StatusCode != http.StatusOK {
-		return nil, fmt.Errorf("get /objects/users: status %s", resp.Status)
-	}
-	return []User{testUser}, nil
-}
-
-func (c *Client) CreateUser(name, email string) error {
-	u := User{
-		Name: name,
-		Type: "User",
-		Attrs: struct {
-			Email string
-		}{email},
-	}
-	buf := &bytes.Buffer{}
-	if err := json.NewEncoder(buf).Encode(u); err != nil {
-		return err
-	}
-	_, err := c.put("/objects/users/"+name, buf)
-	return err
-}
blob - /dev/null
blob + 64068f9309c6e8d5c6a9010a7480b5947d86d288 (mode 644)
--- /dev/null
+++ user.go
@@ -0,0 +1,75 @@
+package icinga
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"net/http"
+)
+
+type User struct {
+	Name   string
+	Email  string
+	Groups []string
+}
+
+var testUser = User{
+	Name:  "testUser",
+	Email: "test@example.com",
+}
+
+var ErrNoUser = errors.New("no such user")
+
+func (u User) MarshalJSON() ([]byte, error) {
+	type Alias User
+	return json.Marshal(&struct {
+		Attrs Alias
+	}{Attrs: (Alias)(u)})
+}
+
+func (c *Client) Users() ([]User, error) {
+	_, err := c.get("/objects/users")
+	if err != nil {
+		return nil, err
+	}
+	return []User{testUser}, nil
+}
+
+func (c *Client) LookupUser(name string) (User, error) {
+	resp, err := c.get("/objects/users/" + name)
+	if err != nil {
+		return User{}, err
+	}
+	if resp.StatusCode == http.StatusNotFound {
+		return User{}, fmt.Errorf("lookup %s: %w", name, ErrNoUser)
+	}
+	return testUser, nil
+}
+
+func (c *Client) CreateUser(u User) error {
+	buf := &bytes.Buffer{}
+	if err := json.NewEncoder(buf).Encode(u); err != nil {
+		return err
+	}
+	resp, err := c.put("/objects/users/"+u.Name, buf)
+	if err != nil {
+		return fmt.Errorf("create %s: %w", u.Name, err)
+	}
+	if resp.StatusCode == http.StatusOK {
+		return nil
+	}
+	defer resp.Body.Close()
+	var results results
+	if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
+		return fmt.Errorf("create %s: decode response: %w", u.Name, err)
+	}
+	return fmt.Errorf("create %s: %w", u.Name, results)
+}
+
+func (c *Client) DeleteUser(name string) error {
+	if err := c.delete("/objects/users/" + name); err != nil {
+		return fmt.Errorf("delete user %s: %w", name, err)
+	}
+	return nil
+}