Skip to content

Commit

Permalink
push supports --route-path option
Browse files Browse the repository at this point in the history
[#110521980]

Signed-off-by: Muhammad Altaf <malik.altaf@gmail.com>
  • Loading branch information
Kris Hicks authored and malik-altaf committed Jan 8, 2016
1 parent 049654f commit 563cbf5
Show file tree
Hide file tree
Showing 16 changed files with 119 additions and 62 deletions.
43 changes: 33 additions & 10 deletions cf/commands/application/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"strings"

"github.com/blang/semver"
. "github.com/cloudfoundry/cli/cf/i18n"
"github.com/cloudfoundry/cli/flags"
"github.com/cloudfoundry/cli/flags/flag"
Expand Down Expand Up @@ -73,28 +74,41 @@ func (cmd *Push) MetaData() command_registry.CommandMetadata {
fs["no-route"] = &cliFlags.BoolFlag{Name: "no-route", Usage: T("Do not map a route to this app and remove routes from previous pushes of this app.")}
fs["no-start"] = &cliFlags.BoolFlag{Name: "no-start", Usage: T("Do not start an app after pushing")}
fs["random-route"] = &cliFlags.BoolFlag{Name: "random-route", Usage: T("Create a random route for this app")}
fs["route-path"] = &cliFlags.StringFlag{Name: "route-path", Usage: T("Path for the route")}

return command_registry.CommandMetadata{
Name: "push",
ShortName: "p",
Description: T("Push a new app or sync changes to an existing app"),
Usage: T("Push a single app (with or without a manifest):\n") + T(" CF_NAME push APP_NAME [-b BUILDPACK_NAME] [-c COMMAND] [-d DOMAIN] [-f MANIFEST_PATH] [--docker-image DOCKER_IMAGE]\n") + T(" [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n") +
Usage: T("Push a single app (with or without a manifest):\n") + T(" CF_NAME push APP_NAME [-b BUILDPACK_NAME] [-c COMMAND] [-d DOMAIN] [-f MANIFEST_PATH] [--docker-image DOCKER_IMAGE]\n") + T(" [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n") +
" [--no-hostname] [--no-manifest] [--no-route] [--no-start]\n" +
"\n" + T(" Push multiple apps with a manifest:\n") + T(" CF_NAME push [-f MANIFEST_PATH]\n"),
Flags: fs,
}
}

func (cmd *Push) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) (reqs []requirements.Requirement, err error) {
func (cmd *Push) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) {
if len(fc.Args()) > 1 {
cmd.ui.Failed(T("Incorrect Usage.\n\n") + command_registry.Commands.CommandUsage("push"))
}

reqs = []requirements.Requirement{
var reqs []requirements.Requirement

if fc.String("route-path") != "" {
requiredVersion, err := semver.Make("2.36.0")
if err != nil {
panic(err.Error())
}

reqs = append(reqs, requirementsFactory.NewMinAPIVersionRequirement("Option '--route-path'", requiredVersion))
}

reqs = append(reqs, []requirements.Requirement{
requirementsFactory.NewLoginRequirement(),
requirementsFactory.NewTargetedSpaceRequirement(),
}
return
}...)

return reqs, nil
}

func (cmd *Push) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
Expand Down Expand Up @@ -218,18 +232,22 @@ func (cmd *Push) updateRoutes(routeActor actors.RouteActor, app models.Applicati

func (cmd *Push) processDomainsAndBindRoutes(appParams models.AppParams, routeActor actors.RouteActor, app models.Application, domain models.DomainFields) {
if appParams.IsHostEmpty() {
cmd.createAndBindRoute(nil, appParams.UseRandomHostname, routeActor, app, appParams.NoHostname, domain)
cmd.createAndBindRoute(nil, appParams.UseRandomHostname, routeActor, app, appParams.NoHostname, domain, appParams.RoutePath)
} else {
for _, host := range *(appParams.Hosts) {
cmd.createAndBindRoute(&host, appParams.UseRandomHostname, routeActor, app, appParams.NoHostname, domain)
cmd.createAndBindRoute(&host, appParams.UseRandomHostname, routeActor, app, appParams.NoHostname, domain, appParams.RoutePath)
}
}
}

func (cmd *Push) createAndBindRoute(host *string, UseRandomHostname bool, routeActor actors.RouteActor, app models.Application, noHostName bool, domain models.DomainFields) {
func (cmd *Push) createAndBindRoute(host *string, UseRandomHostname bool, routeActor actors.RouteActor, app models.Application, noHostName bool, domain models.DomainFields, routePath *string) {
hostname := cmd.hostnameForApp(host, UseRandomHostname, app.Name, noHostName)
path := "" // not currently configurable in the manifest
route := routeActor.FindOrCreateRoute(hostname, domain, path)
var route models.Route
if routePath != nil {
route = routeActor.FindOrCreateRoute(hostname, domain, *routePath)
} else {
route = routeActor.FindOrCreateRoute(hostname, domain, "")
}
routeActor.BindRoute(app, route)
}

Expand Down Expand Up @@ -542,6 +560,11 @@ func (cmd *Push) getAppParamsFromContext(c flags.FlagContext) (appParams models.
appParams.Hosts = &[]string{c.String("n")}
}

if c.String("route-path") != "" {
routePath := c.String("route-path")
appParams.RoutePath = &routePath
}

if c.String("b") != "" {
buildpack := c.String("b")
if buildpack == "null" || buildpack == "default" {
Expand Down
41 changes: 33 additions & 8 deletions cf/commands/application/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ var _ = Describe("Push Command", func() {
ui = new(testterm.FakeUI)
configRepo = testconfig.NewRepositoryWithDefaults()

requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: true, TargetedSpaceSuccess: true}
requirementsFactory = &testreq.FakeReqFactory{
LoginSuccess: true,
TargetedSpaceSuccess: true,
MinAPIVersionSuccess: true,
}

zipper = &fakeappfiles.FakeZipper{}
appfiles = &fakeappfiles.FakeAppFiles{}
Expand Down Expand Up @@ -199,6 +203,26 @@ var _ = Describe("Push Command", func() {
It("fails when provided too many args", func() {
Expect(callPush("-p", "path", "too-much", "app-name")).To(BeFalse())
})

Context("when the CC API version is too low", func() {
BeforeEach(func() {
requirementsFactory.MinAPIVersionSuccess = false
})

It("fails when provided the --route-path option", func() {
Expect(callPush("--route-path", "the-path", "app-name")).To(BeFalse())
})
})

Context("when the CC API version is not too low", func() {
BeforeEach(func() {
requirementsFactory.MinAPIVersionSuccess = true
})

It("does not fail when provided the --route-path option", func() {
Expect(callPush("--route-path", "the-path", "app-name")).To(BeTrue())
})
})
})

Describe("when pushing a new app", func() {
Expand Down Expand Up @@ -434,6 +458,7 @@ var _ = Describe("Push Command", func() {
"-c", "unicorn -c config/unicorn.rb -D",
"-d", "bar.cf-app.com",
"-n", "my-hostname",
"--route-path", "my-route-path",
"-k", "4G",
"-i", "3",
"-m", "2G",
Expand All @@ -450,9 +475,9 @@ var _ = Describe("Push Command", func() {
[]string{"OK"},
[]string{"Creating app", "app-name"},
[]string{"OK"},
[]string{"Creating route", "my-hostname.bar.cf-app.com"},
[]string{"Creating route", "my-hostname.bar.cf-app.com/my-route-path"},
[]string{"OK"},
[]string{"Binding", "my-hostname.bar.cf-app.com", "app-name"},
[]string{"Binding", "my-hostname.bar.cf-app.com/my-route-path", "app-name"},
[]string{"Uploading", "app-name"},
[]string{"OK"},
))
Expand All @@ -478,7 +503,7 @@ var _ = Describe("Push Command", func() {
createdHost, createdDomainFields, createdPath := routeRepo.CreateArgsForCall(0)
Expect(createdHost).To(Equal("my-hostname"))
Expect(createdDomainFields.Guid).To(Equal("bar-domain-guid"))
Expect(createdPath).To(BeEmpty())
Expect(createdPath).To(Equal("my-route-path"))

Expect(routeRepo.BindCallCount()).To(Equal(1))
boundRouteGUID, boundAppGUID := routeRepo.BindArgsForCall(0)
Expand Down Expand Up @@ -550,7 +575,7 @@ var _ = Describe("Push Command", func() {
return nil
}

callPush("-t", "111", "app-name")
callPush("-t", "111", "--route-path", "the-route-path", "app-name")

Expect(routeRepo.FindCallCount()).To(Equal(1))
host, _, _ := routeRepo.FindArgsForCall(0)
Expand All @@ -560,7 +585,7 @@ var _ = Describe("Push Command", func() {
createdHost, createdDomainFields, createdPath := routeRepo.CreateArgsForCall(0)
Expect(createdHost).To(Equal("app-name"))
Expect(createdDomainFields.Guid).To(Equal("shared-domain-guid"))
Expect(createdPath).To(BeEmpty())
Expect(createdPath).To(Equal("the-route-path"))

Expect(routeRepo.BindCallCount()).To(Equal(1))
boundRouteGUID, boundAppGUID := routeRepo.BindArgsForCall(0)
Expand All @@ -570,9 +595,9 @@ var _ = Describe("Push Command", func() {
Expect(ui.Outputs).To(ContainSubstrings(
[]string{"Creating app", "app-name", "my-org", "my-space"},
[]string{"OK"},
[]string{"Creating", "app-name.shared.cf-app.com"},
[]string{"Creating", "app-name.shared.cf-app.com/the-route-path"},
[]string{"OK"},
[]string{"Binding", "app-name.shared.cf-app.com"},
[]string{"Binding", "app-name.shared.cf-app.com/the-route-path"},
[]string{"OK"},
[]string{"Uploading app-name"},
[]string{"OK"},
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/de_DE.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/en_US.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"modified": false
},
{
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/es_ES.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/fr_FR.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/it_IT.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/ja_JP.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/ko_KR.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/pt_BR.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/zh_Hans.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 2 additions & 2 deletions cf/i18n/resources/zh_Hant.all.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@
"modified": false
},
{
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"id": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] [--route-path ROUTE_PATH]\n",
"translation": " [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u HEALTH_CHECK_TYPE] \n",
"modified": false
"modified": true
},
{
"id": " added as '",
Expand Down
4 changes: 4 additions & 0 deletions cf/models/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type AppParams struct {
Diego *bool
EnableSsh *bool
Hosts *[]string
RoutePath *string
InstanceCount *int
Memory *int64
Name *string
Expand Down Expand Up @@ -127,6 +128,9 @@ func (app *AppParams) Merge(other *AppParams) {
if other.Hosts != nil {
app.Hosts = other.Hosts
}
if other.RoutePath != nil {
app.RoutePath = other.RoutePath
}
if other.InstanceCount != nil {
app.InstanceCount = other.InstanceCount
}
Expand Down
4 changes: 4 additions & 0 deletions cf/requirements/min_api_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func (r MinAPIVersionRequirement) Execute() bool {
r.ui.Failed(T("Unable to parse CC API Version '{{.APIVersion}}'", map[string]interface{}{
"APIVersion": r.config.ApiVersion(),
}))

return false
}

if apiVersion.LT(r.requiredVersion) {
Expand All @@ -48,6 +50,8 @@ func (r MinAPIVersionRequirement) Execute() bool {
"Feature": r.feature,
"RequiredVersion": r.requiredVersion.String(),
}))

return false
}

return true
Expand Down
40 changes: 20 additions & 20 deletions cf/resources/i18n_resources.go

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions testhelpers/requirements/fake_req_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ type FakeReqFactory struct {

Buildpack models.Buildpack

MinAPIVersionCommandName string
MinAPIVersionFeatureName string
MinAPIVersionRequiredVersion semver.Version
MinAPIVersionSuccess bool
}

func (f *FakeReqFactory) NewApplicationRequirement(name string) requirements.ApplicationRequirement {
Expand Down Expand Up @@ -105,10 +106,10 @@ func (f *FakeReqFactory) NewApiEndpointRequirement() requirements.Requirement {
return FakeRequirement{f, f.ApiEndpointSuccess}
}

func (f *FakeReqFactory) NewMinAPIVersionRequirement(commandName string, requiredVersion semver.Version) requirements.Requirement {
f.MinAPIVersionCommandName = commandName
func (f *FakeReqFactory) NewMinAPIVersionRequirement(featureName string, requiredVersion semver.Version) requirements.Requirement {
f.MinAPIVersionFeatureName = featureName
f.MinAPIVersionRequiredVersion = requiredVersion
return FakeRequirement{f, true}
return FakeRequirement{f, f.MinAPIVersionSuccess}
}

type FakeRequirement struct {
Expand Down

0 comments on commit 563cbf5

Please sign in to comment.