diff --git a/ca/client.go b/ca/client.go index eefc4612..6c288ee2 100644 --- a/ca/client.go +++ b/ca/client.go @@ -418,6 +418,30 @@ func (c *Client) SetTransport(tr http.RoundTripper) { c.client.Transport = tr } +// Version performs the version request to the CA and returns the +// api.VersionResponse struct. +func (c *Client) Version() (*api.VersionResponse, error) { + var retried bool + u := c.endpoint.ResolveReference(&url.URL{Path: "/version"}) +retry: + resp, err := c.client.Get(u.String()) + if err != nil { + return nil, errors.Wrapf(err, "client GET %s failed", u) + } + if resp.StatusCode >= 400 { + if !retried && c.retryOnError(resp) { + retried = true + goto retry + } + return nil, readError(resp.Body) + } + var version api.VersionResponse + if err := readJSON(resp.Body, &version); err != nil { + return nil, errors.Wrapf(err, "error reading %s", u) + } + return &version, nil +} + // Health performs the health request to the CA and returns the // api.HealthResponse struct. func (c *Client) Health() (*api.HealthResponse, error) { diff --git a/ca/client_test.go b/ca/client_test.go index f9a968c0..7a36a64b 100644 --- a/ca/client_test.go +++ b/ca/client_test.go @@ -150,6 +150,61 @@ func equalJSON(t *testing.T, a interface{}, b interface{}) bool { return bytes.Equal(ab, bb) } +func TestClient_Version(t *testing.T) { + ok := &api.VersionResponse{Version: "test"} + internal := api.InternalServerError(fmt.Errorf("Internal Server Error")) + notFound := api.NotFound(fmt.Errorf("Not Found")) + + tests := []struct { + name string + response interface{} + responseCode int + wantErr bool + }{ + {"ok", ok, 200, false}, + {"500", internal, 500, true}, + {"404", notFound, 404, true}, + } + + srv := httptest.NewServer(nil) + defer srv.Close() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c, err := NewClient(srv.URL, WithTransport(http.DefaultTransport)) + if err != nil { + t.Errorf("NewClient() error = %v", err) + return + } + + srv.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + api.JSONStatus(w, tt.response, tt.responseCode) + }) + + got, err := c.Version() + if (err != nil) != tt.wantErr { + fmt.Printf("%+v", err) + t.Errorf("Client.Version() error = %v, wantErr %v", err, tt.wantErr) + return + } + + switch { + case err != nil: + if got != nil { + t.Errorf("Client.Version() = %v, want nil", got) + } + if !reflect.DeepEqual(err, tt.response) { + t.Errorf("Client.Version() error = %v, want %v", err, tt.response) + } + default: + if !reflect.DeepEqual(got, tt.response) { + t.Errorf("Client.Version() = %v, want %v", got, tt.response) + } + } + }) + } +} + func TestClient_Health(t *testing.T) { ok := &api.HealthResponse{Status: "ok"} nok := api.InternalServerError(fmt.Errorf("Internal Server Error"))