169 lines
4.9 KiB
Go
169 lines
4.9 KiB
Go
|
package cfclient
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
type RoutesResponse struct {
|
||
|
Count int `json:"total_results"`
|
||
|
Pages int `json:"total_pages"`
|
||
|
NextUrl string `json:"next_url"`
|
||
|
Resources []RoutesResource `json:"resources"`
|
||
|
}
|
||
|
|
||
|
type RoutesResource struct {
|
||
|
Meta Meta `json:"metadata"`
|
||
|
Entity Route `json:"entity"`
|
||
|
}
|
||
|
|
||
|
type RouteRequest struct {
|
||
|
DomainGuid string `json:"domain_guid"`
|
||
|
SpaceGuid string `json:"space_guid"`
|
||
|
Host string `json:"host"` // required for http routes
|
||
|
Path string `json:"path"`
|
||
|
Port int `json:"port"`
|
||
|
}
|
||
|
|
||
|
type Route struct {
|
||
|
Guid string `json:"guid"`
|
||
|
CreatedAt string `json:"created_at"`
|
||
|
UpdatedAt string `json:"updated_at"`
|
||
|
Host string `json:"host"`
|
||
|
Path string `json:"path"`
|
||
|
DomainGuid string `json:"domain_guid"`
|
||
|
SpaceGuid string `json:"space_guid"`
|
||
|
ServiceInstanceGuid string `json:"service_instance_guid"`
|
||
|
Port int `json:"port"`
|
||
|
c *Client
|
||
|
}
|
||
|
|
||
|
// CreateRoute creates a regular http route
|
||
|
func (c *Client) CreateRoute(routeRequest RouteRequest) (Route, error) {
|
||
|
routesResource, err := c.createRoute("/v2/routes", routeRequest)
|
||
|
if nil != err {
|
||
|
return Route{}, err
|
||
|
}
|
||
|
return c.mergeRouteResource(routesResource), nil
|
||
|
}
|
||
|
|
||
|
// CreateTcpRoute creates a TCP route
|
||
|
func (c *Client) CreateTcpRoute(routeRequest RouteRequest) (Route, error) {
|
||
|
routesResource, err := c.createRoute("/v2/routes?generate_port=true", routeRequest)
|
||
|
if nil != err {
|
||
|
return Route{}, err
|
||
|
}
|
||
|
return c.mergeRouteResource(routesResource), nil
|
||
|
}
|
||
|
|
||
|
// BindRoute associates the specified route with the application
|
||
|
func (c *Client) BindRoute(routeGUID, appGUID string) error {
|
||
|
resp, err := c.DoRequest(c.NewRequest("PUT", fmt.Sprintf("/v2/routes/%s/apps/%s", routeGUID, appGUID)))
|
||
|
if err != nil {
|
||
|
return errors.Wrapf(err, "Error binding route %s to app %s", routeGUID, appGUID)
|
||
|
}
|
||
|
if resp.StatusCode != http.StatusCreated {
|
||
|
return fmt.Errorf("Error binding route %s to app %s, response code: %d", routeGUID, appGUID, resp.StatusCode)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) ListRoutesByQuery(query url.Values) ([]Route, error) {
|
||
|
return c.fetchRoutes("/v2/routes?" + query.Encode())
|
||
|
}
|
||
|
|
||
|
func (c *Client) fetchRoutes(requestUrl string) ([]Route, error) {
|
||
|
var routes []Route
|
||
|
for {
|
||
|
routesResp, err := c.getRoutesResponse(requestUrl)
|
||
|
if err != nil {
|
||
|
return []Route{}, err
|
||
|
}
|
||
|
for _, route := range routesResp.Resources {
|
||
|
route.Entity.Guid = route.Meta.Guid
|
||
|
route.Entity.CreatedAt = route.Meta.CreatedAt
|
||
|
route.Entity.UpdatedAt = route.Meta.UpdatedAt
|
||
|
route.Entity.c = c
|
||
|
routes = append(routes, route.Entity)
|
||
|
}
|
||
|
requestUrl = routesResp.NextUrl
|
||
|
if requestUrl == "" {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return routes, nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) ListRoutes() ([]Route, error) {
|
||
|
return c.ListRoutesByQuery(nil)
|
||
|
}
|
||
|
|
||
|
func (c *Client) getRoutesResponse(requestUrl string) (RoutesResponse, error) {
|
||
|
var routesResp RoutesResponse
|
||
|
r := c.NewRequest("GET", requestUrl)
|
||
|
resp, err := c.DoRequest(r)
|
||
|
if err != nil {
|
||
|
return RoutesResponse{}, errors.Wrap(err, "Error requesting routes")
|
||
|
}
|
||
|
resBody, err := ioutil.ReadAll(resp.Body)
|
||
|
defer resp.Body.Close()
|
||
|
if err != nil {
|
||
|
return RoutesResponse{}, errors.Wrap(err, "Error reading routes body")
|
||
|
}
|
||
|
err = json.Unmarshal(resBody, &routesResp)
|
||
|
if err != nil {
|
||
|
return RoutesResponse{}, errors.Wrap(err, "Error unmarshalling routes")
|
||
|
}
|
||
|
return routesResp, nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) createRoute(requestUrl string, routeRequest RouteRequest) (RoutesResource, error) {
|
||
|
var routeResp RoutesResource
|
||
|
buf := bytes.NewBuffer(nil)
|
||
|
err := json.NewEncoder(buf).Encode(routeRequest)
|
||
|
if err != nil {
|
||
|
return RoutesResource{}, errors.Wrap(err, "Error creating route - failed to serialize request body")
|
||
|
}
|
||
|
r := c.NewRequestWithBody("POST", requestUrl, buf)
|
||
|
resp, err := c.DoRequest(r)
|
||
|
if err != nil {
|
||
|
return RoutesResource{}, errors.Wrap(err, "Error creating route")
|
||
|
}
|
||
|
resBody, err := ioutil.ReadAll(resp.Body)
|
||
|
defer resp.Body.Close()
|
||
|
if err != nil {
|
||
|
return RoutesResource{}, errors.Wrap(err, "Error creating route")
|
||
|
}
|
||
|
err = json.Unmarshal(resBody, &routeResp)
|
||
|
if err != nil {
|
||
|
return RoutesResource{}, errors.Wrap(err, "Error unmarshalling routes")
|
||
|
}
|
||
|
routeResp.Entity.c = c
|
||
|
return routeResp, nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) DeleteRoute(guid string) error {
|
||
|
resp, err := c.DoRequest(c.NewRequest("DELETE", fmt.Sprintf("/v2/routes/%s", guid)))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if resp.StatusCode != http.StatusNoContent {
|
||
|
return errors.Wrapf(err, "Error deleting route %s, response code: %d", guid, resp.StatusCode)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) mergeRouteResource(rr RoutesResource) Route {
|
||
|
rr.Entity.Guid = rr.Meta.Guid
|
||
|
rr.Entity.CreatedAt = rr.Meta.CreatedAt
|
||
|
rr.Entity.UpdatedAt = rr.Meta.UpdatedAt
|
||
|
rr.Entity.c = c
|
||
|
return rr.Entity
|
||
|
}
|