/* * This function must be implemented by any plugin because it is part of the * plugin interface defined by the core CLI. * * Run(....) is the entry point when the core CLI is invoking a command defined * by a plugin. The first parameter, plugin.CliConnection, is a struct that can * be used to invoke cli commands. The second paramter, args, is a slice of * strings. args[0] will be the name of the command, and will be followed by * any additional arguments a cli user typed in. * * Any error handling should be handled with the plugin itself (this means printing * user facing errors). The CLI will exit 0 if the plugin exits 0 and will exit * 1 should the plugin exits nonzero. */ func (c *DoctorPlugin) Run(cliConnection plugin.CliConnection, args []string) { fmt.Printf("\n\n") var triageApps []string var triageRoutes []string var triageServices []string c.ui = terminal.NewUI(os.Stdin, terminal.NewTeePrinter()) c.ui.Say(terminal.WarningColor("doctor: time to triage cloudfoundry")) fmt.Printf("\n") c.CFMainChecks(cliConnection) listOfRunningApps := c.AppsStateRunning(cliConnection) listOfStoppedApps := c.AppsStateStopped(cliConnection) triageApps = c.CheckUpApps(cliConnection, triageApps, listOfRunningApps, listOfStoppedApps) triageRoutes = c.CheckUpRoutes(cliConnection, triageRoutes) triageServices = c.CheckUpServices(cliConnection, triageServices) if len(triageApps) == 0 && len(triageRoutes) == 0 && len(triageServices) == 0 { c.ui.Say(terminal.SuccessColor("doctor: Everything looks OK!")) return } // doctor run results if len(triageApps) > 0 { c.ui.Say(terminal.WarningColor("Detected triage points for apps: ")) for _, v := range triageApps { c.ui.Say(terminal.LogStderrColor(strings.Split(v, "___")[0]+" <---> ") + terminal.LogStderrColor(strings.Split(v, "___")[1])) } } c.ui.Say(" ") if len(triageRoutes) > 0 { c.ui.Say(terminal.WarningColor("Following routes do not have any app bound to them:")) for _, y := range triageRoutes { c.ui.Say(terminal.LogStderrColor(y)) } } fmt.Printf("\n") if len(triageServices) > 0 { c.ui.Say(terminal.WarningColor("Following services do not have any app bound to them:")) for _, y := range triageServices { c.ui.Say(terminal.LogStderrColor(y)) } } }
func (cmd *Login) MetaData() commandregistry.CommandMetadata { fs := make(map[string]flags.FlagSet) fs["a"] = &flags.StringFlag{ShortName: "a", Usage: T("API endpoint (e.g. https://api.example.com)")} fs["u"] = &flags.StringFlag{ShortName: "u", Usage: T("Username")} fs["p"] = &flags.StringFlag{ShortName: "p", Usage: T("Password")} fs["o"] = &flags.StringFlag{ShortName: "o", Usage: T("Org")} fs["s"] = &flags.StringFlag{ShortName: "s", Usage: T("Space")} fs["sso"] = &flags.BoolFlag{Name: "sso", Usage: T("Use a one-time password to login")} fs["skip-ssl-validation"] = &flags.BoolFlag{Name: "skip-ssl-validation", Usage: T("Skip verification of the API endpoint. Not recommended!")} return commandregistry.CommandMetadata{ Name: "login", ShortName: "l", Description: T("Log user in"), Usage: []string{ T("CF_NAME login [-a API_URL] [-u USERNAME] [-p PASSWORD] [-o ORG] [-s SPACE]\n\n"), terminal.WarningColor(T("WARNING:\n Providing your password as a command line option is highly discouraged\n Your password may be visible to others and may be recorded in your shell history")), }, Examples: []string{ T("CF_NAME login (omit username and password to login interactively -- CF_NAME will prompt for both)"), T("CF_NAME login -u [email protected] -p pa55woRD (specify username and password as arguments)"), T("CF_NAME login -u [email protected] -p \"my password\" (use quotes for passwords with a space)"), T("CF_NAME login -u [email protected] -p \"\\\"password\\\"\" (escape quotes if used in password)"), T("CF_NAME login --sso (CF_NAME will provide a url to obtain a one-time password to login)"), }, Flags: fs, } }
func (cmd *unbindFromStagingGroup) Execute(context flags.FlagContext) error { name := context.Args()[0] cmd.ui.Say(T("Unbinding security group {{.security_group}} from defaults for staging as {{.username}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "username": terminal.EntityNameColor(cmd.configRepo.Username()), })) securityGroup, err := cmd.securityGroupRepo.Read(name) switch (err).(type) { case nil: case *errors.ModelNotFoundError: cmd.ui.Ok() cmd.ui.Warn(T("Security group {{.security_group}} {{.error_message}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "error_message": terminal.WarningColor(T("does not exist.")), })) return nil default: return err } err = cmd.stagingGroupRepo.UnbindFromStagingSet(securityGroup.GUID) if err != nil { return err } cmd.ui.Ok() cmd.ui.Say("\n\n") cmd.ui.Say(T("TIP: Changes will not apply to existing running applications until they are restarted.")) return nil }
func (cmd *removeFromRunningGroup) Run(context *cli.Context) { name := context.Args()[0] securityGroup, err := cmd.securityGroupRepo.Read(name) switch (err).(type) { case nil: case *errors.ModelNotFoundError: cmd.ui.Ok() cmd.ui.Warn(T("Security group {{.security_group}} {{.error_message}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "error_message": terminal.WarningColor(T("does not exist.")), })) return default: cmd.ui.Failed(err.Error()) } cmd.ui.Say(T("Removing security group {{.security_group}} from defaults for running as {{.username}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(securityGroup.Name), "username": terminal.EntityNameColor(cmd.configRepo.Username()), })) err = cmd.runningGroupRepo.RemoveFromRunningSet(securityGroup.Guid) if err != nil { cmd.ui.Failed(err.Error()) } cmd.ui.Ok() }
func (cmd API) setAPIEndpoint(endpoint string, skipSSL bool, cmdName string) error { if strings.HasSuffix(endpoint, "/") { endpoint = strings.TrimSuffix(endpoint, "/") } cmd.config.SetSSLDisabled(skipSSL) refresher := coreconfig.APIConfigRefresher{ Endpoint: endpoint, EndpointRepo: cmd.endpointRepo, Config: cmd.config, } warning, err := refresher.Refresh() if err != nil { cmd.config.SetAPIEndpoint("") cmd.config.SetSSLDisabled(false) switch typedErr := err.(type) { case *errors.InvalidSSLCert: cfAPICommand := terminal.CommandColor(fmt.Sprintf("%s %s --skip-ssl-validation", cf.Name, cmdName)) tipMessage := fmt.Sprintf(T("TIP: Use '{{.APICommand}}' to continue with an insecure API endpoint", map[string]interface{}{"APICommand": cfAPICommand})) return errors.New(T("Invalid SSL Cert for {{.URL}}\n{{.TipMessage}}", map[string]interface{}{"URL": typedErr.URL, "TipMessage": tipMessage})) default: return typedErr } } if warning != nil { cmd.ui.Say(terminal.WarningColor(warning.Warn())) } return nil }
func (cmd Api) setApiEndpoint(endpoint string, skipSSL bool, cmdName string) { if strings.HasSuffix(endpoint, "/") { endpoint = strings.TrimSuffix(endpoint, "/") } cmd.config.SetSSLDisabled(skipSSL) endpoint, err := cmd.endpointRepo.UpdateEndpoint(endpoint) if err != nil { cmd.config.SetApiEndpoint("") cmd.config.SetSSLDisabled(false) switch typedErr := err.(type) { case *errors.InvalidSSLCert: cfApiCommand := terminal.CommandColor(fmt.Sprintf("%s %s --skip-ssl-validation", cf.Name, cmdName)) tipMessage := fmt.Sprintf(T("TIP: Use '{{.ApiCommand}}' to continue with an insecure API endpoint", map[string]interface{}{"ApiCommand": cfApiCommand})) cmd.ui.Failed(T("Invalid SSL Cert for {{.URL}}\n{{.TipMessage}}", map[string]interface{}{"URL": typedErr.URL, "TipMessage": tipMessage})) default: cmd.ui.Failed(typedErr.Error()) } } if !strings.HasPrefix(endpoint, "https://") { cmd.ui.Say(terminal.WarningColor(T("Warning: Insecure http API endpoint detected: secure https API endpoints are recommended\n"))) } }
func (cmd CreateSecurityGroup) Run(context *cli.Context) { name := context.Args()[0] pathToJSONFile := context.String("json") rules, err := json.ParseJSON(pathToJSONFile) if err != nil { cmd.ui.Failed(err.Error()) } cmd.ui.Say(T("Creating security group {{.security_group}} as {{.username}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "username": terminal.EntityNameColor(cmd.configRepo.Username()), })) err = cmd.securityGroupRepo.Create(name, rules) httpErr, ok := err.(errors.HttpError) if ok && httpErr.ErrorCode() == errors.SECURITY_GROUP_EXISTS { cmd.ui.Ok() cmd.ui.Warn(T("Security group {{.security_group}} {{.error_message}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "error_message": terminal.WarningColor(T("already exists")), })) return } if err != nil { cmd.ui.Failed(err.Error()) } cmd.ui.Ok() }
func (cmd *Stop) Execute(c flags.FlagContext) { app := cmd.appReq.GetApplication() if app.State == "stopped" { cmd.ui.Say(terminal.WarningColor(T("App ") + app.Name + T(" is already stopped"))) } else { cmd.ApplicationStop(app, cmd.config.OrganizationFields().Name, cmd.config.SpaceFields().Name) } }
func (cmd Authenticate) Metadata() command_metadata.CommandMetadata { return command_metadata.CommandMetadata{ Name: "auth", Description: T("Authenticate user non-interactively"), Usage: T("CF_NAME auth USERNAME PASSWORD\n\n") + terminal.WarningColor(T("WARNING:\n Providing your password as a command line option is highly discouraged\n Your password may be visible to others and may be recorded in your shell history\n\n")) + T("EXAMPLE:\n") + T(" CF_NAME auth [email protected] \"my password\" (use quotes for passwords with a space)\n") + T(" CF_NAME auth [email protected] \"\\\"password\\\"\" (escape quotes if used in password)"), } }
func (cmd *Stop) Run(c *cli.Context) { app := cmd.appReq.GetApplication() if app.State == "stopped" { cmd.ui.Say(terminal.WarningColor(T("App ") + app.Name + T(" is already stopped"))) } else { cmd.ApplicationStop(app) } }
func (cmd *Stop) Execute(c flags.FlagContext) error { app := cmd.appReq.GetApplication() if app.State == models.ApplicationStateStopped { cmd.ui.Say(terminal.WarningColor(T("App ") + app.Name + T(" is already stopped"))) } else { _, err := cmd.ApplicationStop(app, cmd.config.OrganizationFields().Name, cmd.config.SpaceFields().Name) if err != nil { return err } } return nil }
func ColoredAppState(app models.ApplicationFields) string { appState := strings.ToLower(app.State) if app.RunningInstances == 0 { if appState == "stopped" { return appState } return terminal.CrashedColor(appState) } if app.RunningInstances < app.InstanceCount { return terminal.WarningColor(appState) } return appState }
func ColoredAppInstances(app models.ApplicationFields) string { healthString := fmt.Sprintf("%d/%d", app.RunningInstances, app.InstanceCount) if app.RunningInstances == 0 { if strings.ToLower(app.State) == "stopped" { return healthString } else { return terminal.CrashedColor(healthString) } } if app.RunningInstances < app.InstanceCount { return terminal.WarningColor(healthString) } return healthString }
func (cmd *Start) ApplicationStart(app models.Application, orgName, spaceName string) (updatedApp models.Application, err error) { if app.State == "started" { cmd.ui.Say(terminal.WarningColor(T("App ") + app.Name + T(" is already started"))) return } return cmd.ApplicationWatchStaging(app, orgName, spaceName, func(app models.Application) (models.Application, error) { cmd.ui.Say(T("Starting app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...", map[string]interface{}{ "AppName": terminal.EntityNameColor(app.Name), "OrgName": terminal.EntityNameColor(orgName), "SpaceName": terminal.EntityNameColor(spaceName), "CurrentUser": terminal.EntityNameColor(cmd.config.Username())})) state := "STARTED" return cmd.appRepo.Update(app.Guid, models.AppParams{State: &state}) }) }
func ColoredInstanceState(instance models.AppInstanceFields) (colored string) { state := string(instance.State) switch state { case "started", "running": colored = T("running") case "stopped": colored = terminal.StoppedColor(T("stopped")) case "flapping": colored = terminal.CrashedColor(T("crashing")) case "down": colored = terminal.CrashedColor(T("down")) case "starting": colored = terminal.AdvisoryColor(T("starting")) default: colored = terminal.WarningColor(state) } return }
func (cmd *CreateSecurityGroup) Execute(context flags.FlagContext) error { name := context.Args()[0] pathToJSONFile := context.Args()[1] rules, err := json.ParseJSONArray(pathToJSONFile) if err != nil { return errors.New(T(`Incorrect json format: file: {{.JSONFile}} Valid json file example: [ { "protocol": "tcp", "destination": "10.244.1.18", "ports": "3306" } ]`, map[string]interface{}{"JSONFile": pathToJSONFile})) } cmd.ui.Say(T("Creating security group {{.security_group}} as {{.username}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "username": terminal.EntityNameColor(cmd.configRepo.Username()), })) err = cmd.securityGroupRepo.Create(name, rules) httpErr, ok := err.(errors.HTTPError) if ok && httpErr.ErrorCode() == errors.SecurityGroupNameTaken { cmd.ui.Ok() cmd.ui.Warn(T("Security group {{.security_group}} {{.error_message}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "error_message": terminal.WarningColor(T("already exists")), })) return nil } if err != nil { return err } cmd.ui.Ok() return nil }
func (cmd CreateSecurityGroup) Run(context *cli.Context) { name := context.Args()[0] pathToJSONFile := context.Args()[1] rules, err := json.ParseJSON(pathToJSONFile) if err != nil { cmd.ui.Failed(T(`Incorrect json format: file: {{.JSONFile}} Valid json file example: [ { "protocol": "tcp", "destination": "10.244.1.18", "ports": "3306" } ]`, map[string]interface{}{"JSONFile": pathToJSONFile})) } cmd.ui.Say(T("Creating security group {{.security_group}} as {{.username}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "username": terminal.EntityNameColor(cmd.configRepo.Username()), })) err = cmd.securityGroupRepo.Create(name, rules) httpErr, ok := err.(errors.HttpError) if ok && httpErr.ErrorCode() == errors.SECURITY_GROUP_EXISTS { cmd.ui.Ok() cmd.ui.Warn(T("Security group {{.security_group}} {{.error_message}}", map[string]interface{}{ "security_group": terminal.EntityNameColor(name), "error_message": terminal.WarningColor(T("already exists")), })) return } if err != nil { cmd.ui.Failed(err.Error()) } cmd.ui.Ok() }
func (cmd *Start) ApplicationStart(app models.Application) (updatedApp models.Application, err error) { if app.State == "started" { cmd.ui.Say(terminal.WarningColor("App " + app.Name + " is already started")) return } stopLoggingChan := make(chan bool, 1) loggingStartedChan := make(chan bool) go cmd.tailStagingLogs(app, loggingStartedChan, stopLoggingChan) <-loggingStartedChan // block until we have established connection to Loggregator cmd.ui.Say("Starting app %s in org %s / space %s as %s...", terminal.EntityNameColor(app.Name), terminal.EntityNameColor(cmd.config.OrganizationFields().Name), terminal.EntityNameColor(cmd.config.SpaceFields().Name), terminal.EntityNameColor(cmd.config.Username()), ) state := "STARTED" updatedApp, apiErr := cmd.appRepo.Update(app.Guid, models.AppParams{State: &state}) if apiErr != nil { cmd.ui.Failed(apiErr.Error()) return } cmd.ui.Ok() cmd.waitForInstancesToStage(updatedApp) stopLoggingChan <- true cmd.ui.Say("") cmd.waitForOneRunningInstance(updatedApp) cmd.ui.Say(terminal.HeaderColor("\nApp started\n")) cmd.appDisplayer.ShowApp(updatedApp) return }
func (ui *browserUI) Warn(message string, args ...interface{}) { message = fmt.Sprintf(message, args...) ui.Say(terminal.WarningColor(message)) }