github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/cf/commands/service/bind_route_service.go (about) 1 package service 2 3 import ( 4 "fmt" 5 "strings" 6 7 "code.cloudfoundry.org/cli/cf/api" 8 "code.cloudfoundry.org/cli/cf/commandregistry" 9 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 10 "code.cloudfoundry.org/cli/cf/errors" 11 "code.cloudfoundry.org/cli/cf/flagcontext" 12 "code.cloudfoundry.org/cli/cf/flags" 13 . "code.cloudfoundry.org/cli/cf/i18n" 14 "code.cloudfoundry.org/cli/cf/requirements" 15 "code.cloudfoundry.org/cli/cf/terminal" 16 ) 17 18 type BindRouteService struct { 19 ui terminal.UI 20 config coreconfig.Reader 21 routeRepo api.RouteRepository 22 routeServiceBindingRepo api.RouteServiceBindingRepository 23 domainReq requirements.DomainRequirement 24 serviceInstanceReq requirements.ServiceInstanceRequirement 25 } 26 27 func init() { 28 commandregistry.Register(&BindRouteService{}) 29 } 30 31 func (cmd *BindRouteService) MetaData() commandregistry.CommandMetadata { 32 fs := make(map[string]flags.FlagSet) 33 fs["hostname"] = &flags.StringFlag{ 34 Name: "hostname", 35 ShortName: "n", 36 Usage: T("Hostname used in combination with DOMAIN to specify the route to bind"), 37 } 38 fs["path"] = &flags.StringFlag{ 39 Name: "path", 40 Usage: T("Path for the HTTP route"), 41 } 42 fs["parameters"] = &flags.StringFlag{ 43 ShortName: "c", 44 Usage: T("Valid JSON object containing service-specific configuration parameters, provided inline or in a file. For a list of supported configuration parameters, see documentation for the particular service offering."), 45 } 46 fs["f"] = &flags.BackwardsCompatibilityFlag{} 47 48 return commandregistry.CommandMetadata{ 49 Name: "bind-route-service", 50 ShortName: "brs", 51 Description: T("Bind a service instance to an HTTP route"), 52 Usage: []string{ 53 T(`CF_NAME bind-route-service DOMAIN SERVICE_INSTANCE [--hostname HOSTNAME] [--path PATH] [-c PARAMETERS_AS_JSON]`), 54 }, 55 Examples: []string{ 56 `CF_NAME bind-route-service example.com myratelimiter --hostname myapp --path foo`, 57 `CF_NAME bind-route-service example.com myratelimiter -c file.json`, 58 `CF_NAME bind-route-service example.com myratelimiter -c '{"valid":"json"}'`, 59 ``, 60 T(`In Windows PowerShell use double-quoted, escaped JSON: "{\"valid\":\"json\"}"`), 61 T(`In Windows Command Line use single-quoted, escaped JSON: '{\"valid\":\"json\"}'`), 62 }, 63 Flags: fs, 64 } 65 } 66 67 func (cmd *BindRouteService) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) { 68 if len(fc.Args()) != 2 { 69 cmd.ui.Failed(T("Incorrect Usage. Requires DOMAIN and SERVICE_INSTANCE as arguments\n\n") + commandregistry.Commands.CommandUsage("bind-route-service")) 70 return nil, fmt.Errorf("Incorrect usage: %d arguments of %d required", len(fc.Args()), 2) 71 } 72 73 domainName := fc.Args()[0] 74 cmd.domainReq = requirementsFactory.NewDomainRequirement(domainName) 75 76 serviceName := fc.Args()[1] 77 cmd.serviceInstanceReq = requirementsFactory.NewServiceInstanceRequirement(serviceName) 78 79 reqs := []requirements.Requirement{ 80 requirementsFactory.NewLoginRequirement(), 81 cmd.domainReq, 82 cmd.serviceInstanceReq, 83 } 84 return reqs, nil 85 } 86 87 func (cmd *BindRouteService) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 88 cmd.ui = deps.UI 89 cmd.config = deps.Config 90 cmd.routeRepo = deps.RepoLocator.GetRouteRepository() 91 cmd.routeServiceBindingRepo = deps.RepoLocator.GetRouteServiceBindingRepository() 92 return cmd 93 } 94 95 func (cmd *BindRouteService) Execute(c flags.FlagContext) error { 96 var port int 97 98 host := c.String("hostname") 99 domain := cmd.domainReq.GetDomain() 100 path := c.String("path") 101 if !strings.HasPrefix(path, "/") && len(path) > 0 { 102 path = fmt.Sprintf("/%s", path) 103 } 104 105 var parameters string 106 107 if c.IsSet("parameters") { 108 jsonBytes, err := flagcontext.GetContentsFromFlagValue(c.String("parameters")) 109 if err != nil { 110 return err 111 } 112 parameters = string(jsonBytes) 113 } 114 115 route, err := cmd.routeRepo.Find(host, domain, path, port) 116 if err != nil { 117 return err 118 } 119 120 serviceInstance := cmd.serviceInstanceReq.GetServiceInstance() 121 122 cmd.ui.Say(T("Binding route {{.URL}} to service instance {{.ServiceInstanceName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...", 123 map[string]interface{}{ 124 "ServiceInstanceName": terminal.EntityNameColor(serviceInstance.Name), 125 "URL": terminal.EntityNameColor(route.URL()), 126 "OrgName": terminal.EntityNameColor(cmd.config.OrganizationFields().Name), 127 "SpaceName": terminal.EntityNameColor(cmd.config.SpaceFields().Name), 128 "CurrentUser": terminal.EntityNameColor(cmd.config.Username()), 129 })) 130 131 err = cmd.routeServiceBindingRepo.Bind(serviceInstance.GUID, route.GUID, serviceInstance.IsUserProvided(), parameters) 132 if err != nil { 133 if httpErr, ok := err.(errors.HTTPError); ok && httpErr.ErrorCode() == errors.ServiceInstanceAlreadyBoundToSameRoute { 134 cmd.ui.Warn(T("Route {{.URL}} is already bound to service instance {{.ServiceInstanceName}}.", 135 map[string]interface{}{ 136 "URL": route.URL(), 137 "ServiceInstanceName": serviceInstance.Name, 138 })) 139 } else { 140 return err 141 } 142 } 143 144 cmd.ui.Ok() 145 return nil 146 }