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

[RFC0027] CLI command "update-route" to manage generic per-route options #2

Closed
Closed
Show file tree
Hide file tree
Changes from all 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
137 changes: 137 additions & 0 deletions cf/commands/route/update-route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package route

import (
"code.cloudfoundry.org/cli/cf/errors"
"code.cloudfoundry.org/cli/cf/models"
"fmt"
"strings"

"code.cloudfoundry.org/cli/cf/api"
"code.cloudfoundry.org/cli/cf/commandregistry"
"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
"code.cloudfoundry.org/cli/cf/flags"
. "code.cloudfoundry.org/cli/cf/i18n"
"code.cloudfoundry.org/cli/cf/requirements"
"code.cloudfoundry.org/cli/cf/terminal"
)

type UpdateRoute struct {
ui terminal.UI
config coreconfig.Reader
routeRepo api.RouteRepository
domainRepo api.DomainRepository
domainReq requirements.DomainRequirement
}

func init() {
commandregistry.Register(&UpdateRoute{})
}

func (cmd *UpdateRoute) MetaData() commandregistry.CommandMetadata {
fs := make(map[string]flags.FlagSet)
fs["hostname"] = &flags.StringFlag{Name: "hostname", ShortName: "n", Usage: T("Hostname for the HTTP route (required for shared domains)")}
fs["path"] = &flags.StringFlag{Name: "path", Usage: T("Path for the HTTP route")}
fs["option"] = &flags.StringSliceFlag{Name: "option", ShortName: "o", Usage: T("Set the value of a per-route option")}
fs["remove-option"] = &flags.BoolFlag{Name: "remove-option", ShortName: "r", Usage: T("Remove an option with the given name")}

return commandregistry.CommandMetadata{
Name: "update-route",
Description: T("Update an existing route"),
Usage: []string{
fmt.Sprintf("%s:\n", T("Update an existing HTTP route")),
" CF_NAME update-route ",
fmt.Sprintf("%s ", T("DOMAIN")),
fmt.Sprintf("[--hostname %s] ", T("HOSTNAME")),
fmt.Sprintf("[--path %s]\n\n", T("PATH")),
fmt.Sprintf("[--option %s=%s]\n\n", T("OPTION"), T("VALUE")),
fmt.Sprintf("[--remove-option %s]\n\n", T("OPTION‚")),
},
Examples: []string{
"CF_NAME update-route example.com -o loadbalancing=round-robin",
"CF_NAME update-route example.com -o loadbalancing=least-connection",
"CF_NAME update-route example.com -r loadbalancing",
"CF_NAME map-route my-app example.com --hostname myhost --path foo -o loadbalancing=round-robin",
},
Flags: fs,
}
}

func (cmd *UpdateRoute) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) {
if len(fc.Args()) != 1 {
cmd.ui.Failed(T("Incorrect Usage. Requires DOMAIN as an argument\n\n") + commandregistry.Commands.CommandUsage("update-route"))
return nil, fmt.Errorf("incorrect usage: %d arguments of %d required", len(fc.Args()), 1)
}

domainName := fc.Args()[0]
cmd.domainReq = requirementsFactory.NewDomainRequirement(domainName)

var reqs []requirements.Requirement

reqs = append(reqs, []requirements.Requirement{
requirementsFactory.NewLoginRequirement(),
cmd.domainReq,
}...)

return reqs, nil
}

func (cmd *UpdateRoute) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command {
cmd.ui = deps.UI
cmd.config = deps.Config
cmd.routeRepo = deps.RepoLocator.GetRouteRepository()
cmd.domainRepo = deps.RepoLocator.GetDomainRepository()

return cmd
}

func (cmd *UpdateRoute) Execute(c flags.FlagContext) error {
domain := c.Args()[0]
rawHostNameFromFlag := c.String("n")
host := strings.ToLower(rawHostNameFromFlag)
path := c.String("path")
domainFields := cmd.domainReq.GetDomain()
option := c.String("o")
removeOption := c.String("r")
port := 0

url := (&models.RoutePresenter{
Host: host,
Domain: domain,
Path: path,
Port: port,
}).URL()

route, err := cmd.routeRepo.Find(host, domainFields, path, 0)
if err != nil {
if _, ok := err.(*errors.ModelNotFoundError); ok {
cmd.ui.Warn(T("Route with domain '{{.URL}}' does not exist.",
map[string]interface{}{"URL": url}))
return nil
}
return err
}

if c.IsSet("o") {
key, value, found := strings.Cut(option, "=")
if found {
cmd.ui.Say(T("Setting route option {{.Option}} for {{.URL}}...", map[string]interface{}{
"Option": terminal.EntityNameColor(key),
"URL": terminal.EntityNameColor(url)}))
route.Options[key] = value
} else {
cmd.ui.Say(T("Wrong route option format {{.Option}} for {{.URL}}...", map[string]interface{}{
"Option": terminal.FailureColor(option),
"URL": terminal.EntityNameColor(url)}))
}
}

if c.IsSet("r") {
cmd.ui.Say(T("Removing route option {{.Option}} for {{.URL}}...", map[string]interface{}{
"Option": terminal.EntityNameColor(removeOption),
"URL": terminal.EntityNameColor(url)}))
delete(route.Options, removeOption)
}

cmd.ui.Ok()
return nil
}
29 changes: 16 additions & 13 deletions cf/models/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
)

type Route struct {
GUID string
Host string
Domain DomainFields
Path string
Port int
GUID string
Host string
Domain DomainFields
Path string
Port int
Options map[string]string

Space SpaceFields
Apps []ApplicationFields
Expand All @@ -20,18 +21,20 @@ type Route struct {

func (r Route) URL() string {
return (&RoutePresenter{
Host: r.Host,
Domain: r.Domain.Name,
Path: r.Path,
Port: r.Port,
Host: r.Host,
Domain: r.Domain.Name,
Path: r.Path,
Port: r.Port,
Options: r.Options,
}).URL()
}

type RoutePresenter struct {
Host string
Domain string
Path string
Port int
Host string
Domain string
Path string
Port int
Options map[string]string
}

func (r *RoutePresenter) URL() string {
Expand Down
Loading