github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+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 err := cloudcontroller.DecodeJSON(data, &ccRoute) 52 if err != nil { 53 return err 54 } 55 56 route.GUID = ccRoute.Metadata.GUID 57 route.Host = ccRoute.Entity.Host 58 route.Path = ccRoute.Entity.Path 59 route.Port = ccRoute.Entity.Port 60 route.DomainGUID = ccRoute.Entity.DomainGUID 61 route.SpaceGUID = ccRoute.Entity.SpaceGUID 62 return nil 63 } 64 65 // CreateRoute creates the route with the given properties; SpaceGUID and 66 // DomainGUID are required Route properties. Additional configuration rules: 67 // - generatePort = true to generate a random port on the cloud controller. 68 // - generatePort takes precedence over the provided port. Setting the port and 69 // generatePort only works with CC API 2.53.0 or higher and when TCP router 70 // groups are enabled. 71 func (client *Client) CreateRoute(route Route, generatePort bool) (Route, Warnings, error) { 72 body, err := json.Marshal(route) 73 if err != nil { 74 return Route{}, nil, err 75 } 76 77 request, err := client.newHTTPRequest(requestOptions{ 78 RequestName: internal.PostRouteRequest, 79 Body: bytes.NewReader(body), 80 }) 81 if err != nil { 82 return Route{}, nil, err 83 } 84 85 if generatePort { 86 query := url.Values{} 87 query.Add("generate_port", "true") 88 request.URL.RawQuery = query.Encode() 89 } 90 91 var updatedRoute Route 92 response := cloudcontroller.Response{ 93 Result: &updatedRoute, 94 } 95 96 err = client.connection.Make(request, &response) 97 return updatedRoute, response.Warnings, err 98 } 99 100 // DeleteRoute deletes the Route associated with the provided Route GUID. 101 func (client *Client) DeleteRoute(routeGUID string) (Warnings, error) { 102 request, err := client.newHTTPRequest(requestOptions{ 103 RequestName: internal.DeleteRouteRequest, 104 URIParams: map[string]string{"route_guid": routeGUID}, 105 }) 106 if err != nil { 107 return nil, err 108 } 109 110 var response cloudcontroller.Response 111 err = client.connection.Make(request, &response) 112 return response.Warnings, err 113 } 114 115 // DeleteRouteApplication removes the link between the route and application. 116 func (client *Client) DeleteRouteApplication(routeGUID string, appGUID string) (Warnings, error) { 117 request, err := client.newHTTPRequest(requestOptions{ 118 RequestName: internal.DeleteRouteAppRequest, 119 URIParams: map[string]string{ 120 "app_guid": appGUID, 121 "route_guid": routeGUID, 122 }, 123 }) 124 if err != nil { 125 return nil, err 126 } 127 128 var response cloudcontroller.Response 129 err = client.connection.Make(request, &response) 130 return response.Warnings, err 131 } 132 133 // DoesRouteExist returns true if the route exists in the CF instance. DomainGUID 134 // is required for check. This call will only work for CC API 2.55 or higher. 135 func (client *Client) DoesRouteExist(route Route) (bool, Warnings, error) { 136 currentVersion := client.APIVersion() 137 switch { 138 case cloudcontroller.MinimumAPIVersionCheck(currentVersion, ccversion.MinVersionNoHostInReservedRouteEndpoint) == nil: 139 return client.checkRoute(route) 140 case cloudcontroller.MinimumAPIVersionCheck(currentVersion, ccversion.MinVersionHTTPRoutePath) == nil: 141 return client.checkRouteDeprecated(route.DomainGUID, route.Host, route.Path) 142 default: 143 return client.checkRouteDeprecated(route.DomainGUID, route.Host, "") 144 } 145 } 146 147 // GetApplicationRoutes returns a list of Routes associated with the provided 148 // Application GUID, and filtered by the provided filters. 149 func (client *Client) GetApplicationRoutes(appGUID string, filters ...Filter) ([]Route, Warnings, error) { 150 request, err := client.newHTTPRequest(requestOptions{ 151 RequestName: internal.GetAppRoutesRequest, 152 URIParams: map[string]string{"app_guid": appGUID}, 153 Query: ConvertFilterParameters(filters), 154 }) 155 if err != nil { 156 return nil, nil, err 157 } 158 159 var fullRoutesList []Route 160 warnings, err := client.paginate(request, Route{}, func(item interface{}) error { 161 if route, ok := item.(Route); ok { 162 fullRoutesList = append(fullRoutesList, route) 163 } else { 164 return ccerror.UnknownObjectInListError{ 165 Expected: Route{}, 166 Unexpected: item, 167 } 168 } 169 return nil 170 }) 171 172 return fullRoutesList, warnings, err 173 } 174 175 // GetRoute returns a route with the provided guid. 176 func (client *Client) GetRoute(guid string) (Route, Warnings, error) { 177 request, err := client.newHTTPRequest(requestOptions{ 178 RequestName: internal.GetRouteRequest, 179 URIParams: Params{"route_guid": guid}, 180 }) 181 if err != nil { 182 return Route{}, nil, err 183 } 184 185 var route Route 186 response := cloudcontroller.Response{ 187 Result: &route, 188 } 189 190 err = client.connection.Make(request, &response) 191 return route, response.Warnings, err 192 } 193 194 // GetRoutes returns a list of Routes based off of the provided filters. 195 func (client *Client) GetRoutes(filters ...Filter) ([]Route, Warnings, error) { 196 request, err := client.newHTTPRequest(requestOptions{ 197 RequestName: internal.GetRoutesRequest, 198 Query: ConvertFilterParameters(filters), 199 }) 200 if err != nil { 201 return nil, nil, err 202 } 203 204 var fullRoutesList []Route 205 warnings, err := client.paginate(request, Route{}, func(item interface{}) error { 206 if route, ok := item.(Route); ok { 207 fullRoutesList = append(fullRoutesList, route) 208 } else { 209 return ccerror.UnknownObjectInListError{ 210 Expected: Route{}, 211 Unexpected: item, 212 } 213 } 214 return nil 215 }) 216 217 return fullRoutesList, warnings, err 218 } 219 220 // GetSpaceRoutes returns a list of Routes associated with the provided Space 221 // GUID, and filtered by the provided filters. 222 func (client *Client) GetSpaceRoutes(spaceGUID string, filters ...Filter) ([]Route, Warnings, error) { 223 request, err := client.newHTTPRequest(requestOptions{ 224 RequestName: internal.GetSpaceRoutesRequest, 225 URIParams: map[string]string{"space_guid": spaceGUID}, 226 Query: ConvertFilterParameters(filters), 227 }) 228 if err != nil { 229 return nil, nil, err 230 } 231 232 var fullRoutesList []Route 233 warnings, err := client.paginate(request, Route{}, func(item interface{}) error { 234 if route, ok := item.(Route); ok { 235 fullRoutesList = append(fullRoutesList, route) 236 } else { 237 return ccerror.UnknownObjectInListError{ 238 Expected: Route{}, 239 Unexpected: item, 240 } 241 } 242 return nil 243 }) 244 245 return fullRoutesList, warnings, err 246 } 247 248 // UpdateRouteApplication creates a link between the route and application. 249 func (client *Client) UpdateRouteApplication(routeGUID string, appGUID string) (Route, Warnings, error) { 250 request, err := client.newHTTPRequest(requestOptions{ 251 RequestName: internal.PutRouteAppRequest, 252 URIParams: map[string]string{ 253 "app_guid": appGUID, 254 "route_guid": routeGUID, 255 }, 256 }) 257 if err != nil { 258 return Route{}, nil, err 259 } 260 261 var route Route 262 response := cloudcontroller.Response{ 263 Result: &route, 264 } 265 err = client.connection.Make(request, &response) 266 267 return route, response.Warnings, err 268 } 269 270 func (client *Client) checkRoute(route Route) (bool, Warnings, error) { 271 request, err := client.newHTTPRequest(requestOptions{ 272 RequestName: internal.GetRouteReservedRequest, 273 URIParams: map[string]string{"domain_guid": route.DomainGUID}, 274 }) 275 if err != nil { 276 return false, nil, err 277 } 278 279 queryParams := url.Values{} 280 if route.Host != "" { 281 queryParams.Add("host", route.Host) 282 } 283 if route.Path != "" { 284 queryParams.Add("path", route.Path) 285 } 286 if route.Port.IsSet { 287 queryParams.Add("port", fmt.Sprint(route.Port.Value)) 288 } 289 request.URL.RawQuery = queryParams.Encode() 290 291 var response cloudcontroller.Response 292 err = client.connection.Make(request, &response) 293 if _, ok := err.(ccerror.ResourceNotFoundError); ok { 294 return false, response.Warnings, nil 295 } 296 297 return response.HTTPResponse.StatusCode == http.StatusNoContent, response.Warnings, err 298 } 299 300 func (client *Client) checkRouteDeprecated(domainGUID string, host string, path string) (bool, Warnings, error) { 301 request, err := client.newHTTPRequest(requestOptions{ 302 RequestName: internal.GetRouteReservedDeprecatedRequest, 303 URIParams: map[string]string{"domain_guid": domainGUID, "host": host}, 304 }) 305 if err != nil { 306 return false, nil, err 307 } 308 309 queryParams := url.Values{} 310 if path != "" { 311 queryParams.Add("path", path) 312 } 313 request.URL.RawQuery = queryParams.Encode() 314 315 var response cloudcontroller.Response 316 err = client.connection.Make(request, &response) 317 if _, ok := err.(ccerror.ResourceNotFoundError); ok { 318 return false, response.Warnings, nil 319 } 320 321 return response.HTTPResponse.StatusCode == http.StatusNoContent, response.Warnings, err 322 }