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 }