From 84288875833b8d2db20efa8ca5c3aac3853707f5 Mon Sep 17 00:00:00 2001 From: Maurice Brinkmann Date: Fri, 17 Oct 2025 01:38:49 +0200 Subject: [PATCH] Allow setting the route destination port via the CF CLI map-route command using a new app-port parameter --- .gitignore | 1 + actor/v7action/cloud_controller_client.go | 2 +- actor/v7action/route.go | 19 ++++- actor/v7action/route_test.go | 7 +- .../fake_cloud_controller_client.go | 18 ++--- actor/v7pushaction/v7_actor.go | 2 +- .../v7pushactionfakes/fake_v7actor.go | 18 ++--- api/cloudcontroller/ccv3/route.go | 6 +- api/cloudcontroller/ccv3/route_test.go | 71 +++++++++++++------ command/v7/actor.go | 2 +- command/v7/map_route_command.go | 6 +- command/v7/map_route_command_test.go | 27 +++++-- command/v7/routes_command.go | 2 + command/v7/routes_command_test.go | 2 +- command/v7/v7fakes/fake_actor.go | 18 ++--- .../v7/isolated/map_route_command_test.go | 6 +- .../v7/isolated/routes_command_test.go | 26 +++---- 17 files changed, 157 insertions(+), 76 deletions(-) diff --git a/.gitignore b/.gitignore index a35518518ec..12c343c390c 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,4 @@ integration/assets/test_plugin/test_plugin .vscode .secrets .vars +.patch diff --git a/actor/v7action/cloud_controller_client.go b/actor/v7action/cloud_controller_client.go index 0acf7b7168a..bc754c0976d 100644 --- a/actor/v7action/cloud_controller_client.go +++ b/actor/v7action/cloud_controller_client.go @@ -142,7 +142,7 @@ type CloudControllerClient interface { GetUser(userGUID string) (resources.User, ccv3.Warnings, error) GetUsers(query ...ccv3.Query) ([]resources.User, ccv3.Warnings, error) MakeRequestSendReceiveRaw(Method string, URL string, headers http.Header, requestBody []byte) ([]byte, *http.Response, error) - MapRoute(routeGUID string, appGUID string, destinationProtocol string) (ccv3.Warnings, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string, destinationPort int) (ccv3.Warnings, error) MoveRoute(routeGUID string, spaceGUID string) (ccv3.Warnings, error) PollJob(jobURL ccv3.JobURL) (ccv3.Warnings, error) PollJobForState(jobURL ccv3.JobURL, state constant.JobState) (ccv3.Warnings, error) diff --git a/actor/v7action/route.go b/actor/v7action/route.go index 8ef0a4479e3..702649a018a 100644 --- a/actor/v7action/route.go +++ b/actor/v7action/route.go @@ -21,6 +21,7 @@ type RouteSummary struct { resources.Route AppNames []string AppProtocols []string + AppPorts []string DomainName string SpaceName string ServiceInstanceName string @@ -279,9 +280,13 @@ func (actor Actor) GetRouteSummaries(routes []resources.Route) ([]RouteSummary, var appNames []string protocolSet := map[string]bool{} + portSet := map[int]bool{} for _, destination := range route.Destinations { appNames = append(appNames, appNamesByGUID[destination.App.GUID]) protocolSet[destination.Protocol] = true + if destination.Port > 0 { + portSet[destination.Port] = true + } } var appProtocols []string @@ -293,10 +298,20 @@ func (actor Actor) GetRouteSummaries(routes []resources.Route) ([]RouteSummary, sort.Strings(appProtocols) } + var appPorts []string + if len(portSet) > 0 { + appPorts = make([]string, 0, len(portSet)) + for key := range portSet { + appPorts = append(appPorts, strconv.Itoa(key)) + } + sort.Strings(appPorts) + } + routeSummaries = append(routeSummaries, RouteSummary{ Route: route, AppNames: appNames, AppProtocols: appProtocols, + AppPorts: appPorts, SpaceName: spaceNamesByGUID[route.SpaceGUID], DomainName: getDomainName(route.URL, route.Host, route.Path, route.Port), ServiceInstanceName: serviceInstanceNameByRouteGUID[route.GUID], @@ -397,8 +412,8 @@ func (actor Actor) GetRouteByAttributes(domain resources.Domain, hostname string return routes[0], Warnings(ccWarnings), nil } -func (actor Actor) MapRoute(routeGUID string, appGUID string, destinationProtocol string) (Warnings, error) { - warnings, err := actor.CloudControllerClient.MapRoute(routeGUID, appGUID, destinationProtocol) +func (actor Actor) MapRoute(routeGUID string, appGUID string, destinationProtocol string, destinationPort int) (Warnings, error) { + warnings, err := actor.CloudControllerClient.MapRoute(routeGUID, appGUID, destinationProtocol, destinationPort) return Warnings(warnings), err } diff --git a/actor/v7action/route_test.go b/actor/v7action/route_test.go index 55bd75fa11f..bb2b93607e6 100644 --- a/actor/v7action/route_test.go +++ b/actor/v7action/route_test.go @@ -1581,19 +1581,21 @@ var _ = Describe("Route Actions", func() { routeGUID string appGUID string destinationProtocol string + destinationPort int executeErr error warnings Warnings ) JustBeforeEach(func() { - warnings, executeErr = actor.MapRoute(routeGUID, appGUID, destinationProtocol) + warnings, executeErr = actor.MapRoute(routeGUID, appGUID, destinationProtocol, destinationPort) }) BeforeEach(func() { routeGUID = "route-guid" appGUID = "app-guid" destinationProtocol = "http2" + destinationPort = 8080 }) When("the cloud controller client errors", func() { @@ -1613,10 +1615,11 @@ var _ = Describe("Route Actions", func() { }) It("calls the cloud controller client with the right arguments", func() { - actualRouteGUID, actualAppGUID, actualDestinationProtocol := fakeCloudControllerClient.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualDestinationProtocol, actualDestinationPort := fakeCloudControllerClient.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) Expect(actualDestinationProtocol).To(Equal("http2")) + Expect(actualDestinationPort).To(Equal(8080)) }) It("returns the error and warnings", func() { diff --git a/actor/v7action/v7actionfakes/fake_cloud_controller_client.go b/actor/v7action/v7actionfakes/fake_cloud_controller_client.go index 0add7dcd938..2cc272f1ca3 100644 --- a/actor/v7action/v7actionfakes/fake_cloud_controller_client.go +++ b/actor/v7action/v7actionfakes/fake_cloud_controller_client.go @@ -1991,12 +1991,13 @@ type FakeCloudControllerClient struct { result2 *http.Response result3 error } - MapRouteStub func(string, string, string) (ccv3.Warnings, error) + MapRouteStub func(string, string, string, int) (ccv3.Warnings, error) mapRouteMutex sync.RWMutex mapRouteArgsForCall []struct { arg1 string arg2 string arg3 string + arg4 int } mapRouteReturns struct { result1 ccv3.Warnings @@ -11542,20 +11543,21 @@ func (fake *FakeCloudControllerClient) MakeRequestSendReceiveRawReturnsOnCall(i }{result1, result2, result3} } -func (fake *FakeCloudControllerClient) MapRoute(arg1 string, arg2 string, arg3 string) (ccv3.Warnings, error) { +func (fake *FakeCloudControllerClient) MapRoute(arg1 string, arg2 string, arg3 string, arg4 int) (ccv3.Warnings, error) { fake.mapRouteMutex.Lock() ret, specificReturn := fake.mapRouteReturnsOnCall[len(fake.mapRouteArgsForCall)] fake.mapRouteArgsForCall = append(fake.mapRouteArgsForCall, struct { arg1 string arg2 string arg3 string - }{arg1, arg2, arg3}) + arg4 int + }{arg1, arg2, arg3, arg4}) stub := fake.MapRouteStub fakeReturns := fake.mapRouteReturns - fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3}) + fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3, arg4}) fake.mapRouteMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3) + return stub(arg1, arg2, arg3, arg4) } if specificReturn { return ret.result1, ret.result2 @@ -11569,17 +11571,17 @@ func (fake *FakeCloudControllerClient) MapRouteCallCount() int { return len(fake.mapRouteArgsForCall) } -func (fake *FakeCloudControllerClient) MapRouteCalls(stub func(string, string, string) (ccv3.Warnings, error)) { +func (fake *FakeCloudControllerClient) MapRouteCalls(stub func(string, string, string, int) (ccv3.Warnings, error)) { fake.mapRouteMutex.Lock() defer fake.mapRouteMutex.Unlock() fake.MapRouteStub = stub } -func (fake *FakeCloudControllerClient) MapRouteArgsForCall(i int) (string, string, string) { +func (fake *FakeCloudControllerClient) MapRouteArgsForCall(i int) (string, string, string, int) { fake.mapRouteMutex.RLock() defer fake.mapRouteMutex.RUnlock() argsForCall := fake.mapRouteArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 } func (fake *FakeCloudControllerClient) MapRouteReturns(result1 ccv3.Warnings, result2 error) { diff --git a/actor/v7pushaction/v7_actor.go b/actor/v7pushaction/v7_actor.go index 9f0ebd5a34b..2aa859afb5a 100644 --- a/actor/v7pushaction/v7_actor.go +++ b/actor/v7pushaction/v7_actor.go @@ -25,7 +25,7 @@ type V7Actor interface { GetDomain(domainGUID string) (resources.Domain, v7action.Warnings, error) GetRouteByAttributes(domain resources.Domain, hostname, path string, port int) (resources.Route, v7action.Warnings, error) GetRouteDestinationByAppGUID(route resources.Route, appGUID string) (resources.RouteDestination, error) - MapRoute(routeGUID string, appGUID string, destinationProtocol string) (v7action.Warnings, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string, destinationPort int) (v7action.Warnings, error) PollBuild(buildGUID string, appName string) (resources.Droplet, v7action.Warnings, error) PollPackage(pkg resources.Package) (resources.Package, v7action.Warnings, error) PollStart(app resources.Application, noWait bool, handleProcessStats func(string)) (v7action.Warnings, error) diff --git a/actor/v7pushaction/v7pushactionfakes/fake_v7actor.go b/actor/v7pushaction/v7pushactionfakes/fake_v7actor.go index ce878c727ea..c99f7a2f3e5 100644 --- a/actor/v7pushaction/v7pushactionfakes/fake_v7actor.go +++ b/actor/v7pushaction/v7pushactionfakes/fake_v7actor.go @@ -234,12 +234,13 @@ type FakeV7Actor struct { result1 resources.RouteDestination result2 error } - MapRouteStub func(string, string, string) (v7action.Warnings, error) + MapRouteStub func(string, string, string, int) (v7action.Warnings, error) mapRouteMutex sync.RWMutex mapRouteArgsForCall []struct { arg1 string arg2 string arg3 string + arg4 int } mapRouteReturns struct { result1 v7action.Warnings @@ -1476,20 +1477,21 @@ func (fake *FakeV7Actor) GetRouteDestinationByAppGUIDReturnsOnCall(i int, result }{result1, result2} } -func (fake *FakeV7Actor) MapRoute(arg1 string, arg2 string, arg3 string) (v7action.Warnings, error) { +func (fake *FakeV7Actor) MapRoute(arg1 string, arg2 string, arg3 string, arg4 int) (v7action.Warnings, error) { fake.mapRouteMutex.Lock() ret, specificReturn := fake.mapRouteReturnsOnCall[len(fake.mapRouteArgsForCall)] fake.mapRouteArgsForCall = append(fake.mapRouteArgsForCall, struct { arg1 string arg2 string arg3 string - }{arg1, arg2, arg3}) + arg4 int + }{arg1, arg2, arg3, arg4}) stub := fake.MapRouteStub fakeReturns := fake.mapRouteReturns - fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3}) + fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3, arg4}) fake.mapRouteMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3) + return stub(arg1, arg2, arg3, arg4) } if specificReturn { return ret.result1, ret.result2 @@ -1503,17 +1505,17 @@ func (fake *FakeV7Actor) MapRouteCallCount() int { return len(fake.mapRouteArgsForCall) } -func (fake *FakeV7Actor) MapRouteCalls(stub func(string, string, string) (v7action.Warnings, error)) { +func (fake *FakeV7Actor) MapRouteCalls(stub func(string, string, string, int) (v7action.Warnings, error)) { fake.mapRouteMutex.Lock() defer fake.mapRouteMutex.Unlock() fake.MapRouteStub = stub } -func (fake *FakeV7Actor) MapRouteArgsForCall(i int) (string, string, string) { +func (fake *FakeV7Actor) MapRouteArgsForCall(i int) (string, string, string, int) { fake.mapRouteMutex.RLock() defer fake.mapRouteMutex.RUnlock() argsForCall := fake.mapRouteArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 } func (fake *FakeV7Actor) MapRouteReturns(result1 v7action.Warnings, result2 error) { diff --git a/api/cloudcontroller/ccv3/route.go b/api/cloudcontroller/ccv3/route.go index f42763956fa..8963600d5aa 100644 --- a/api/cloudcontroller/ccv3/route.go +++ b/api/cloudcontroller/ccv3/route.go @@ -100,7 +100,7 @@ func (client Client) UpdateRoute(routeGUID string, options map[string]*string) ( } -func (client Client) MapRoute(routeGUID string, appGUID string, destinationProtocol string) (Warnings, error) { +func (client Client) MapRoute(routeGUID string, appGUID string, destinationProtocol string, destinationPort int) (Warnings, error) { type destinationProcess struct { ProcessType string `json:"process_type"` } @@ -112,6 +112,7 @@ func (client Client) MapRoute(routeGUID string, appGUID string, destinationProto type destination struct { App destinationApp `json:"app"` Protocol string `json:"protocol,omitempty"` + Port int `json:"port,omitempty"` } type body struct { @@ -128,6 +129,9 @@ func (client Client) MapRoute(routeGUID string, appGUID string, destinationProto if destinationProtocol != "" { requestBody.Destinations[0].Protocol = destinationProtocol } + if destinationPort != 0 { + requestBody.Destinations[0].Port = destinationPort + } _, warnings, err := client.MakeRequest(RequestParams{ RequestName: internal.MapRouteRequest, diff --git a/api/cloudcontroller/ccv3/route_test.go b/api/cloudcontroller/ccv3/route_test.go index a0a6dd92d6b..f81e011a441 100644 --- a/api/cloudcontroller/ccv3/route_test.go +++ b/api/cloudcontroller/ccv3/route_test.go @@ -577,6 +577,7 @@ var _ = Describe("Route", func() { routeGUID = "route-guid" appGUID = "app-guid" destinationProtocol string + destinationPort int expectedBody string warnings Warnings executeErr error @@ -591,24 +592,26 @@ var _ = Describe("Route", func() { RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), ), ) - warnings, executeErr = client.MapRoute(routeGUID, appGUID, destinationProtocol) + warnings, executeErr = client.MapRoute(routeGUID, appGUID, destinationProtocol, destinationPort) }) When("the request is successful", func() { BeforeEach(func() { destinationProtocol = "http2" + destinationPort = 8080 expectedBody = fmt.Sprintf(` - { - "destinations": [ - { - "app": { - "guid": "%s" - }, - "protocol": "%s" - } - ] - } - `, appGUID, destinationProtocol) + { + "destinations": [ + { + "app": { + "guid": "%s" + }, + "protocol": "%s", + "port": %d + } + ] + } + `, appGUID, destinationProtocol, destinationPort) }) It("returns the warnings and no error", func() { @@ -620,17 +623,18 @@ var _ = Describe("Route", func() { Context("when destination protocol is not provided", func() { BeforeEach(func() { destinationProtocol = "" + destinationPort = 0 expectedBody = fmt.Sprintf(` - { - "destinations": [ - { - "app": { - "guid": "%s" - } - } - ] - } - `, appGUID) + { + "destinations": [ + { + "app": { + "guid": "%s" + } + } + ] + } + `, appGUID) }) It("does not include it in the request", func() { @@ -638,6 +642,29 @@ var _ = Describe("Route", func() { }) }) + Context("when destination port is provided without protocol", func() { + BeforeEach(func() { + destinationProtocol = "" + destinationPort = 9090 + expectedBody = fmt.Sprintf(` + { + "destinations": [ + { + "app": { + "guid": "%s" + }, + "port": %d + } + ] + } + `, appGUID, destinationPort) + }) + + It("includes the port in the request", func() { + Expect(executeErr).ToNot(HaveOccurred()) + }) + }) + When("the cloud controller returns errors and warnings", func() { BeforeEach(func() { response := `{ diff --git a/command/v7/actor.go b/command/v7/actor.go index 872dd8a8628..a182669f8cf 100644 --- a/command/v7/actor.go +++ b/command/v7/actor.go @@ -186,7 +186,7 @@ type Actor interface { GetUser(username, origin string) (resources.User, error) ListServiceAppBindings(params v7action.ListServiceAppBindingParams) ([]resources.ServiceCredentialBinding, v7action.Warnings, error) MakeCurlRequest(httpMethod string, path string, customHeaders []string, httpData string, failOnHTTPError bool) ([]byte, *http.Response, error) - MapRoute(routeGUID string, appGUID string, destinationProtocol string) (v7action.Warnings, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string, destinationPort int) (v7action.Warnings, error) Marketplace(filter v7action.MarketplaceFilter) ([]v7action.ServiceOfferingWithPlans, v7action.Warnings, error) MoveRoute(routeGUID string, spaceGUID string) (v7action.Warnings, error) ParseAccessToken(accessToken string) (jwt.JWT, error) diff --git a/command/v7/map_route_command.go b/command/v7/map_route_command.go index 1c572ed933f..f7fdcb843c9 100644 --- a/command/v7/map_route_command.go +++ b/command/v7/map_route_command.go @@ -16,6 +16,7 @@ type MapRouteCommand struct { Path flag.V7RoutePath `long:"path" description:"Path for the HTTP route"` Port int `long:"port" description:"Port for the TCP route (default: random port)"` AppProtocol string `long:"app-protocol" description:"[Beta flag, subject to change] Protocol for the route destination (default: http1). Only applied to HTTP routes"` + AppPort int `long:"app-port" description:"[Beta flag, subject to change] App port for the route destination (default: 8080). Only applied to HTTP routes"` Options []string `long:"option" short:"o" description:"Set the value of a per-route option"` relatedCommands interface{} `related_commands:"create-route, update-route, routes, unmap-route"` } @@ -23,7 +24,7 @@ type MapRouteCommand struct { func (cmd MapRouteCommand) Usage() string { return ` Map an HTTP route: - CF_NAME map-route APP_NAME DOMAIN [--hostname HOSTNAME] [--path PATH] [--app-protocol PROTOCOL] [--option OPTION=VALUE] + CF_NAME map-route APP_NAME DOMAIN [--hostname HOSTNAME] [--path PATH] [--app-protocol PROTOCOL] [--app-port PORT] [--option OPTION=VALUE] Map a TCP route: CF_NAME map-route APP_NAME DOMAIN [--port PORT] [--option OPTION=VALUE]` @@ -36,6 +37,7 @@ CF_NAME map-route my-app example.com --hostname myhost CF_NAME map-route my-app example.com --hostname myhost -o loadbalancing=least-connection # myhost.example.com with a per-route option CF_NAME map-route my-app example.com --hostname myhost --path foo # myhost.example.com/foo CF_NAME map-route my-app example.com --hostname myhost --app-protocol http2 # myhost.example.com +CF_NAME map-route my-app example.com --hostname myhost --app-port 8090 # myhost.example.com CF_NAME map-route my-app example.com --port 5000 # example.com:5000` } @@ -148,7 +150,7 @@ func (cmd MapRouteCommand) Execute(args []string) error { return nil } - warnings, err = cmd.Actor.MapRoute(route.GUID, app.GUID, cmd.AppProtocol) + warnings, err = cmd.Actor.MapRoute(route.GUID, app.GUID, cmd.AppProtocol, cmd.AppPort) cmd.UI.DisplayWarnings(warnings) if err != nil { return err diff --git a/command/v7/map_route_command_test.go b/command/v7/map_route_command_test.go index dd1c62ecf21..ad2d236145b 100644 --- a/command/v7/map_route_command_test.go +++ b/command/v7/map_route_command_test.go @@ -448,10 +448,11 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID, actualAppProtocol := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualAppProtocol, actualAppPort := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) Expect(actualAppProtocol).To(Equal("http2")) + Expect(actualAppPort).To(Equal(0)) }) }) @@ -487,10 +488,11 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID, actualAppProtocol := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualAppProtocol, actualAppPort := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) Expect(actualAppProtocol).To(Equal("http2")) + Expect(actualAppPort).To(Equal(0)) }) }) }) @@ -631,10 +633,11 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID, actualAppProtocol := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualAppProtocol, actualAppPort := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) Expect(actualAppProtocol).To(Equal("http2")) + Expect(actualAppPort).To(Equal(0)) }) }) @@ -670,10 +673,26 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID, actualAppProtocol := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualAppProtocol, actualAppPort := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) Expect(actualAppProtocol).To(Equal("http2")) + Expect(actualAppPort).To(Equal(0)) + }) + }) + + Context("when an app port is provided", func() { + BeforeEach(func() { + cmd.AppPort = 9292 + }) + + It("passes the port to the actor", func() { + Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) + actualRouteGUID, actualAppGUID, actualAppProtocol, actualAppPort := fakeActor.MapRouteArgsForCall(0) + Expect(actualRouteGUID).To(Equal("route-guid")) + Expect(actualAppGUID).To(Equal("app-guid")) + Expect(actualAppProtocol).To(Equal("http2")) + Expect(actualAppPort).To(Equal(9292)) }) }) }) diff --git a/command/v7/routes_command.go b/command/v7/routes_command.go index 0b63d618a72..c3743c5f886 100644 --- a/command/v7/routes_command.go +++ b/command/v7/routes_command.go @@ -83,6 +83,7 @@ func (cmd RoutesCommand) displayRoutesTable(routeSummaries []v7action.RouteSumma cmd.UI.TranslateText("path"), cmd.UI.TranslateText("protocol"), cmd.UI.TranslateText("app-protocol"), + cmd.UI.TranslateText("app-port"), cmd.UI.TranslateText("apps"), cmd.UI.TranslateText("service instance"), cmd.UI.TranslateText("options"), @@ -103,6 +104,7 @@ func (cmd RoutesCommand) displayRoutesTable(routeSummaries []v7action.RouteSumma routeSummary.Path, routeSummary.Protocol, strings.Join(routeSummary.AppProtocols, ", "), + strings.Join(routeSummary.AppPorts, ", "), strings.Join(routeSummary.AppNames, ", "), routeSummary.ServiceInstanceName, routeSummary.Route.FormattedOptions(), diff --git a/command/v7/routes_command_test.go b/command/v7/routes_command_test.go index 96c67dfa104..a0f865feb80 100644 --- a/command/v7/routes_command_test.go +++ b/command/v7/routes_command_test.go @@ -29,7 +29,7 @@ var _ = Describe("routes Command", func() { binaryName string ) - const tableHeaders = `space\s+host\s+domain\s+port\s+path\s+protocol\s+app-protocol\s+apps\s+service instance` + const tableHeaders = `space\s+host\s+domain\s+port\s+path\s+protocol\s+app-protocol\s+app-port\s+apps\s+service instance` BeforeEach(func() { testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) diff --git a/command/v7/v7fakes/fake_actor.go b/command/v7/v7fakes/fake_actor.go index 2598de0ff99..20116fbfdee 100644 --- a/command/v7/v7fakes/fake_actor.go +++ b/command/v7/v7fakes/fake_actor.go @@ -2537,12 +2537,13 @@ type FakeActor struct { result2 *http.Response result3 error } - MapRouteStub func(string, string, string) (v7action.Warnings, error) + MapRouteStub func(string, string, string, int) (v7action.Warnings, error) mapRouteMutex sync.RWMutex mapRouteArgsForCall []struct { arg1 string arg2 string arg3 string + arg4 int } mapRouteReturns struct { result1 v7action.Warnings @@ -14686,20 +14687,21 @@ func (fake *FakeActor) MakeCurlRequestReturnsOnCall(i int, result1 []byte, resul }{result1, result2, result3} } -func (fake *FakeActor) MapRoute(arg1 string, arg2 string, arg3 string) (v7action.Warnings, error) { +func (fake *FakeActor) MapRoute(arg1 string, arg2 string, arg3 string, arg4 int) (v7action.Warnings, error) { fake.mapRouteMutex.Lock() ret, specificReturn := fake.mapRouteReturnsOnCall[len(fake.mapRouteArgsForCall)] fake.mapRouteArgsForCall = append(fake.mapRouteArgsForCall, struct { arg1 string arg2 string arg3 string - }{arg1, arg2, arg3}) + arg4 int + }{arg1, arg2, arg3, arg4}) stub := fake.MapRouteStub fakeReturns := fake.mapRouteReturns - fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3}) + fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3, arg4}) fake.mapRouteMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3) + return stub(arg1, arg2, arg3, arg4) } if specificReturn { return ret.result1, ret.result2 @@ -14713,17 +14715,17 @@ func (fake *FakeActor) MapRouteCallCount() int { return len(fake.mapRouteArgsForCall) } -func (fake *FakeActor) MapRouteCalls(stub func(string, string, string) (v7action.Warnings, error)) { +func (fake *FakeActor) MapRouteCalls(stub func(string, string, string, int) (v7action.Warnings, error)) { fake.mapRouteMutex.Lock() defer fake.mapRouteMutex.Unlock() fake.MapRouteStub = stub } -func (fake *FakeActor) MapRouteArgsForCall(i int) (string, string, string) { +func (fake *FakeActor) MapRouteArgsForCall(i int) (string, string, string, int) { fake.mapRouteMutex.RLock() defer fake.mapRouteMutex.RUnlock() argsForCall := fake.mapRouteArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 } func (fake *FakeActor) MapRouteReturns(result1 v7action.Warnings, result2 error) { diff --git a/integration/v7/isolated/map_route_command_test.go b/integration/v7/isolated/map_route_command_test.go index 4d0804e7641..a8520de08f3 100644 --- a/integration/v7/isolated/map_route_command_test.go +++ b/integration/v7/isolated/map_route_command_test.go @@ -29,7 +29,7 @@ var _ = Describe("map-route command", func() { Eventually(session).Should(Say(`USAGE:`)) Eventually(session).Should(Say(`Map an HTTP route:\n`)) - Eventually(session).Should(Say(`cf map-route APP_NAME DOMAIN \[--hostname HOSTNAME\] \[--path PATH\] \[--app-protocol PROTOCOL\] \[--option OPTION=VALUE\]\n`)) + Eventually(session).Should(Say(`cf map-route APP_NAME DOMAIN \[--hostname HOSTNAME\] \[--path PATH\] \[--app-protocol PROTOCOL\] \[--app-port PORT\] \[--option OPTION=VALUE\]\n`)) Eventually(session).Should(Say(`Map a TCP route:\n`)) Eventually(session).Should(Say(`cf map-route APP_NAME DOMAIN \[--port PORT] \[--option OPTION=VALUE\]\n`)) Eventually(session).Should(Say(`\n`)) @@ -40,6 +40,7 @@ var _ = Describe("map-route command", func() { Eventually(session).Should(Say(`cf map-route my-app example.com --hostname myhost -o loadbalancing=least-connection # myhost.example.com with a per-route option`)) Eventually(session).Should(Say(`cf map-route my-app example.com --hostname myhost --path foo # myhost.example.com/foo`)) Eventually(session).Should(Say(`cf map-route my-app example.com --hostname myhost --app-protocol http2 # myhost.example.com`)) + Eventually(session).Should(Say(`cf map-route my-app example.com --hostname myhost --app-port 8090 # myhost.example.com`)) Eventually(session).Should(Say(`cf map-route my-app example.com --port 5000 # example.com:5000`)) Eventually(session).Should(Say(`\n`)) @@ -47,7 +48,8 @@ var _ = Describe("map-route command", func() { Eventually(session).Should(Say(`--hostname, -n\s+Hostname for the HTTP route \(required for shared domains\)`)) Eventually(session).Should(Say(`--path\s+Path for the HTTP route`)) Eventually(session).Should(Say(`--port\s+Port for the TCP route \(default: random port\)`)) - Eventually(session).Should(Say(`--app-protocol\s+\[Beta flag, subject to change\] Protocol for the route destination \(default: http1\). Only applied to HTTP routes`)) + Eventually(session).Should(Say(`--app-protocol\s+\[Beta flag, subject to change\] Protocol for the route destination \(default: http1\).\s+Only applied to HTTP routes`)) + Eventually(session).Should(Say(`--app-port\s+\[Beta flag, subject to change\] App port for the route destination \(default: 8080\).\s+Only applied to HTTP routes`)) Eventually(session).Should(Say(`--option, -o\s+Set the value of a per-route option`)) Eventually(session).Should(Say(`\n`)) diff --git a/integration/v7/isolated/routes_command_test.go b/integration/v7/isolated/routes_command_test.go index 08a6ed35aa7..8ca8660f643 100644 --- a/integration/v7/isolated/routes_command_test.go +++ b/integration/v7/isolated/routes_command_test.go @@ -16,7 +16,7 @@ import ( var _ = Describe("routes command", func() { appProtocolValue := "http1" - const tableHeaders = `space\s+host\s+domain\s+port\s+path\s+protocol\s+app-protocol\s+apps\s+service instance\s+options` + const tableHeaders = `space\s+host\s+domain\s+port\s+path\s+protocol\s+app-protocol\s+app-port\s+apps\s+service instance\s+options` Context("Help", func() { It("appears in cf help -a", func() { session := helpers.CF("help", "-a") @@ -122,10 +122,10 @@ var _ = Describe("routes command", func() { Eventually(session).Should(Exit(0)) Expect(session).To(Say(`Getting routes for org %s / space %s as %s\.\.\.`, orgName, spaceName, userName)) Expect(session).To(Say(tableHeaders)) - Expect(session).To(Say(`%s\s+route1\s+%s\s+http\s+%s\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1, serviceInstanceName)) - Expect(session).To(Say(`%s\s+route1a\s+%s\s+http\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) - Expect(session).To(Say(`%s\s+route1b\s+%s\s+http\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) - Expect(session).ToNot(Say(`%s\s+route2\s+%s\s+http\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName2)) + Expect(session).To(Say(`%s\s+route1\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1, serviceInstanceName)) + Expect(session).To(Say(`%s\s+route1a\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) + Expect(session).To(Say(`%s\s+route1b\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) + Expect(session).ToNot(Say(`%s\s+route2\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName2)) }) It("lists all the routes by label", func() { @@ -133,10 +133,10 @@ var _ = Describe("routes command", func() { Eventually(session).Should(Exit(0)) Expect(session).To(Say(`Getting routes for org %s / space %s as %s\.\.\.`, orgName, spaceName, userName)) Expect(session).To(Say(tableHeaders)) - Expect(session).ToNot(Say(`%s\s+route1\s+%s\s+http\s+%s\s+%s\s+%s\n`, spaceName, domainName, appProtocolValue, appName1, serviceInstanceName)) - Expect(session).ToNot(Say(`%s\s+route1a\s+%s\s+http\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) - Expect(session).To(Say(`%s\s+route1b\s+%s\s+http\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) - Expect(session).ToNot(Say(`%s\s+route2\s+%s\s+http\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName2)) + Expect(session).ToNot(Say(`%s\s+route1\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+%s\n`, spaceName, domainName, appProtocolValue, appName1, serviceInstanceName)) + Expect(session).ToNot(Say(`%s\s+route1a\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) + Expect(session).To(Say(`%s\s+route1b\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1)) + Expect(session).ToNot(Say(`%s\s+route2\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName2)) }) When("fetching routes by org", func() { @@ -145,8 +145,8 @@ var _ = Describe("routes command", func() { Eventually(session).Should(Exit(0)) Expect(session).To(Say(`Getting routes for org %s as %s\.\.\.`, orgName, userName)) Expect(session).To(Say(tableHeaders)) - Expect(session).To(Say(`%s\s+route1\s+%s\s+http\s+%s\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1, serviceInstanceName)) - Expect(session).To(Say(`%s\s+route2\s+%s\s+\/dodo\s+http\s+%s\s+%s\s+\n`, otherSpaceName, domainName, appProtocolValue, appName2)) + Expect(session).To(Say(`%s\s+route1\s+%s\s+http\s+%s\s+[0-9]+\s+%s\s+%s\s+\n`, spaceName, domainName, appProtocolValue, appName1, serviceInstanceName)) + Expect(session).To(Say(`%s\s+route2\s+%s\s+\/dodo\s+http\s+%s\s+[0-9]+\s+%s\s+\n`, otherSpaceName, domainName, appProtocolValue, appName2)) }) }) }) @@ -186,8 +186,8 @@ var _ = Describe("routes command", func() { Eventually(session).Should(Exit(0)) Expect(session).To(Say(`Getting routes for org %s / space %s as %s\.\.\.`, orgName, spaceName, userName)) Expect(session).To(Say(tableHeaders)) - Eventually(session).Should(Or(Say(`%s\s+route1\s+%s\s+http\s+http1, http2\s+%s\s+\n`, spaceName, domainName, fmt.Sprintf("%s, %s", appName2, appName1)), Say(`%s\s+route1\s+%s\s+http\s+http1, http2\s+%s\s+\n`, spaceName, domainName, fmt.Sprintf("%s, %s", appName1, appName2)))) - Eventually(session).Should(Say(`%s\s+route2\s+%s\s+http\s+http1\s+%s\s+\n`, spaceName, domainName, appName2)) + Eventually(session).Should(Or(Say(`%s\s+route1\s+%s\s+http\s+http1, http2\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, fmt.Sprintf("%s, %s", appName2, appName1)), Say(`%s\s+route1\s+%s\s+http\s+http1, http2\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, fmt.Sprintf("%s, %s", appName1, appName2)))) + Eventually(session).Should(Say(`%s\s+route2\s+%s\s+http\s+http1\s+[0-9]+\s+%s\s+\n`, spaceName, domainName, appName2)) }) })