github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/api/cloudcontroller/ccv2/route.go (about)

     1  package ccv2
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/internal"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
    14  	"code.cloudfoundry.org/cli/types"
    15  )
    16  
    17  // Route represents a Cloud Controller Route.
    18  type Route struct {
    19  
    20  	// GUID is the unique Route identifier.
    21  	GUID string `json:"-"`
    22  
    23  	// Host is the hostname of the route.
    24  	Host string `json:"host,omitempty"`
    25  
    26  	// Path is the path of the route.
    27  	Path string `json:"path,omitempty"`
    28  
    29  	// Port is the port number of the route.
    30  	Port types.NullInt `json:"port,omitempty"`
    31  
    32  	// DomainGUID is the unique Domain identifier.
    33  	DomainGUID string `json:"domain_guid"`
    34  
    35  	// SpaceGUID is the unique Space identifier.
    36  	SpaceGUID string `json:"space_guid"`
    37  }
    38  
    39  // UnmarshalJSON helps unmarshal a Cloud Controller Route response.
    40  func (route *Route) UnmarshalJSON(data []byte) error {
    41  	var ccRoute struct {
    42  		Metadata internal.Metadata `json:"metadata"`
    43  		Entity   struct {
    44  			Host       string        `json:"host"`
    45  			Path       string        `json:"path"`
    46  			Port       types.NullInt `json:"port"`
    47  			DomainGUID string        `json:"domain_guid"`
    48  			SpaceGUID  string        `json:"space_guid"`
    49  		} `json:"entity"`
    50  	}
    51  	if err := json.Unmarshal(data, &ccRoute); err != nil {
    52  		return err
    53  	}
    54  
    55  	route.GUID = ccRoute.Metadata.GUID
    56  	route.Host = ccRoute.Entity.Host
    57  	route.Path = ccRoute.Entity.Path
    58  	route.Port = ccRoute.Entity.Port
    59  	route.DomainGUID = ccRoute.Entity.DomainGUID
    60  	route.SpaceGUID = ccRoute.Entity.SpaceGUID
    61  	return nil
    62  }
    63  
    64  // UpdateRouteApplication creates a link between the route and application.
    65  func (client *Client) UpdateRouteApplication(routeGUID string, appGUID string) (Route, Warnings, error) {
    66  	request, err := client.newHTTPRequest(requestOptions{
    67  		RequestName: internal.PutRouteAppRequest,
    68  		URIParams: map[string]string{
    69  			"app_guid":   appGUID,
    70  			"route_guid": routeGUID,
    71  		},
    72  	})
    73  	if err != nil {
    74  		return Route{}, nil, err
    75  	}
    76  
    77  	var route Route
    78  	response := cloudcontroller.Response{
    79  		Result: &route,
    80  	}
    81  	err = client.connection.Make(request, &response)
    82  
    83  	return route, response.Warnings, err
    84  }
    85  
    86  // DeleteRouteApplication removes the link between the route and application.
    87  func (client *Client) DeleteRouteApplication(routeGUID string, appGUID string) (Warnings, error) {
    88  	request, err := client.newHTTPRequest(requestOptions{
    89  		RequestName: internal.DeleteRouteAppRequest,
    90  		URIParams: map[string]string{
    91  			"app_guid":   appGUID,
    92  			"route_guid": routeGUID,
    93  		},
    94  	})
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	var response cloudcontroller.Response
   100  	err = client.connection.Make(request, &response)
   101  	return response.Warnings, err
   102  }
   103  
   104  // CreateRoute creates the route with the given properties; SpaceGUID and
   105  // DomainGUID are required Route properties. Additional configuration rules:
   106  // - generatePort = true to generate a random port on the cloud controller.
   107  // - generatePort takes precedence over the provided port. Setting the port and
   108  // generatePort only works with CC API 2.53.0 or higher and when TCP router
   109  // groups are enabled.
   110  func (client *Client) CreateRoute(route Route, generatePort bool) (Route, Warnings, error) {
   111  	body, err := json.Marshal(route)
   112  	if err != nil {
   113  		return Route{}, nil, err
   114  	}
   115  
   116  	request, err := client.newHTTPRequest(requestOptions{
   117  		RequestName: internal.PostRouteRequest,
   118  		Body:        bytes.NewReader(body),
   119  	})
   120  	if err != nil {
   121  		return Route{}, nil, err
   122  	}
   123  
   124  	if generatePort {
   125  		query := url.Values{}
   126  		query.Add("generate_port", "true")
   127  		request.URL.RawQuery = query.Encode()
   128  	}
   129  
   130  	var updatedRoute Route
   131  	response := cloudcontroller.Response{
   132  		Result: &updatedRoute,
   133  	}
   134  
   135  	err = client.connection.Make(request, &response)
   136  	return updatedRoute, response.Warnings, err
   137  }
   138  
   139  // GetApplicationRoutes returns a list of Routes associated with the provided
   140  // Application GUID, and filtered by the provided filters.
   141  func (client *Client) GetApplicationRoutes(appGUID string, filters ...Filter) ([]Route, Warnings, error) {
   142  	request, err := client.newHTTPRequest(requestOptions{
   143  		RequestName: internal.GetAppRoutesRequest,
   144  		URIParams:   map[string]string{"app_guid": appGUID},
   145  		Query:       ConvertFilterParameters(filters),
   146  	})
   147  	if err != nil {
   148  		return nil, nil, err
   149  	}
   150  
   151  	var fullRoutesList []Route
   152  	warnings, err := client.paginate(request, Route{}, func(item interface{}) error {
   153  		if route, ok := item.(Route); ok {
   154  			fullRoutesList = append(fullRoutesList, route)
   155  		} else {
   156  			return ccerror.UnknownObjectInListError{
   157  				Expected:   Route{},
   158  				Unexpected: item,
   159  			}
   160  		}
   161  		return nil
   162  	})
   163  
   164  	return fullRoutesList, warnings, err
   165  }
   166  
   167  // GetSpaceRoutes returns a list of Routes associated with the provided Space
   168  // GUID, and filtered by the provided filters.
   169  func (client *Client) GetSpaceRoutes(spaceGUID string, filters ...Filter) ([]Route, Warnings, error) {
   170  	request, err := client.newHTTPRequest(requestOptions{
   171  		RequestName: internal.GetSpaceRoutesRequest,
   172  		URIParams:   map[string]string{"space_guid": spaceGUID},
   173  		Query:       ConvertFilterParameters(filters),
   174  	})
   175  	if err != nil {
   176  		return nil, nil, err
   177  	}
   178  
   179  	var fullRoutesList []Route
   180  	warnings, err := client.paginate(request, Route{}, func(item interface{}) error {
   181  		if route, ok := item.(Route); ok {
   182  			fullRoutesList = append(fullRoutesList, route)
   183  		} else {
   184  			return ccerror.UnknownObjectInListError{
   185  				Expected:   Route{},
   186  				Unexpected: item,
   187  			}
   188  		}
   189  		return nil
   190  	})
   191  
   192  	return fullRoutesList, warnings, err
   193  }
   194  
   195  // GetRoutes returns a list of Routes based off of the provided filters.
   196  func (client *Client) GetRoutes(filters ...Filter) ([]Route, Warnings, error) {
   197  	request, err := client.newHTTPRequest(requestOptions{
   198  		RequestName: internal.GetRoutesRequest,
   199  		Query:       ConvertFilterParameters(filters),
   200  	})
   201  	if err != nil {
   202  		return nil, nil, err
   203  	}
   204  
   205  	var fullRoutesList []Route
   206  	warnings, err := client.paginate(request, Route{}, func(item interface{}) error {
   207  		if route, ok := item.(Route); ok {
   208  			fullRoutesList = append(fullRoutesList, route)
   209  		} else {
   210  			return ccerror.UnknownObjectInListError{
   211  				Expected:   Route{},
   212  				Unexpected: item,
   213  			}
   214  		}
   215  		return nil
   216  	})
   217  
   218  	return fullRoutesList, warnings, err
   219  }
   220  
   221  // DeleteRoute deletes the Route associated with the provided Route GUID.
   222  func (client *Client) DeleteRoute(routeGUID string) (Warnings, error) {
   223  	request, err := client.newHTTPRequest(requestOptions{
   224  		RequestName: internal.DeleteRouteRequest,
   225  		URIParams:   map[string]string{"route_guid": routeGUID},
   226  	})
   227  	if err != nil {
   228  		return nil, err
   229  	}
   230  
   231  	var response cloudcontroller.Response
   232  	err = client.connection.Make(request, &response)
   233  	return response.Warnings, err
   234  }
   235  
   236  // CheckRoute returns true if the route exists in the CF instance. DomainGUID
   237  // is required for check. This call will only work for CC API 2.55 or higher.
   238  func (client *Client) CheckRoute(route Route) (bool, Warnings, error) {
   239  	currentVersion := client.APIVersion()
   240  	switch {
   241  	case cloudcontroller.MinimumAPIVersionCheck(currentVersion, ccversion.MinVersionNoHostInReservedRouteEndpoint) == nil:
   242  		return client.checkRoute(route)
   243  	case cloudcontroller.MinimumAPIVersionCheck(currentVersion, ccversion.MinVersionHTTPRoutePath) == nil:
   244  		return client.checkRouteDeprecated(route.DomainGUID, route.Host, route.Path)
   245  	default:
   246  		return client.checkRouteDeprecated(route.DomainGUID, route.Host, "")
   247  	}
   248  }
   249  
   250  func (client *Client) checkRoute(route Route) (bool, Warnings, error) {
   251  	request, err := client.newHTTPRequest(requestOptions{
   252  		RequestName: internal.GetRouteReservedRequest,
   253  		URIParams:   map[string]string{"domain_guid": route.DomainGUID},
   254  	})
   255  	if err != nil {
   256  		return false, nil, err
   257  	}
   258  
   259  	queryParams := url.Values{}
   260  	if route.Host != "" {
   261  		queryParams.Add("host", route.Host)
   262  	}
   263  	if route.Path != "" {
   264  		queryParams.Add("path", route.Path)
   265  	}
   266  	if route.Port.IsSet {
   267  		queryParams.Add("port", fmt.Sprint(route.Port.Value))
   268  	}
   269  	request.URL.RawQuery = queryParams.Encode()
   270  
   271  	var response cloudcontroller.Response
   272  	err = client.connection.Make(request, &response)
   273  	if _, ok := err.(ccerror.ResourceNotFoundError); ok {
   274  		return false, response.Warnings, nil
   275  	}
   276  
   277  	return response.HTTPResponse.StatusCode == http.StatusNoContent, response.Warnings, err
   278  }
   279  
   280  func (client *Client) checkRouteDeprecated(domainGUID string, host string, path string) (bool, Warnings, error) {
   281  	request, err := client.newHTTPRequest(requestOptions{
   282  		RequestName: internal.GetRouteReservedDeprecatedRequest,
   283  		URIParams:   map[string]string{"domain_guid": domainGUID, "host": host},
   284  	})
   285  	if err != nil {
   286  		return false, nil, err
   287  	}
   288  
   289  	queryParams := url.Values{}
   290  	if path != "" {
   291  		queryParams.Add("path", path)
   292  	}
   293  	request.URL.RawQuery = queryParams.Encode()
   294  
   295  	var response cloudcontroller.Response
   296  	err = client.connection.Make(request, &response)
   297  	if _, ok := err.(ccerror.ResourceNotFoundError); ok {
   298  		return false, response.Warnings, nil
   299  	}
   300  
   301  	return response.HTTPResponse.StatusCode == http.StatusNoContent, response.Warnings, err
   302  }