github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/commands/service/unbind_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/flags" 12 . "code.cloudfoundry.org/cli/cf/i18n" 13 "code.cloudfoundry.org/cli/cf/models" 14 "code.cloudfoundry.org/cli/cf/requirements" 15 "code.cloudfoundry.org/cli/cf/terminal" 16 ) 17 18 //go:generate counterfeiter . RouteServiceUnbinder 19 20 type RouteServiceUnbinder interface { 21 UnbindRoute(route models.Route, serviceInstance models.ServiceInstance) error 22 } 23 24 type UnbindRouteService struct { 25 ui terminal.UI 26 config coreconfig.Reader 27 routeRepo api.RouteRepository 28 routeServiceBindingRepo api.RouteServiceBindingRepository 29 domainReq requirements.DomainRequirement 30 serviceInstanceReq requirements.ServiceInstanceRequirement 31 } 32 33 func init() { 34 commandregistry.Register(&UnbindRouteService{}) 35 } 36 37 func (cmd *UnbindRouteService) MetaData() commandregistry.CommandMetadata { 38 fs := make(map[string]flags.FlagSet) 39 fs["hostname"] = &flags.StringFlag{Name: "hostname", ShortName: "n", Usage: T("Hostname used in combination with DOMAIN to specify the route to unbind")} 40 fs["path"] = &flags.StringFlag{Name: "path", Usage: T("Path for HTTP route")} 41 fs["f"] = &flags.BoolFlag{ShortName: "f", Usage: T("Force unbinding without confirmation")} 42 43 return commandregistry.CommandMetadata{ 44 Name: "unbind-route-service", 45 ShortName: "urs", 46 Description: T("Unbind a service instance from an HTTP route"), 47 Usage: []string{ 48 T("CF_NAME unbind-route-service DOMAIN SERVICE_INSTANCE [--hostname HOSTNAME] [--path PATH] [-f]"), 49 }, 50 Examples: []string{ 51 "CF_NAME unbind-route-service example.com myratelimiter --hostname myapp --path foo", 52 }, 53 Flags: fs, 54 } 55 } 56 57 func (cmd *UnbindRouteService) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) { 58 if len(fc.Args()) != 2 { 59 cmd.ui.Failed(T("Incorrect Usage. Requires DOMAIN and SERVICE_INSTANCE as arguments\n\n") + commandregistry.Commands.CommandUsage("unbind-route-service")) 60 return nil, fmt.Errorf("Incorrect usage: %d arguments of %d required", len(fc.Args()), 2) 61 } 62 63 serviceName := fc.Args()[1] 64 cmd.serviceInstanceReq = requirementsFactory.NewServiceInstanceRequirement(serviceName) 65 66 domainName := fc.Args()[0] 67 cmd.domainReq = requirementsFactory.NewDomainRequirement(domainName) 68 69 reqs := []requirements.Requirement{ 70 requirementsFactory.NewLoginRequirement(), 71 cmd.domainReq, 72 cmd.serviceInstanceReq, 73 } 74 return reqs, nil 75 } 76 77 func (cmd *UnbindRouteService) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 78 cmd.ui = deps.UI 79 cmd.config = deps.Config 80 cmd.routeRepo = deps.RepoLocator.GetRouteRepository() 81 cmd.routeServiceBindingRepo = deps.RepoLocator.GetRouteServiceBindingRepository() 82 return cmd 83 } 84 85 func (cmd *UnbindRouteService) Execute(c flags.FlagContext) error { 86 var port int 87 88 host := c.String("hostname") 89 domain := cmd.domainReq.GetDomain() 90 path := c.String("path") 91 if !strings.HasPrefix(path, "/") && len(path) > 0 { 92 path = fmt.Sprintf("/%s", path) 93 } 94 95 route, err := cmd.routeRepo.Find(host, domain, path, port) 96 if err != nil { 97 return err 98 } 99 100 serviceInstance := cmd.serviceInstanceReq.GetServiceInstance() 101 confirmed := c.Bool("f") 102 if !confirmed { 103 confirmed = cmd.ui.Confirm(T("Unbinding may leave apps mapped to route {{.URL}} vulnerable; e.g. if service instance {{.ServiceInstanceName}} provides authentication. Do you want to proceed?", 104 map[string]interface{}{ 105 "URL": route.URL(), 106 "ServiceInstanceName": serviceInstance.Name, 107 })) 108 109 if !confirmed { 110 cmd.ui.Warn(T("Unbind cancelled")) 111 return nil 112 } 113 } 114 115 cmd.ui.Say(T("Unbinding route {{.URL}} from service instance {{.ServiceInstanceName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...", 116 map[string]interface{}{ 117 "ServiceInstanceName": terminal.EntityNameColor(serviceInstance.Name), 118 "URL": terminal.EntityNameColor(route.URL()), 119 "OrgName": terminal.EntityNameColor(cmd.config.OrganizationFields().Name), 120 "SpaceName": terminal.EntityNameColor(cmd.config.SpaceFields().Name), 121 "CurrentUser": terminal.EntityNameColor(cmd.config.Username()), 122 })) 123 124 err = cmd.UnbindRoute(route, serviceInstance) 125 if err != nil { 126 httpError, ok := err.(errors.HTTPError) 127 if ok && httpError.ErrorCode() == errors.InvalidRelation { 128 cmd.ui.Warn(T("Route {{.Route}} was not bound to service instance {{.ServiceInstance}}.", map[string]interface{}{"Route": route.URL(), "ServiceInstance": serviceInstance.Name})) 129 } else { 130 return err 131 } 132 } 133 134 cmd.ui.Ok() 135 return nil 136 } 137 138 func (cmd *UnbindRouteService) UnbindRoute(route models.Route, serviceInstance models.ServiceInstance) error { 139 return cmd.routeServiceBindingRepo.Unbind(serviceInstance.GUID, route.GUID, serviceInstance.IsUserProvided()) 140 }