github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+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  )
    13  
    14  type AppSummaryDisplayer struct {
    15  	UI command.UI
    16  }
    17  
    18  func NewAppSummaryDisplayer(ui command.UI) *AppSummaryDisplayer {
    19  	return &AppSummaryDisplayer{
    20  		UI: ui,
    21  	}
    22  }
    23  
    24  func (display AppSummaryDisplayer) AppDisplay(summary v7action.ApplicationSummary, displayStartCommand bool) {
    25  	var isoRow []string
    26  	if name, exists := summary.GetIsolationSegmentName(); exists {
    27  		isoRow = append(isoRow, display.UI.TranslateText("isolation segment:"), name)
    28  	}
    29  
    30  	var lifecycleInfo []string
    31  	if summary.LifecycleType == constant.AppLifecycleTypeDocker {
    32  		lifecycleInfo = []string{display.UI.TranslateText("docker image:"), summary.CurrentDroplet.Image}
    33  	} else {
    34  		lifecycleInfo = []string{display.UI.TranslateText("buildpacks:"), display.buildpackNames(summary.CurrentDroplet.Buildpacks)}
    35  	}
    36  
    37  	keyValueTable := [][]string{
    38  		{display.UI.TranslateText("name:"), summary.Application.Name},
    39  		{display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))},
    40  		isoRow,
    41  		{display.UI.TranslateText("routes:"), summary.Routes.Summary()},
    42  		{display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)},
    43  		{display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack},
    44  		lifecycleInfo,
    45  	}
    46  
    47  	display.UI.DisplayKeyValueTable("", keyValueTable, 3)
    48  
    49  	display.displayProcessTable(summary, displayStartCommand)
    50  }
    51  
    52  func (display AppSummaryDisplayer) displayAppInstancesTable(processSummary v7action.ProcessSummary) {
    53  	table := [][]string{
    54  		{
    55  			"",
    56  			display.UI.TranslateText("state"),
    57  			display.UI.TranslateText("since"),
    58  			display.UI.TranslateText("cpu"),
    59  			display.UI.TranslateText("memory"),
    60  			display.UI.TranslateText("disk"),
    61  			display.UI.TranslateText("details"),
    62  		},
    63  	}
    64  
    65  	for _, instance := range processSummary.InstanceDetails {
    66  		table = append(table, []string{
    67  			fmt.Sprintf("#%d", instance.Index),
    68  			display.UI.TranslateText(strings.ToLower(string(instance.State))),
    69  			display.appInstanceDate(instance.StartTime()),
    70  			fmt.Sprintf("%.1f%%", instance.CPU*100),
    71  			display.UI.TranslateText("{{.MemUsage}} of {{.MemQuota}}", map[string]interface{}{
    72  				"MemUsage": bytefmt.ByteSize(instance.MemoryUsage),
    73  				"MemQuota": bytefmt.ByteSize(instance.MemoryQuota),
    74  			}),
    75  			display.UI.TranslateText("{{.DiskUsage}} of {{.DiskQuota}}", map[string]interface{}{
    76  				"DiskUsage": bytefmt.ByteSize(instance.DiskUsage),
    77  				"DiskQuota": bytefmt.ByteSize(instance.DiskQuota),
    78  			}),
    79  			instance.Details,
    80  		})
    81  	}
    82  
    83  	display.UI.DisplayInstancesTableForApp(table)
    84  }
    85  
    86  func (display AppSummaryDisplayer) displayProcessTable(summary v7action.ApplicationSummary, displayStartCommand bool) {
    87  	for _, process := range summary.ProcessSummaries {
    88  		display.UI.DisplayNewline()
    89  
    90  		var startCommandRow []string
    91  		if displayStartCommand && len(process.Command.Value) > 0 {
    92  			startCommandRow = append(startCommandRow, display.UI.TranslateText("start command:"), process.Command.Value)
    93  		}
    94  
    95  		keyValueTable := [][]string{
    96  			{display.UI.TranslateText("type:"), process.Type},
    97  			{display.UI.TranslateText("instances:"), fmt.Sprintf("%d/%d", process.HealthyInstanceCount(), process.TotalInstanceCount())},
    98  			{display.UI.TranslateText("memory usage:"), fmt.Sprintf("%dM", process.MemoryInMB.Value)},
    99  			startCommandRow,
   100  		}
   101  
   102  		display.UI.DisplayKeyValueTable("", keyValueTable, 3)
   103  
   104  		if len(process.InstanceDetails) == 0 {
   105  			display.UI.DisplayNewline()
   106  			display.UI.DisplayText("There are no running instances of this process.")
   107  			continue
   108  		}
   109  		display.displayAppInstancesTable(process)
   110  	}
   111  }
   112  
   113  func (display AppSummaryDisplayer) getCreatedTime(summary v7action.ApplicationSummary) string {
   114  	if summary.CurrentDroplet.CreatedAt != "" {
   115  		timestamp, _ := time.Parse(time.RFC3339, summary.CurrentDroplet.CreatedAt)
   116  		return display.UI.UserFriendlyDate(timestamp)
   117  	}
   118  
   119  	return ""
   120  }
   121  
   122  func (AppSummaryDisplayer) usageSummary(processSummaries v7action.ProcessSummaries) string {
   123  	var usageStrings []string
   124  	for _, summary := range processSummaries {
   125  		if summary.TotalInstanceCount() > 0 {
   126  			usageStrings = append(usageStrings, fmt.Sprintf("%dM x %d", summary.MemoryInMB.Value, summary.TotalInstanceCount()))
   127  		}
   128  	}
   129  
   130  	return strings.Join(usageStrings, ", ")
   131  }
   132  
   133  func (AppSummaryDisplayer) buildpackNames(buildpacks []v7action.DropletBuildpack) string {
   134  	var names []string
   135  	for _, buildpack := range buildpacks {
   136  		if buildpack.DetectOutput != "" {
   137  			names = append(names, buildpack.DetectOutput)
   138  		} else {
   139  			names = append(names, buildpack.Name)
   140  		}
   141  	}
   142  
   143  	return strings.Join(names, ", ")
   144  }
   145  
   146  func (AppSummaryDisplayer) appInstanceDate(input time.Time) string {
   147  	return input.UTC().Format(time.RFC3339)
   148  }
   149  
   150  func (AppSummaryDisplayer) processHasAnInstanceUp(processSummary *v7action.ProcessSummary) bool {
   151  	for _, processInstance := range processSummary.InstanceDetails {
   152  		if processInstance.State != constant.ProcessInstanceDown {
   153  			return true
   154  		}
   155  	}
   156  	return false
   157  }
   158  
   159  func (AppSummaryDisplayer) processInstancesAreAllCrashed(processSummary *v7action.ProcessSummary) bool {
   160  	if len(processSummary.InstanceDetails) < 1 {
   161  		return false
   162  	}
   163  
   164  	for _, processInstance := range processSummary.InstanceDetails {
   165  		if processInstance.State != constant.ProcessInstanceDown {
   166  			return false
   167  		}
   168  	}
   169  	return true
   170  }