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  }