diff --git a/api/cloudcontroller/ccv3/process_instance.go b/api/cloudcontroller/ccv3/process_instance.go index 17bb5277941..12d37f63389 100644 --- a/api/cloudcontroller/ccv3/process_instance.go +++ b/api/cloudcontroller/ccv3/process_instance.go @@ -40,6 +40,8 @@ type ProcessInstance struct { LogRate uint64 // State is the state of the instance. State constant.ProcessInstanceState + // Routeable is the readiness state of the instance, can be true, false or null. + Routable *bool // Type is the process type for the instance. Type string // Uptime is the duration that the instance has been running. @@ -56,6 +58,7 @@ func (instance *ProcessInstance) UnmarshalJSON(data []byte) error { MemQuota uint64 `json:"mem_quota"` LogRateLimit int64 `json:"log_rate_limit"` State string `json:"state"` + Routable *bool `json:"routable"` Type string `json:"type"` Uptime int64 `json:"uptime"` Usage struct { @@ -84,6 +87,7 @@ func (instance *ProcessInstance) UnmarshalJSON(data []byte) error { instance.LogRateLimit = inputInstance.LogRateLimit instance.LogRate = inputInstance.Usage.LogRate instance.State = constant.ProcessInstanceState(inputInstance.State) + instance.Routable = inputInstance.Routable instance.Type = inputInstance.Type instance.Uptime, err = time.ParseDuration(fmt.Sprintf("%ds", inputInstance.Uptime)) if err != nil { diff --git a/command/v7/shared/app_summary_displayer.go b/command/v7/shared/app_summary_displayer.go index fac5dc975c5..82c2025584b 100644 --- a/command/v7/shared/app_summary_displayer.go +++ b/command/v7/shared/app_summary_displayer.go @@ -80,6 +80,14 @@ func formatCPUEntitlement(cpuEntitlement types.NullFloat64) string { return fmt.Sprintf("%.1f%%", cpuEntitlement.Value*100) } +func formatRoutable(b *bool) string { + if b == nil { + return "-" + } + + return fmt.Sprintf("%t", *b) +} + func (display AppSummaryDisplayer) displayAppInstancesTable(processSummary v7action.ProcessSummary) { table := [][]string{ { @@ -92,6 +100,7 @@ func (display AppSummaryDisplayer) displayAppInstancesTable(processSummary v7act display.UI.TranslateText("logging"), display.UI.TranslateText("cpu entitlement"), display.UI.TranslateText("details"), + display.UI.TranslateText("ready"), }, } @@ -115,6 +124,7 @@ func (display AppSummaryDisplayer) displayAppInstancesTable(processSummary v7act }), formatCPUEntitlement(instance.CPUEntitlement), instance.Details, + formatRoutable(instance.Routable), }) } diff --git a/command/v7/shared/app_summary_displayer_test.go b/command/v7/shared/app_summary_displayer_test.go index fe41c7a6317..7a1ac043d25 100644 --- a/command/v7/shared/app_summary_displayer_test.go +++ b/command/v7/shared/app_summary_displayer_test.go @@ -17,7 +17,7 @@ import ( var _ = Describe("app summary displayer", func() { - const instanceStatsTitles = `state\s+since\s+cpu\s+memory\s+disk\s+logging\s+cpu entitlement\s+details` + const instanceStatsTitles = `state\s+since\s+cpu\s+memory\s+disk\s+logging\s+cpu entitlement\s+details\s+ready` var ( appSummaryDisplayer *AppSummaryDisplayer @@ -48,6 +48,10 @@ var _ = Describe("app summary displayer", func() { BeforeEach(func() { uptime = time.Since(time.Unix(267321600, 0)) + var ( + bTrue = true + bFalse = false + ) summary = v7action.DetailedApplicationSummary{ ApplicationSummary: v7action.ApplicationSummary{ Application: resources.Application{ @@ -76,6 +80,7 @@ var _ = Describe("app summary displayer", func() { LogRateLimit: 1024 * 5, Uptime: uptime, Details: "Some Details 1", + Routable: &bTrue, }, v7action.ProcessInstance{ Index: 1, @@ -89,6 +94,7 @@ var _ = Describe("app summary displayer", func() { LogRateLimit: 1024 * 5, Uptime: time.Since(time.Unix(330480000, 0)), Details: "Some Details 2", + Routable: &bTrue, }, v7action.ProcessInstance{ Index: 2, @@ -101,6 +107,7 @@ var _ = Describe("app summary displayer", func() { DiskQuota: 6000000, LogRateLimit: 1024 * 5, Uptime: time.Since(time.Unix(1277164800, 0)), + Routable: &bFalse, }, }, }, @@ -123,6 +130,7 @@ var _ = Describe("app summary displayer", func() { DiskQuota: 8000000, LogRateLimit: 256, Uptime: time.Since(time.Unix(167572800, 0)), + Routable: &bTrue, }, }, }, @@ -149,6 +157,7 @@ var _ = Describe("app summary displayer", func() { Expect(webProcessSummary.Instances[0].CPUEntitlement).To(Equal("0.0%")) Expect(webProcessSummary.Instances[0].LogRate).To(Equal("1K/s of 5K/s")) Expect(webProcessSummary.Instances[0].Details).To(Equal("Some Details 1")) + Expect(webProcessSummary.Instances[0].Ready).To(Equal("true")) Expect(webProcessSummary.Instances[1].Memory).To(Equal("1.9M of 32M")) Expect(webProcessSummary.Instances[1].Disk).To(Equal("1.9M of 3.8M")) @@ -156,12 +165,14 @@ var _ = Describe("app summary displayer", func() { Expect(webProcessSummary.Instances[1].CPUEntitlement).To(Equal("")) Expect(webProcessSummary.Instances[1].LogRate).To(Equal("2K/s of 5K/s")) Expect(webProcessSummary.Instances[1].Details).To(Equal("Some Details 2")) + Expect(webProcessSummary.Instances[1].Ready).To(Equal("true")) Expect(webProcessSummary.Instances[2].Memory).To(Equal("2.9M of 32M")) Expect(webProcessSummary.Instances[2].Disk).To(Equal("2.9M of 5.7M")) Expect(webProcessSummary.Instances[2].CPU).To(Equal("0.0%")) Expect(webProcessSummary.Instances[2].CPUEntitlement).To(Equal("3.0%")) Expect(webProcessSummary.Instances[2].LogRate).To(Equal("3K/s of 5K/s")) + Expect(webProcessSummary.Instances[2].Ready).To(Equal("false")) consoleProcessSummary := processTable.Processes[1] Expect(consoleProcessSummary.Type).To(Equal("console")) diff --git a/integration/helpers/app_instance_table.go b/integration/helpers/app_instance_table.go index 5ee6c136989..3189192ffd0 100644 --- a/integration/helpers/app_instance_table.go +++ b/integration/helpers/app_instance_table.go @@ -17,6 +17,7 @@ type AppInstanceRow struct { LogRate string CPUEntitlement string Details string + Ready string } // AppProcessTable represents a process of a V3 app, as displayed in the 'cf @@ -57,18 +58,8 @@ func ParseV3AppProcessTable(input []byte) AppTable { switch { case strings.HasPrefix(row, "#"): - const columnCount = 9 - // instance row columns := splitColumns(row) - cpuEntitlement, details := "", "" - if len(columns) >= columnCount-1 { - cpuEntitlement = columns[columnCount-2] - } - if len(columns) >= columnCount { - details = columns[columnCount-1] - } - instanceRow := AppInstanceRow{ Index: columns[0], State: columns[1], @@ -77,8 +68,9 @@ func ParseV3AppProcessTable(input []byte) AppTable { Memory: columns[4], Disk: columns[5], LogRate: columns[6], - CPUEntitlement: cpuEntitlement, - Details: details, + CPUEntitlement: columns[7], + Details: columns[8], + Ready: columns[9], } lastProcessIndex := len(appTable.Processes) - 1 appTable.Processes[lastProcessIndex].Instances = append( @@ -115,9 +107,20 @@ func splitColumns(row string) []string { s := strings.TrimSpace(row) // uses 3 spaces between columns result := regexp.MustCompile(`\s{3,}`).Split(s, -1) - // 21 spaces should only occur if cpu entitlement is empty but details is filled in - if regexp.MustCompile(`\s{21}`).MatchString(s) { - result = append(result[:len(result)-1], "", result[len(result)-1]) + + if regexp.MustCompile(`\s{31}`).MatchString(s) { + + if len(result) == 8 { + // Both cpu entitlement and details are empty + result = append(result[:len(result)-1], "", "", result[len(result)-1]) + } else { + // Only details is empty + result = append(result[:len(result)-2], result[len(result)-2], "", result[len(result)-1]) + } + + } else if regexp.MustCompile(`\s{21}`).MatchString(s) { + // cpu entitlement is empty, details is filled + result = append(result[:len(result)-2], "", result[len(result)-2], result[len(result)-1]) } return result }