github.com/orange-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 }