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