Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add move-route command to cf cli #2302

Merged
merged 20 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
if: ${{ github.action_repository == 'cloudfoundry/cli' }}
if: ${{ github.repository == 'cloudfoundry/cli' }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer having GitHub Actions related changes in a separate PR, so we can easily synchronize these changes with other branches.

permissions:
actions: read
contents: read
Expand Down
9 changes: 2 additions & 7 deletions .github/workflows/units.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
name: Units Tests

on:
push:
branches:
- "*"

on: [push]
permissions:
contents: write

Expand Down Expand Up @@ -83,9 +79,8 @@ jobs:
strategy:
matrix:
os:
- windows-2022
- windows-latest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why we unlocked this.

- windows-2019
- windows-2016
runs-on: ${{ matrix.os }}
needs: shared-values
defaults:
Expand Down
1 change: 1 addition & 0 deletions actor/v7action/cloud_controller_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ type CloudControllerClient interface {
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)
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)
PollJobToEventStream(jobURL ccv3.JobURL) chan ccv3.PollJobEvent
Expand Down
5 changes: 5 additions & 0 deletions actor/v7action/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ func (actor Actor) GetApplicationRoutes(appGUID string) ([]resources.Route, Warn
return routes, allWarnings, nil
}

func (actor Actor) MoveRoute(routeGUID string, spaceGUID string) (Warnings, error) {
warnings, err := actor.CloudControllerClient.MoveRoute(routeGUID, spaceGUID)
return Warnings(warnings), err
}

func getDomainName(fullURL, host, path string, port int) string {
domainWithoutHost := strings.TrimPrefix(fullURL, host+".")
domainWithoutPath := strings.TrimSuffix(domainWithoutHost, path)
Expand Down
80 changes: 80 additions & 0 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.

7 changes: 6 additions & 1 deletion actor/v7pushaction/handle_app_path_override_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"

. "code.cloudfoundry.org/cli/actor/v7pushaction"
"code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
Expand Down Expand Up @@ -94,7 +95,11 @@ var _ = Describe("HandleAppPathOverride", func() {
absoluteAppFilehandle, err = ioutil.TempFile("", "")
Expect(err).NotTo(HaveOccurred())
defer absoluteAppFilehandle.Close()
relativeAppFilePath = filepath.Join(".", absoluteAppFilehandle.Name())
if runtime.GOOS == "windows" {
relativeAppFilePath = absoluteAppFilehandle.Name()
} else {
relativeAppFilePath = filepath.Join(filepath.Dir("/"), absoluteAppFilehandle.Name())
}
flagOverrides.ProvidedAppPath = relativeAppFilePath

// TODO: Do NOT use Chdir! it affects ALL other threads
Expand Down
2 changes: 2 additions & 0 deletions api/cloudcontroller/ccv3/internal/api_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const (
PatchSpaceFeaturesRequest = "PatchSpaceFeatures"
PatchSpaceQuotaRequest = "PatchSpaceQuota"
PatchStackRequest = "PatchStack"
PatchMoveRouteRequest = "PatchMoveRouteRequest"
PostApplicationActionApplyManifest = "PostApplicationActionApplyM"
PostApplicationActionRestartRequest = "PostApplicationActionRestart"
PostApplicationActionStartRequest = "PostApplicationActionStart"
Expand Down Expand Up @@ -279,6 +280,7 @@ var APIRoutes = map[string]Route{
UnmapRouteRequest: {Path: "/v3/routes/:route_guid/destinations/:destination_guid", Method: http.MethodDelete},
PatchDestinationRequest: {Path: "/v3/routes/:route_guid/destinations/:destination_guid", Method: http.MethodPatch},
ShareRouteRequest: {Path: "/v3/routes/:route_guid/relationships/shared_spaces", Method: http.MethodPost},
PatchMoveRouteRequest: {Path: "/v3/routes/:route-guid/relationships/space", Method: http.MethodPatch},
GetSecurityGroupsRequest: {Path: "/v3/security_groups", Method: http.MethodGet},
PostSecurityGroupRequest: {Path: "/v3/security_groups", Method: http.MethodPost},
DeleteSecurityGroupRequest: {Path: "/v3/security_groups/:security_group_guid", Method: http.MethodDelete},
Expand Down
25 changes: 25 additions & 0 deletions api/cloudcontroller/ccv3/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,28 @@ func (client Client) ShareRoute(routeGUID string, spaceGUID string) (Warnings, e
})
return warnings, err
}

func (client Client) MoveRoute(routeGUID string, spaceGUID string) (Warnings, error) {
type space struct {
GUID string `json:"guid"`
}

type body struct {
Data []space `json:"data"`
}

requestBody := body{
Data: []space{
{GUID: spaceGUID},
},
}

var responseBody resources.Build
_, warnings, err := client.MakeRequest(RequestParams{
RequestName: internal.PatchMoveRouteRequest,
URIParams: internal.Params{"route_guid": routeGUID},
RequestBody: &requestBody,
ResponseBody: &responseBody,
})
return warnings, err
}
1 change: 1 addition & 0 deletions command/common/command_list_v7.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ type commandList struct {
Target v7.TargetCommand `command:"target" alias:"t" description:"Set or view the targeted org or space"`
Tasks v7.TasksCommand `command:"tasks" description:"List tasks of an app"`
TerminateTask v7.TerminateTaskCommand `command:"terminate-task" description:"Terminate a running task of an app"`
MoveRoute v7.MoveRouteCommand `command:"move-route" description:"Assign a route to a different space"`
UnbindRouteService v7.UnbindRouteServiceCommand `command:"unbind-route-service" alias:"urs" description:"Unbind a service instance from an HTTP route"`
UnbindRunningSecurityGroup v7.UnbindRunningSecurityGroupCommand `command:"unbind-running-security-group" description:"Unbind a security group from the set of security groups for running applications globally"`
UnbindSecurityGroup v7.UnbindSecurityGroupCommand `command:"unbind-security-group" description:"Unbind a security group from a space"`
Expand Down
1 change: 1 addition & 0 deletions command/common/internal/help_all_display.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ var HelpCategoryList = []HelpCategory{
{"delete-orphaned-routes"},
{"update-destination"},
{"share-route"},
{"move-route"},
},
},
{
Expand Down
1 change: 1 addition & 0 deletions command/v7/actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ type Actor interface {
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)
Marketplace(filter v7action.MarketplaceFilter) ([]v7action.ServiceOfferingWithPlans, v7action.Warnings, error)
MoveRoute(routeGUID string, spaceGUID string) (v7action.Warnings, error)
ParseAccessToken(accessToken string) (jwt.JWT, error)
PollBuild(buildGUID string, appName string) (resources.Droplet, v7action.Warnings, error)
PollPackage(pkg resources.Package) (resources.Package, v7action.Warnings, error)
Expand Down
101 changes: 101 additions & 0 deletions command/v7/move_route_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package v7

import (
"code.cloudfoundry.org/cli/actor/actionerror"
"code.cloudfoundry.org/cli/command/flag"
)

type MoveRouteCommand struct {
BaseCommand

RequireArgs flag.Domain `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"`
DestinationSpace string `short:"s" description:"The space of the destination app (Default: targeted space)"`
DestinationOrg string `short:"o" description:"The org of the destination app (Default: targeted org)"`

relatedCommands interface{} `related_commands:"create-route, map-route, unmap-route, routes"`
}

func (cmd MoveRouteCommand) Usage() string {
return `
Transfers the ownership of a route to a another space:
CF_NAME move-route DOMAIN [--hostname HOSTNAME] [--path PATH] -s OTHER_SPACE [-o OTHER_ORG]`
}

func (cmd MoveRouteCommand) Examples() string {
return `
CF_NAME move-route example.com --hostname myHost --path foo -s TargetSpace -o TargetOrg # myhost.example.com/foo
CF_NAME move-route example.com --hostname myHost -s TargetSpace # myhost.example.com
CF_NAME move-route example.com --hostname myHost -s TargetSpace -o TargetOrg # myhost.example.com`
}

func (cmd MoveRouteCommand) Execute(args []string) error {
err := cmd.SharedActor.CheckTarget(true, true)
if err != nil {
return err
}

user, err := cmd.Actor.GetCurrentUser()
if err != nil {
return err
}

domain, warnings, err := cmd.Actor.GetDomainByName(cmd.RequireArgs.Domain)
cmd.UI.DisplayWarnings(warnings)
if err != nil {
return err
}

path := cmd.Path.Path
route, warnings, err := cmd.Actor.GetRouteByAttributes(domain, cmd.Hostname, path, 0)
cmd.UI.DisplayWarnings(warnings)
if err != nil {
if _, ok := err.(actionerror.RouteNotFoundError); ok {
cmd.UI.DisplayText("Can not transfer ownership of route:")
return err
}
}

destinationOrgName := cmd.DestinationOrg

if destinationOrgName == "" {
destinationOrgName = cmd.Config.TargetedOrganizationName()
}

destinationOrg, warnings, err := cmd.Actor.GetOrganizationByName(destinationOrgName)

if err != nil {
if _, ok := err.(actionerror.OrganizationNotFoundError); ok {
cmd.UI.DisplayText("Can not transfer ownership of route:")
return err
}
}

targetedSpace, warnings, err := cmd.Actor.GetSpaceByNameAndOrganization(cmd.DestinationSpace, destinationOrg.GUID)
if err != nil {
if _, ok := err.(actionerror.SpaceNotFoundError); ok {
cmd.UI.DisplayText("Can not transfer ownership of route:")
return err
}
}

url := desiredURL(domain.Name, cmd.Hostname, path, 0)
cmd.UI.DisplayTextWithFlavor("Move ownership of route {{.URL}} to space {{.DestinationSpace}} as {{.User}}",
map[string]interface{}{
"URL": url,
"DestinationSpace": cmd.DestinationSpace,
"User": user.Name,
})
warnings, err = cmd.Actor.MoveRoute(
route.GUID,
targetedSpace.GUID,
)
cmd.UI.DisplayWarnings(warnings)
if err != nil {
return err
}
cmd.UI.DisplayOK()

return nil
}
Loading