Skip to content

Commit

Permalink
Add experimental destination-protocol flag to map-route
Browse files Browse the repository at this point in the history
Allows to specify HTTP2 protocol that is used to reach application.

#2188

Co-authored-by: Maria Shaldybin <mariash@vmware.com>
  • Loading branch information
ctlong and mariash committed Aug 18, 2021
1 parent ef8f348 commit eeb6091
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 84 deletions.
2 changes: 1 addition & 1 deletion actor/v7action/cloud_controller_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions actor/v7action/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
15 changes: 12 additions & 3 deletions actor/v7action/route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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"))
Expand Down
18 changes: 10 additions & 8 deletions actor/v7action/v7actionfakes/fake_cloud_controller_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion actor/v7pushaction/v7_actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 10 additions & 8 deletions actor/v7pushaction/v7pushactionfakes/fake_v7actor.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions api/cloudcontroller/ccv3/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
Expand All @@ -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 {
Expand All @@ -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,
Expand Down
58 changes: 40 additions & 18 deletions api/cloudcontroller/ccv3/route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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 := `{
Expand Down
2 changes: 1 addition & 1 deletion command/v7/actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
51 changes: 33 additions & 18 deletions command/v7/map_route_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,31 @@ 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]`
}

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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -106,7 +121,7 @@ func (cmd MapRouteCommand) Execute(args []string) error {
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
Expand Down
Loading

0 comments on commit eeb6091

Please sign in to comment.