github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/v7/shared/app_summary_displayer.go (about)

     1  package shared
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/bytefmt"
     9  	"code.cloudfoundry.org/cli/actor/v7action"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    11  	"code.cloudfoundry.org/cli/command"
    12  	log "github.com/sirupsen/logrus"
    13  )
    14  
    15  type AppSummaryDisplayer struct {
    16  	UI command.UI
    17  }
    18  
    19  func NewAppSummaryDisplayer(ui command.UI) *AppSummaryDisplayer {
    20  	return &AppSummaryDisplayer{
    21  		UI: ui,
    22  	}
    23  }
    24  
    25  func (display AppSummaryDisplayer) AppDisplay(summary v7action.DetailedApplicationSummary, displayStartCommand bool) {
    26  	var isoRow []string
    27  	if name, exists := summary.GetIsolationSegmentName(); exists {
    28  		isoRow = append(isoRow, display.UI.TranslateText("isolation segment:"), name)
    29  	}
    30  
    31  	var lifecycleInfo []string
    32  	if summary.LifecycleType == constant.AppLifecycleTypeDocker {
    33  		lifecycleInfo = []string{display.UI.TranslateText("docker image:"), summary.CurrentDroplet.Image}
    34  	} else {
    35  		lifecycleInfo = []string{display.UI.TranslateText("buildpacks:"), display.buildpackNames(summary.CurrentDroplet.Buildpacks)}
    36  	}
    37  
    38  	keyValueTable := [][]string{
    39  		{display.UI.TranslateText("name:"), summary.Application.Name},
    40  		{display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))},
    41  		isoRow,
    42  		{display.UI.TranslateText("routes:"), routeSummary(summary.Routes)},
    43  		{display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)},
    44  		{display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack},
    45  		lifecycleInfo,
    46  	}
    47  
    48  	display.UI.DisplayKeyValueTable("", keyValueTable, 3)
    49  
    50  	display.displayProcessTable(summary, displayStartCommand)
    51  }
    52  
    53  func routeSummary(rs []v7action.Route) string {
    54  	formattedRoutes := []string{}
    55  	for _, route := range rs {
    56  		formattedRoutes = append(formattedRoutes, route.URL)
    57  	}
    58  	return strings.Join(formattedRoutes, ", ")
    59  }
    60  
    61  func (display AppSummaryDisplayer) displayAppInstancesTable(processSummary v7action.ProcessSummary) {
    62  	table := [][]string{
    63  		{
    64  			"",
    65  			display.UI.TranslateText("state"),
    66  			display.UI.TranslateText("since"),
    67  			display.UI.TranslateText("cpu"),
    68  			display.UI.TranslateText("memory"),
    69  			display.UI.TranslateText("disk"),
    70  			display.UI.TranslateText("details"),
    71  		},
    72  	}
    73  
    74  	for _, instance := range processSummary.InstanceDetails {
    75  		table = append(table, []string{
    76  			fmt.Sprintf("#%d", instance.Index),
    77  			display.UI.TranslateText(strings.ToLower(string(instance.State))),
    78  			display.appInstanceDate(instance.StartTime()),
    79  			fmt.Sprintf("%.1f%%", instance.CPU*100),
    80  			display.UI.TranslateText("{{.MemUsage}} of {{.MemQuota}}", map[string]interface{}{
    81  				"MemUsage": bytefmt.ByteSize(instance.MemoryUsage),
    82  				"MemQuota": bytefmt.ByteSize(instance.MemoryQuota),
    83  			}),
    84  			display.UI.TranslateText("{{.DiskUsage}} of {{.DiskQuota}}", map[string]interface{}{
    85  				"DiskUsage": bytefmt.ByteSize(instance.DiskUsage),
    86  				"DiskQuota": bytefmt.ByteSize(instance.DiskQuota),
    87  			}),
    88  			instance.Details,
    89  		})
    90  	}
    91  
    92  	display.UI.DisplayInstancesTableForApp(table)
    93  }
    94  
    95  func (display AppSummaryDisplayer) displayProcessTable(summary v7action.DetailedApplicationSummary, displayStartCommand bool) {
    96  	for _, process := range summary.ProcessSummaries {
    97  		display.UI.DisplayNewline()
    98  
    99  		var startCommandRow []string
   100  		if displayStartCommand && len(process.Command.Value) > 0 {
   101  			startCommandRow = append(startCommandRow, display.UI.TranslateText("start command:"), process.Command.Value)
   102  		}
   103  
   104  		var processSidecars []string
   105  		for _, sidecar := range process.Sidecars {
   106  			processSidecars = append(processSidecars, sidecar.Name)
   107  		}
   108  
   109  		keyValueTable := [][]string{
   110  			{display.UI.TranslateText("type:"), process.Type},
   111  			{display.UI.TranslateText("sidecars:"), strings.Join(processSidecars, ", ")},
   112  			{display.UI.TranslateText("instances:"), fmt.Sprintf("%d/%d", process.HealthyInstanceCount(), process.TotalInstanceCount())},
   113  			{display.UI.TranslateText("memory usage:"), fmt.Sprintf("%dM", process.MemoryInMB.Value)},
   114  			startCommandRow,
   115  		}
   116  
   117  		display.UI.DisplayKeyValueTable("", keyValueTable, 3)
   118  
   119  		if len(process.InstanceDetails) == 0 {
   120  			display.UI.DisplayText("There are no running instances of this process.")
   121  			continue
   122  		}
   123  		display.displayAppInstancesTable(process)
   124  	}
   125  }
   126  
   127  func (display AppSummaryDisplayer) getCreatedTime(summary v7action.DetailedApplicationSummary) string {
   128  	if summary.CurrentDroplet.CreatedAt != "" {
   129  		timestamp, err := time.Parse(time.RFC3339, summary.CurrentDroplet.CreatedAt)
   130  		if err != nil {
   131  			log.WithField("createdAt", summary.CurrentDroplet.CreatedAt).Errorln("error parsing created at:", err)
   132  		}
   133  
   134  		return display.UI.UserFriendlyDate(timestamp)
   135  	}
   136  
   137  	return ""
   138  }
   139  
   140  func (AppSummaryDisplayer) buildpackNames(buildpacks []v7action.DropletBuildpack) string {
   141  	var names []string
   142  	for _, buildpack := range buildpacks {
   143  		if buildpack.DetectOutput != "" {
   144  			names = append(names, buildpack.DetectOutput)
   145  		} else {
   146  			names = append(names, buildpack.Name)
   147  		}
   148  	}
   149  
   150  	return strings.Join(names, ", ")
   151  }
   152  
   153  func (AppSummaryDisplayer) appInstanceDate(input time.Time) string {
   154  	return input.UTC().Format(time.RFC3339)
   155  }