commit 6e415953de07ac11e0f54ac397d156b23f384a15 from: Oliver Lowe date: Thu Jan 6 01:30:37 2022 UTC dump 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 +}