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