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