Initial implementation of garage.AdminClient

This commit is contained in:
Brian Picciano 2022-10-16 22:17:24 +02:00
parent eba9b23e61
commit 7a25e1b6e6

View File

@ -0,0 +1,84 @@
package garage
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
)
// AdminClient is a helper type for performing actions against the garage admin
// interface.
type AdminClient struct {
c *http.Client
addr string
adminToken string
}
// NewAdminClient initializes and returns an AdminClient which will use the
// given address and adminToken for all requests made.
func NewAdminClient(addr, adminToken string) *AdminClient {
return &AdminClient{
c: &http.Client{
Transport: http.DefaultTransport.(*http.Transport).Clone(),
},
addr: addr,
adminToken: adminToken,
}
}
// Do performs an HTTP request with the given method (GET, POST) and path, and
// using the json marshaling of the given body as the request body (unless body
// is nil). It will JSON unmarshal the response into rcv, unless rcv is nil.
func (c *AdminClient) Do(
ctx context.Context, rcv interface{}, method, path string, body interface{},
) error {
var bodyR io.Reader
if body != nil {
bodyBuf := new(bytes.Buffer)
bodyR = bodyBuf
if err := json.NewEncoder(bodyBuf).Encode(body); err != nil {
return fmt.Errorf("json marshaling body: %w", err)
}
}
urlStr := fmt.Sprintf("http://%s%s", c.addr, path)
req, err := http.NewRequestWithContext(ctx, method, urlStr, bodyR)
if err != nil {
return fmt.Errorf("initializing request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.adminToken)
res, err := c.c.Do(req)
if err != nil {
return fmt.Errorf("performing http request: %w", err)
}
defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("unexpected %s response returned", res.Status)
}
if rcv == nil {
if _, err := io.Copy(io.Discard, res.Body); err != nil {
return fmt.Errorf("discarding response body: %w", err)
}
return nil
}
if err := json.NewDecoder(res.Body).Decode(rcv); err != nil {
return fmt.Errorf("decoding json response body: %w", err)
}
return nil
}