github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/cf/commands/application/logs.go (about) 1 package application 2 3 import ( 4 "fmt" 5 "time" 6 7 "code.cloudfoundry.org/cli/cf/api/logs" 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 type Logs struct { 19 ui terminal.UI 20 logsRepo logs.Repository 21 config coreconfig.Reader 22 appReq requirements.ApplicationRequirement 23 } 24 25 func init() { 26 commandregistry.Register(&Logs{}) 27 } 28 29 func (cmd *Logs) MetaData() commandregistry.CommandMetadata { 30 fs := make(map[string]flags.FlagSet) 31 fs["recent"] = &flags.BoolFlag{Name: "recent", Usage: T("Dump recent logs instead of tailing")} 32 33 return commandregistry.CommandMetadata{ 34 Name: "logs", 35 Description: T("Tail or show recent logs for an app"), 36 Usage: []string{ 37 T("CF_NAME logs APP_NAME"), 38 }, 39 Flags: fs, 40 } 41 } 42 43 func (cmd *Logs) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) { 44 if len(fc.Args()) != 1 { 45 cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + commandregistry.Commands.CommandUsage("logs")) 46 return nil, fmt.Errorf("Incorrect usage: %d arguments of %d required", len(fc.Args()), 1) 47 } 48 49 cmd.appReq = requirementsFactory.NewApplicationRequirement(fc.Args()[0]) 50 51 reqs := []requirements.Requirement{ 52 requirementsFactory.NewLoginRequirement(), 53 requirementsFactory.NewTargetedSpaceRequirement(), 54 cmd.appReq, 55 } 56 57 return reqs, nil 58 } 59 60 func (cmd *Logs) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 61 cmd.ui = deps.UI 62 cmd.config = deps.Config 63 cmd.logsRepo = deps.RepoLocator.GetLogsRepository() 64 return cmd 65 } 66 67 func (cmd *Logs) Execute(c flags.FlagContext) error { 68 app := cmd.appReq.GetApplication() 69 70 var err error 71 if c.Bool("recent") { 72 err = cmd.recentLogsFor(app) 73 } else { 74 err = cmd.tailLogsFor(app) 75 } 76 if err != nil { 77 return err 78 } 79 return nil 80 } 81 82 func (cmd *Logs) recentLogsFor(app models.Application) error { 83 cmd.ui.Say(T("Connected, dumping recent logs for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...\n", 84 map[string]interface{}{ 85 "AppName": terminal.EntityNameColor(app.Name), 86 "OrgName": terminal.EntityNameColor(cmd.config.OrganizationFields().Name), 87 "SpaceName": terminal.EntityNameColor(cmd.config.SpaceFields().Name), 88 "Username": terminal.EntityNameColor(cmd.config.Username())})) 89 90 messages, err := cmd.logsRepo.RecentLogsFor(app.GUID) 91 if err != nil { 92 return cmd.handleError(err) 93 } 94 95 for _, msg := range messages { 96 cmd.ui.Say("%s", msg.ToLog(time.Local)) 97 } 98 return nil 99 } 100 101 func (cmd *Logs) tailLogsFor(app models.Application) error { 102 onConnect := func() { 103 cmd.ui.Say(T("Connected, tailing logs for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...\n", 104 map[string]interface{}{ 105 "AppName": terminal.EntityNameColor(app.Name), 106 "OrgName": terminal.EntityNameColor(cmd.config.OrganizationFields().Name), 107 "SpaceName": terminal.EntityNameColor(cmd.config.SpaceFields().Name), 108 "Username": terminal.EntityNameColor(cmd.config.Username())})) 109 } 110 111 c := make(chan logs.Loggable) 112 e := make(chan error) 113 114 go cmd.logsRepo.TailLogsFor(app.GUID, onConnect, c, e) 115 116 for { 117 select { 118 case msg, ok := <-c: 119 if !ok { 120 return nil 121 } 122 cmd.ui.Say("%s", msg.ToLog(time.Local)) 123 case err := <-e: 124 return cmd.handleError(err) 125 } 126 } 127 } 128 129 func (cmd *Logs) handleError(err error) error { 130 switch err.(type) { 131 case nil: 132 case *errors.InvalidSSLCert: 133 return errors.New(err.Error() + T("\nTIP: use 'cf login -a API --skip-ssl-validation' or 'cf api API --skip-ssl-validation' to suppress this error")) 134 default: 135 return err 136 } 137 return nil 138 }