From c48df033397ced910daabcd1a2595fb9a8d2af86 Mon Sep 17 00:00:00 2001 From: Carson Long Date: Wed, 18 Aug 2021 16:52:02 +0000 Subject: [PATCH] Add experimental destination-protocol flag to map-route Allows to specify HTTP2 protocol that is used to reach application. cloudfoundry/cli#2188 Co-authored-by: Maria Shaldybin --- actor/v7action/cloud_controller_client.go | 2 +- actor/v7action/route.go | 4 +- actor/v7action/route_test.go | 15 ++++- .../fake_cloud_controller_client.go | 18 +++--- actor/v7pushaction/v7_actor.go | 2 +- .../v7pushactionfakes/fake_v7actor.go | 18 +++--- api/cloudcontroller/ccv3/route.go | 12 +++- api/cloudcontroller/ccv3/route_test.go | 58 +++++++++++++------ command/v7/actor.go | 2 +- command/v7/map_route_command.go | 53 +++++++++++------ command/v7/map_route_command_test.go | 21 ++++--- command/v7/v7fakes/fake_actor.go | 18 +++--- .../v7/isolated/map_route_command_test.go | 27 ++++++--- 13 files changed, 163 insertions(+), 87 deletions(-) diff --git a/actor/v7action/cloud_controller_client.go b/actor/v7action/cloud_controller_client.go index 1967d493747..35ff47380d9 100644 --- a/actor/v7action/cloud_controller_client.go +++ b/actor/v7action/cloud_controller_client.go @@ -139,7 +139,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) (ccv3.Warnings, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string) (ccv3.Warnings, error) PollJob(jobURL ccv3.JobURL) (ccv3.Warnings, error) PollJobForState(jobURL ccv3.JobURL, state constant.JobState) (ccv3.Warnings, error) PollJobToEventStream(jobURL ccv3.JobURL) chan ccv3.PollJobEvent diff --git a/actor/v7action/route.go b/actor/v7action/route.go index 352cd836faf..67c7c374f55 100644 --- a/actor/v7action/route.go +++ b/actor/v7action/route.go @@ -369,8 +369,8 @@ func (actor Actor) GetRouteByAttributes(domain resources.Domain, hostname string return routes[0], Warnings(ccWarnings), nil } -func (actor Actor) MapRoute(routeGUID string, appGUID string) (Warnings, error) { - warnings, err := actor.CloudControllerClient.MapRoute(routeGUID, appGUID) +func (actor Actor) MapRoute(routeGUID string, appGUID string, destinationProtocol string) (Warnings, error) { + warnings, err := actor.CloudControllerClient.MapRoute(routeGUID, appGUID, destinationProtocol) return Warnings(warnings), err } diff --git a/actor/v7action/route_test.go b/actor/v7action/route_test.go index 478fa2cb42c..ec402858c0e 100644 --- a/actor/v7action/route_test.go +++ b/actor/v7action/route_test.go @@ -1453,20 +1453,22 @@ var _ = Describe("Route Actions", func() { Describe("MapRoute", func() { var ( - routeGUID string - appGUID string + routeGUID string + appGUID string + destinationProtocol string executeErr error warnings Warnings ) JustBeforeEach(func() { - warnings, executeErr = actor.MapRoute(routeGUID, appGUID) + warnings, executeErr = actor.MapRoute(routeGUID, appGUID, destinationProtocol) }) BeforeEach(func() { routeGUID = "route-guid" appGUID = "app-guid" + destinationProtocol = "http2" }) When("the cloud controller client errors", func() { @@ -1485,6 +1487,13 @@ var _ = Describe("Route Actions", func() { fakeCloudControllerClient.MapRouteReturns(ccv3.Warnings{"map-route-warning"}, nil) }) + It("calls the cloud controller client with the right arguments", func() { + actualRouteGUID, actualAppGUID, actualDestinationProtocol := fakeCloudControllerClient.MapRouteArgsForCall(0) + Expect(actualRouteGUID).To(Equal("route-guid")) + Expect(actualAppGUID).To(Equal("app-guid")) + Expect(actualDestinationProtocol).To(Equal("http2")) + }) + It("returns the error and warnings", func() { Expect(executeErr).ToNot(HaveOccurred()) Expect(warnings).To(ConsistOf("map-route-warning")) diff --git a/actor/v7action/v7actionfakes/fake_cloud_controller_client.go b/actor/v7action/v7actionfakes/fake_cloud_controller_client.go index bab62d35abc..ca4a7e21d35 100644 --- a/actor/v7action/v7actionfakes/fake_cloud_controller_client.go +++ b/actor/v7action/v7actionfakes/fake_cloud_controller_client.go @@ -1951,11 +1951,12 @@ type FakeCloudControllerClient struct { result2 *http.Response result3 error } - MapRouteStub func(string, string) (ccv3.Warnings, error) + MapRouteStub func(string, string, string) (ccv3.Warnings, error) mapRouteMutex sync.RWMutex mapRouteArgsForCall []struct { arg1 string arg2 string + arg3 string } mapRouteReturns struct { result1 ccv3.Warnings @@ -11083,17 +11084,18 @@ func (fake *FakeCloudControllerClient) MakeRequestSendReceiveRawReturnsOnCall(i }{result1, result2, result3} } -func (fake *FakeCloudControllerClient) MapRoute(arg1 string, arg2 string) (ccv3.Warnings, error) { +func (fake *FakeCloudControllerClient) MapRoute(arg1 string, arg2 string, arg3 string) (ccv3.Warnings, error) { fake.mapRouteMutex.Lock() ret, specificReturn := fake.mapRouteReturnsOnCall[len(fake.mapRouteArgsForCall)] fake.mapRouteArgsForCall = append(fake.mapRouteArgsForCall, struct { arg1 string arg2 string - }{arg1, arg2}) - fake.recordInvocation("MapRoute", []interface{}{arg1, arg2}) + arg3 string + }{arg1, arg2, arg3}) + fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3}) fake.mapRouteMutex.Unlock() if fake.MapRouteStub != nil { - return fake.MapRouteStub(arg1, arg2) + return fake.MapRouteStub(arg1, arg2, arg3) } if specificReturn { return ret.result1, ret.result2 @@ -11108,17 +11110,17 @@ func (fake *FakeCloudControllerClient) MapRouteCallCount() int { return len(fake.mapRouteArgsForCall) } -func (fake *FakeCloudControllerClient) MapRouteCalls(stub func(string, string) (ccv3.Warnings, error)) { +func (fake *FakeCloudControllerClient) MapRouteCalls(stub func(string, string, string) (ccv3.Warnings, error)) { fake.mapRouteMutex.Lock() defer fake.mapRouteMutex.Unlock() fake.MapRouteStub = stub } -func (fake *FakeCloudControllerClient) MapRouteArgsForCall(i int) (string, string) { +func (fake *FakeCloudControllerClient) MapRouteArgsForCall(i int) (string, string, string) { fake.mapRouteMutex.RLock() defer fake.mapRouteMutex.RUnlock() argsForCall := fake.mapRouteArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 } func (fake *FakeCloudControllerClient) MapRouteReturns(result1 ccv3.Warnings, result2 error) { diff --git a/actor/v7pushaction/v7_actor.go b/actor/v7pushaction/v7_actor.go index abe25d5466c..db59052da50 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) (v7action.Warnings, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string) (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 6e491f764a6..c9e8539321e 100644 --- a/actor/v7pushaction/v7pushactionfakes/fake_v7actor.go +++ b/actor/v7pushaction/v7pushactionfakes/fake_v7actor.go @@ -234,11 +234,12 @@ type FakeV7Actor struct { result1 resources.RouteDestination result2 error } - MapRouteStub func(string, string) (v7action.Warnings, error) + MapRouteStub func(string, string, string) (v7action.Warnings, error) mapRouteMutex sync.RWMutex mapRouteArgsForCall []struct { arg1 string arg2 string + arg3 string } mapRouteReturns struct { result1 v7action.Warnings @@ -1445,17 +1446,18 @@ func (fake *FakeV7Actor) GetRouteDestinationByAppGUIDReturnsOnCall(i int, result }{result1, result2} } -func (fake *FakeV7Actor) MapRoute(arg1 string, arg2 string) (v7action.Warnings, error) { +func (fake *FakeV7Actor) MapRoute(arg1 string, arg2 string, arg3 string) (v7action.Warnings, error) { fake.mapRouteMutex.Lock() ret, specificReturn := fake.mapRouteReturnsOnCall[len(fake.mapRouteArgsForCall)] fake.mapRouteArgsForCall = append(fake.mapRouteArgsForCall, struct { arg1 string arg2 string - }{arg1, arg2}) - fake.recordInvocation("MapRoute", []interface{}{arg1, arg2}) + arg3 string + }{arg1, arg2, arg3}) + fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3}) fake.mapRouteMutex.Unlock() if fake.MapRouteStub != nil { - return fake.MapRouteStub(arg1, arg2) + return fake.MapRouteStub(arg1, arg2, arg3) } if specificReturn { return ret.result1, ret.result2 @@ -1470,17 +1472,17 @@ func (fake *FakeV7Actor) MapRouteCallCount() int { return len(fake.mapRouteArgsForCall) } -func (fake *FakeV7Actor) MapRouteCalls(stub func(string, string) (v7action.Warnings, error)) { +func (fake *FakeV7Actor) MapRouteCalls(stub func(string, string, string) (v7action.Warnings, error)) { fake.mapRouteMutex.Lock() defer fake.mapRouteMutex.Unlock() fake.MapRouteStub = stub } -func (fake *FakeV7Actor) MapRouteArgsForCall(i int) (string, string) { +func (fake *FakeV7Actor) MapRouteArgsForCall(i int) (string, string, string) { fake.mapRouteMutex.RLock() defer fake.mapRouteMutex.RUnlock() argsForCall := fake.mapRouteArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 } func (fake *FakeV7Actor) MapRouteReturns(result1 v7action.Warnings, result2 error) { diff --git a/api/cloudcontroller/ccv3/route.go b/api/cloudcontroller/ccv3/route.go index c0643d5eb87..947461c1ee8 100644 --- a/api/cloudcontroller/ccv3/route.go +++ b/api/cloudcontroller/ccv3/route.go @@ -82,7 +82,7 @@ func (client Client) GetRoutes(query ...Query) ([]resources.Route, Warnings, err return routes, warnings, err } -func (client Client) MapRoute(routeGUID string, appGUID string) (Warnings, error) { +func (client Client) MapRoute(routeGUID string, appGUID string, destinationProtocol string) (Warnings, error) { type destinationProcess struct { ProcessType string `json:"process_type"` } @@ -92,7 +92,8 @@ func (client Client) MapRoute(routeGUID string, appGUID string) (Warnings, error Process *destinationProcess `json:"process,omitempty"` } type destination struct { - App destinationApp `json:"app"` + App destinationApp `json:"app"` + Protocol string `json:"protocol,omitempty"` } type body struct { @@ -101,9 +102,14 @@ func (client Client) MapRoute(routeGUID string, appGUID string) (Warnings, error requestBody := body{ Destinations: []destination{ - {App: destinationApp{GUID: appGUID}}, + { + App: destinationApp{GUID: appGUID}, + }, }, } + if destinationProtocol != "" { + requestBody.Destinations[0].Protocol = destinationProtocol + } _, 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 3cd7fe36eca..351e27636d8 100644 --- a/api/cloudcontroller/ccv3/route_test.go +++ b/api/cloudcontroller/ccv3/route_test.go @@ -537,39 +537,40 @@ var _ = Describe("Route", func() { Describe("MapRoute", func() { var ( - routeGUID = "route-guid" - appGUID = "app-guid" - warnings Warnings - executeErr error + routeGUID = "route-guid" + appGUID = "app-guid" + destinationProtocol = "http2" + expectedBody string + warnings Warnings + executeErr error ) JustBeforeEach(func() { - warnings, executeErr = client.MapRoute(routeGUID, appGUID) + response := `{}` + server.AppendHandlers( + CombineHandlers( + VerifyRequest(http.MethodPost, "/v3/routes/route-guid/destinations"), + VerifyJSON(expectedBody), + RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), + ), + ) + warnings, executeErr = client.MapRoute(routeGUID, appGUID, destinationProtocol) }) When("the request is successful", func() { BeforeEach(func() { - expectedBody := fmt.Sprintf(` + expectedBody = fmt.Sprintf(` { "destinations": [ { "app": { "guid": "%s" - } + }, + "protocol": "%s" } ] } - `, appGUID) - - response := `{}` - - server.AppendHandlers( - CombineHandlers( - VerifyRequest(http.MethodPost, "/v3/routes/route-guid/destinations"), - VerifyJSON(expectedBody), - RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), - ), - ) + `, appGUID, destinationProtocol) }) It("returns the warnings and no error", func() { @@ -578,6 +579,27 @@ var _ = Describe("Route", func() { }) }) + Context("when destination protocol is not provided", func() { + BeforeEach(func() { + destinationProtocol = "" + expectedBody = fmt.Sprintf(` + { + "destinations": [ + { + "app": { + "guid": "%s" + } + } + ] + } + `, appGUID) + }) + + It("does not include it 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 57b6a1fff5c..3c6e1ba3560 100644 --- a/command/v7/actor.go +++ b/command/v7/actor.go @@ -178,7 +178,7 @@ type Actor interface { GetUnstagedNewestPackageGUID(appGuid string) (string, v7action.Warnings, error) GetUser(username, origin string) (resources.User, error) MakeCurlRequest(httpMethod string, path string, customHeaders []string, httpData string, failOnHTTPError bool) ([]byte, *http.Response, error) - MapRoute(routeGUID string, appGUID string) (v7action.Warnings, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string) (v7action.Warnings, error) Marketplace(filter v7action.MarketplaceFilter) ([]v7action.ServiceOfferingWithPlans, v7action.Warnings, error) ParseAccessToken(accessToken string) (jwt.JWT, error) PollBuild(buildGUID string, appName string) (resources.Droplet, v7action.Warnings, error) diff --git a/command/v7/map_route_command.go b/command/v7/map_route_command.go index 039b6777d0e..4224b40741c 100644 --- a/command/v7/map_route_command.go +++ b/command/v7/map_route_command.go @@ -8,17 +8,19 @@ import ( type MapRouteCommand struct { BaseCommand - RequiredArgs flag.AppDomain `positional-args:"yes"` - Hostname string `long:"hostname" short:"n" description:"Hostname for the HTTP route (required for shared domains)"` - Path flag.V7RoutePath `long:"path" description:"Path for the HTTP route"` - Port int `long:"port" description:"Port for the TCP route (default: random port)"` - relatedCommands interface{} `related_commands:"create-route, routes, unmap-route"` + RequiredArgs flag.AppDomain `positional-args:"yes"` + Hostname string `long:"hostname" short:"n" description:"Hostname for the HTTP route (required for shared domains)"` + Path flag.V7RoutePath `long:"path" description:"Path for the HTTP route"` + Port int `long:"port" description:"Port for the TCP route (default: random port)"` + DestinationProtocol string `long:"destination-protocol" description:"[Beta flag, subject to change] Protocol for the route destination (default: http1). Only applied to HTTP routes"` + + relatedCommands interface{} `related_commands:"create-route, routes, unmap-route"` } func (cmd MapRouteCommand) Usage() string { return ` Map an HTTP route: - CF_NAME map-route APP_NAME DOMAIN [--hostname HOSTNAME] [--path PATH] + CF_NAME map-route APP_NAME DOMAIN [--hostname HOSTNAME] [--path PATH] [--destination-protocol PROTOCOL] Map a TCP route: CF_NAME map-route APP_NAME DOMAIN [--port PORT]` @@ -26,10 +28,11 @@ Map a TCP route: func (cmd MapRouteCommand) Examples() string { return ` -CF_NAME map-route my-app example.com # example.com -CF_NAME map-route my-app example.com --hostname myhost # myhost.example.com -CF_NAME map-route my-app example.com --hostname myhost --path foo # myhost.example.com/foo -CF_NAME map-route my-app example.com --port 5000 # example.com:5000` +CF_NAME map-route my-app example.com # example.com +CF_NAME map-route my-app example.com --hostname myhost # myhost.example.com +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 --destination-protocol http2 # myhost.example.com +CF_NAME map-route my-app example.com --port 5000 # example.com:5000` } func (cmd MapRouteCommand) Execute(args []string) error { @@ -85,13 +88,25 @@ func (cmd MapRouteCommand) Execute(args []string) error { cmd.UI.DisplayOK() } - cmd.UI.DisplayTextWithFlavor("Mapping route {{.URL}} to app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.User}}...", map[string]interface{}{ - "URL": route.URL, - "AppName": cmd.RequiredArgs.App, - "User": user.Name, - "SpaceName": cmd.Config.TargetedSpace().Name, - "OrgName": cmd.Config.TargetedOrganization().Name, - }) + if cmd.DestinationProtocol != "" { + cmd.UI.DisplayTextWithFlavor("Mapping route {{.URL}} to app {{.AppName}} with protocol {{.Protocol}} in org {{.OrgName}} / space {{.SpaceName}} as {{.User}}...", map[string]interface{}{ + "URL": route.URL, + "AppName": cmd.RequiredArgs.App, + "User": user.Name, + "SpaceName": cmd.Config.TargetedSpace().Name, + "OrgName": cmd.Config.TargetedOrganization().Name, + "Protocol": cmd.DestinationProtocol, + }) + + } else { + cmd.UI.DisplayTextWithFlavor("Mapping route {{.URL}} to app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.User}}...", map[string]interface{}{ + "URL": route.URL, + "AppName": cmd.RequiredArgs.App, + "User": user.Name, + "SpaceName": cmd.Config.TargetedSpace().Name, + "OrgName": cmd.Config.TargetedOrganization().Name, + }) + } dest, err := cmd.Actor.GetRouteDestinationByAppGUID(route, app.GUID) if err != nil { if _, ok := err.(actionerror.RouteDestinationNotFoundError); !ok { @@ -99,14 +114,14 @@ func (cmd MapRouteCommand) Execute(args []string) error { } } if dest.GUID != "" { - cmd.UI.DisplayText("App '{{ .AppName }}' is already mapped to route '{{ .URL}}'.", map[string]interface{}{ + cmd.UI.DisplayText("App '{{ .AppName }}' is already mapped to route '{{ .URL}}'. Nothing has been updated.", map[string]interface{}{ "AppName": cmd.RequiredArgs.App, "URL": route.URL, }) cmd.UI.DisplayOK() return nil } - warnings, err = cmd.Actor.MapRoute(route.GUID, app.GUID) + warnings, err = cmd.Actor.MapRoute(route.GUID, app.GUID, cmd.DestinationProtocol) 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 e3113172a38..00e8154a7a8 100644 --- a/command/v7/map_route_command_test.go +++ b/command/v7/map_route_command_test.go @@ -53,9 +53,10 @@ var _ = Describe("map-route Command", func() { spaceGUID = "some-space-guid" cmd = MapRouteCommand{ - RequiredArgs: flag.AppDomain{App: appName, Domain: domain}, - Hostname: hostname, - Path: flag.V7RoutePath{Path: path}, + RequiredArgs: flag.AppDomain{App: appName, Domain: domain}, + Hostname: hostname, + Path: flag.V7RoutePath{Path: path}, + DestinationProtocol: "http2", BaseCommand: BaseCommand{ UI: testUI, Config: fakeConfig, @@ -371,9 +372,10 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualDestinationProtocol := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) + Expect(actualDestinationProtocol).To(Equal("http2")) }) }) @@ -391,7 +393,7 @@ var _ = Describe("map-route Command", func() { Expect(executeErr).ToNot(HaveOccurred()) }) - By("passing the expected arguments to the actor ", func() { + By("passing the expected arguments to the actor", func() { Expect(fakeActor.GetDomainByNameCallCount()).To(Equal(1)) Expect(fakeActor.GetDomainByNameArgsForCall(0)).To(Equal(domain)) @@ -409,9 +411,10 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualDestinationProtocol := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) + Expect(actualDestinationProtocol).To(Equal("http2")) }) }) }) @@ -531,9 +534,10 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualDestinationProtocol := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) + Expect(actualDestinationProtocol).To(Equal("http2")) }) }) @@ -569,9 +573,10 @@ var _ = Describe("map-route Command", func() { Expect(actualPort).To(Equal(cmd.Port)) Expect(fakeActor.MapRouteCallCount()).To(Equal(1)) - actualRouteGUID, actualAppGUID := fakeActor.MapRouteArgsForCall(0) + actualRouteGUID, actualAppGUID, actualDestinationProtocol := fakeActor.MapRouteArgsForCall(0) Expect(actualRouteGUID).To(Equal("route-guid")) Expect(actualAppGUID).To(Equal("app-guid")) + Expect(actualDestinationProtocol).To(Equal("http2")) }) }) }) diff --git a/command/v7/v7fakes/fake_actor.go b/command/v7/v7fakes/fake_actor.go index dbe355f05db..18191235ae6 100644 --- a/command/v7/v7fakes/fake_actor.go +++ b/command/v7/v7fakes/fake_actor.go @@ -2431,11 +2431,12 @@ type FakeActor struct { result2 *http.Response result3 error } - MapRouteStub func(string, string) (v7action.Warnings, error) + MapRouteStub func(string, string, string) (v7action.Warnings, error) mapRouteMutex sync.RWMutex mapRouteArgsForCall []struct { arg1 string arg2 string + arg3 string } mapRouteReturns struct { result1 v7action.Warnings @@ -13870,17 +13871,18 @@ func (fake *FakeActor) MakeCurlRequestReturnsOnCall(i int, result1 []byte, resul }{result1, result2, result3} } -func (fake *FakeActor) MapRoute(arg1 string, arg2 string) (v7action.Warnings, error) { +func (fake *FakeActor) MapRoute(arg1 string, arg2 string, arg3 string) (v7action.Warnings, error) { fake.mapRouteMutex.Lock() ret, specificReturn := fake.mapRouteReturnsOnCall[len(fake.mapRouteArgsForCall)] fake.mapRouteArgsForCall = append(fake.mapRouteArgsForCall, struct { arg1 string arg2 string - }{arg1, arg2}) - fake.recordInvocation("MapRoute", []interface{}{arg1, arg2}) + arg3 string + }{arg1, arg2, arg3}) + fake.recordInvocation("MapRoute", []interface{}{arg1, arg2, arg3}) fake.mapRouteMutex.Unlock() if fake.MapRouteStub != nil { - return fake.MapRouteStub(arg1, arg2) + return fake.MapRouteStub(arg1, arg2, arg3) } if specificReturn { return ret.result1, ret.result2 @@ -13895,17 +13897,17 @@ func (fake *FakeActor) MapRouteCallCount() int { return len(fake.mapRouteArgsForCall) } -func (fake *FakeActor) MapRouteCalls(stub func(string, string) (v7action.Warnings, error)) { +func (fake *FakeActor) MapRouteCalls(stub func(string, string, string) (v7action.Warnings, error)) { fake.mapRouteMutex.Lock() defer fake.mapRouteMutex.Unlock() fake.MapRouteStub = stub } -func (fake *FakeActor) MapRouteArgsForCall(i int) (string, string) { +func (fake *FakeActor) MapRouteArgsForCall(i int) (string, string, string) { fake.mapRouteMutex.RLock() defer fake.mapRouteMutex.RUnlock() argsForCall := fake.mapRouteArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 } 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 5484eafc9d9..2957545e33b 100644 --- a/integration/v7/isolated/map_route_command_test.go +++ b/integration/v7/isolated/map_route_command_test.go @@ -28,22 +28,25 @@ 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\]\n`)) + Eventually(session).Should(Say(`cf map-route APP_NAME DOMAIN \[--hostname HOSTNAME\] \[--path PATH\] \[--destination-protocol PROTOCOL\]\n`)) Eventually(session).Should(Say(`Map a TCP route:\n`)) Eventually(session).Should(Say(`cf map-route APP_NAME DOMAIN \[--port PORT]\n`)) Eventually(session).Should(Say(`\n`)) Eventually(session).Should(Say(`EXAMPLES:`)) - Eventually(session).Should(Say(`cf map-route my-app example.com # example.com`)) - Eventually(session).Should(Say(`cf map-route my-app example.com --hostname myhost # myhost.example.com`)) - 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 --port 5000 # example.com:5000`)) + Eventually(session).Should(Say(`cf map-route my-app example.com # example.com`)) + Eventually(session).Should(Say(`cf map-route my-app example.com --hostname myhost # myhost.example.com`)) + 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 --destination-protocol http2 # myhost.example.com`)) + Eventually(session).Should(Say(`cf map-route my-app example.com --port 5000 # example.com:5000`)) Eventually(session).Should(Say(`\n`)) Eventually(session).Should(Say(`OPTIONS:`)) 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(`--destination-protocol\s+\[Beta flag, subject to change\] Protocol for the route destination \(default: http1\). Only applied to HTTP routes`)) + Eventually(session).Should(Say(`\n`)) Eventually(session).Should(Say(`SEE ALSO:`)) @@ -108,7 +111,7 @@ var _ = Describe("map-route command", func() { session := helpers.CF("map-route", appName, domainName, "--hostname", route.Host, "--path", route.Path) Eventually(session).Should(Say(`Mapping route %s.%s%s to app %s in org %s / space %s as %s\.\.\.`, hostName, domainName, path, appName, orgName, spaceName, userName)) - Eventually(session).Should(Say(`App '%s' is already mapped to route '%s.%s%s'\.`, appName, hostName, domainName, path)) + Eventually(session).Should(Say(`App '%s' is already mapped to route '%s.%s%s'\. Nothing has been updated\.`, appName, hostName, domainName, path)) Eventually(session).Should(Say(`OK`)) Eventually(session).Should(Exit(0)) @@ -123,6 +126,16 @@ var _ = Describe("map-route command", func() { Eventually(session).Should(Exit(0)) }) }) + + When("destination protocol is provided", func() { + It("maps the route to an app", func() { + session := helpers.CF("map-route", appName, domainName, "--hostname", route.Host, "--destination-protocol", "http2") + + Eventually(session).Should(Say(`Mapping route %s.%s to app %s with protocol http2 in org %s / space %s as %s\.\.\.`, hostName, domainName, appName, orgName, spaceName, userName)) + Eventually(session).Should(Say(`OK`)) + Eventually(session).Should(Exit(0)) + }) + }) }) When("the tcp route already exists", func() { @@ -159,7 +172,7 @@ var _ = Describe("map-route command", func() { session := helpers.CF("map-route", appName, domainName, "--port", fmt.Sprintf("%d", route.Port)) Eventually(session).Should(Say(`Mapping route %s:%d to app %s in org %s / space %s as %s\.\.\.`, domainName, route.Port, appName, orgName, spaceName, userName)) - Eventually(session).Should(Say(`App '%s' is already mapped to route '%s:%d'\.`, appName, domainName, route.Port)) + Eventually(session).Should(Say(`App '%s' is already mapped to route '%s:%d'\. Nothing has been updated\.`, appName, domainName, route.Port)) Eventually(session).Should(Say(`OK`)) Eventually(session).Should(Exit(0)) })