github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+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 requirementsFactory.NewTargetedSpaceRequirement(), 82 cmd.domainReq, 83 cmd.serviceInstanceReq, 84 } 85 return reqs, nil 86 } 87 88 func (cmd *BindRouteService) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 89 cmd.ui = deps.UI 90 cmd.config = deps.Config 91 cmd.routeRepo = deps.RepoLocator.GetRouteRepository() 92 cmd.routeServiceBindingRepo = deps.RepoLocator.GetRouteServiceBindingRepository() 93 return cmd 94 } 95 96 func (cmd *BindRouteService) Execute(c flags.FlagContext) error { 97 var port int 98 99 host := c.String("hostname") 100 domain := cmd.domainReq.GetDomain() 101 path := c.String("path") 102 if !strings.HasPrefix(path, "/") && len(path) > 0 { 103 path = fmt.Sprintf("/%s", path) 104 } 105 106 var parameters string 107 108 if c.IsSet("parameters") { 109 jsonBytes, err := flagcontext.GetContentsFromFlagValue(c.String("parameters")) 110 if err != nil { 111 return err 112 } 113 parameters = string(jsonBytes) 114 } 115 116 route, err := cmd.routeRepo.Find(host, domain, path, port) 117 if err != nil { 118 return err 119 } 120 121 serviceInstance := cmd.serviceInstanceReq.GetServiceInstance() 122 123 cmd.ui.Say(T("Binding route {{.URL}} to service instance {{.ServiceInstanceName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...", 124 map[string]interface{}{ 125 "ServiceInstanceName": terminal.EntityNameColor(serviceInstance.Name), 126 "URL": terminal.EntityNameColor(route.URL()), 127 "OrgName": terminal.EntityNameColor(cmd.config.OrganizationFields().Name), 128 "SpaceName": terminal.EntityNameColor(cmd.config.SpaceFields().Name), 129 "CurrentUser": terminal.EntityNameColor(cmd.config.Username()), 130 })) 131 132 err = cmd.routeServiceBindingRepo.Bind(serviceInstance.GUID, route.GUID, serviceInstance.IsUserProvided(), parameters) 133 if err != nil { 134 if httpErr, ok := err.(errors.HTTPError); ok && httpErr.ErrorCode() == errors.ServiceInstanceAlreadyBoundToSameRoute { 135 cmd.ui.Warn(T("Route {{.URL}} is already bound to service instance {{.ServiceInstanceName}}.", 136 map[string]interface{}{ 137 "URL": route.URL(), 138 "ServiceInstanceName": serviceInstance.Name, 139 })) 140 } else { 141 return err 142 } 143 } 144 145 cmd.ui.Ok() 146 return nil 147 }