github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/command/v7/shared/app_summary_displayer_test.go (about)

     1  package shared_test
     2  
     3  import (
     4  	"time"
     5  
     6  	"code.cloudfoundry.org/cli/actor/v7action"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
     8  	. "code.cloudfoundry.org/cli/command/v7/shared"
     9  	"code.cloudfoundry.org/cli/integration/helpers"
    10  	"code.cloudfoundry.org/cli/types"
    11  	"code.cloudfoundry.org/cli/util/ui"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  	. "github.com/onsi/gomega/gbytes"
    15  )
    16  
    17  var _ = Describe("app summary displayer", func() {
    18  	var (
    19  		appSummaryDisplayer *AppSummaryDisplayer
    20  		output              *Buffer
    21  		testUI              *ui.UI
    22  	)
    23  
    24  	BeforeEach(func() {
    25  		output = NewBuffer()
    26  		testUI = ui.NewTestUI(nil, output, NewBuffer())
    27  
    28  		appSummaryDisplayer = NewAppSummaryDisplayer(testUI)
    29  	})
    30  
    31  	Describe("AppDisplay", func() {
    32  		var (
    33  			summary             v7action.DetailedApplicationSummary
    34  			displayStartCommand bool
    35  		)
    36  
    37  		JustBeforeEach(func() {
    38  			appSummaryDisplayer.AppDisplay(summary, displayStartCommand)
    39  		})
    40  
    41  		When("the app has instances", func() {
    42  			When("the process instances are running", func() {
    43  				var uptime time.Duration
    44  
    45  				BeforeEach(func() {
    46  					uptime = time.Since(time.Unix(267321600, 0))
    47  					summary = v7action.DetailedApplicationSummary{
    48  						ApplicationSummary: v7action.ApplicationSummary{
    49  							Application: v7action.Application{
    50  								GUID:  "some-app-guid",
    51  								State: constant.ApplicationStarted,
    52  							},
    53  							ProcessSummaries: v7action.ProcessSummaries{
    54  								{
    55  									Process: v7action.Process{
    56  										Type:       constant.ProcessTypeWeb,
    57  										MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
    58  										DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
    59  									},
    60  									Sidecars: []v7action.Sidecar{},
    61  									InstanceDetails: []v7action.ProcessInstance{
    62  										v7action.ProcessInstance{
    63  											Index:       0,
    64  											State:       constant.ProcessInstanceRunning,
    65  											MemoryUsage: 1000000,
    66  											DiskUsage:   1000000,
    67  											MemoryQuota: 33554432,
    68  											DiskQuota:   2000000,
    69  											Uptime:      uptime,
    70  											Details:     "Some Details 1",
    71  										},
    72  										v7action.ProcessInstance{
    73  											Index:       1,
    74  											State:       constant.ProcessInstanceRunning,
    75  											MemoryUsage: 2000000,
    76  											DiskUsage:   2000000,
    77  											MemoryQuota: 33554432,
    78  											DiskQuota:   4000000,
    79  											Uptime:      time.Since(time.Unix(330480000, 0)),
    80  											Details:     "Some Details 2",
    81  										},
    82  										v7action.ProcessInstance{
    83  											Index:       2,
    84  											State:       constant.ProcessInstanceRunning,
    85  											MemoryUsage: 3000000,
    86  											DiskUsage:   3000000,
    87  											MemoryQuota: 33554432,
    88  											DiskQuota:   6000000,
    89  											Uptime:      time.Since(time.Unix(1277164800, 0)),
    90  										},
    91  									},
    92  								},
    93  								{
    94  									Process: v7action.Process{
    95  										Type:       "console",
    96  										MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
    97  										DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
    98  									},
    99  									Sidecars: []v7action.Sidecar{},
   100  									InstanceDetails: []v7action.ProcessInstance{
   101  										v7action.ProcessInstance{
   102  											Index:       0,
   103  											State:       constant.ProcessInstanceRunning,
   104  											MemoryUsage: 1000000,
   105  											DiskUsage:   1000000,
   106  											MemoryQuota: 33554432,
   107  											DiskQuota:   8000000,
   108  											Uptime:      time.Since(time.Unix(167572800, 0)),
   109  										},
   110  									},
   111  								},
   112  							},
   113  						},
   114  					}
   115  				})
   116  
   117  				It("lists information for each of the processes", func() {
   118  					processTable := helpers.ParseV3AppProcessTable(output.Contents())
   119  					Expect(len(processTable.Processes)).To(Equal(2))
   120  
   121  					webProcessSummary := processTable.Processes[0]
   122  					Expect(webProcessSummary.Type).To(Equal("web"))
   123  					Expect(webProcessSummary.Sidecars).To(Equal(""))
   124  					Expect(webProcessSummary.InstanceCount).To(Equal("3/3"))
   125  					Expect(webProcessSummary.MemUsage).To(Equal("32M"))
   126  
   127  					Expect(webProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   128  					Expect(webProcessSummary.Instances[0].Since).To(MatchRegexp(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z`))
   129  					Expect(time.Parse(time.RFC3339, webProcessSummary.Instances[0].Since)).To(BeTemporally("~", time.Now().Add(-uptime), 2*time.Second))
   130  					Expect(webProcessSummary.Instances[0].Disk).To(Equal("976.6K of 1.9M"))
   131  					Expect(webProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   132  					Expect(webProcessSummary.Instances[0].Details).To(Equal("Some Details 1"))
   133  
   134  					Expect(webProcessSummary.Instances[1].Memory).To(Equal("1.9M of 32M"))
   135  					Expect(webProcessSummary.Instances[1].Disk).To(Equal("1.9M of 3.8M"))
   136  					Expect(webProcessSummary.Instances[1].CPU).To(Equal("0.0%"))
   137  					Expect(webProcessSummary.Instances[1].Details).To(Equal("Some Details 2"))
   138  
   139  					Expect(webProcessSummary.Instances[2].Memory).To(Equal("2.9M of 32M"))
   140  					Expect(webProcessSummary.Instances[2].Disk).To(Equal("2.9M of 5.7M"))
   141  					Expect(webProcessSummary.Instances[2].CPU).To(Equal("0.0%"))
   142  
   143  					consoleProcessSummary := processTable.Processes[1]
   144  					Expect(consoleProcessSummary.Type).To(Equal("console"))
   145  					Expect(consoleProcessSummary.Sidecars).To(Equal(""))
   146  					Expect(consoleProcessSummary.InstanceCount).To(Equal("1/1"))
   147  					Expect(consoleProcessSummary.MemUsage).To(Equal("16M"))
   148  
   149  					Expect(consoleProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   150  					Expect(consoleProcessSummary.Instances[0].Disk).To(Equal("976.6K of 7.6M"))
   151  					Expect(consoleProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   152  				})
   153  			})
   154  
   155  			When("some processes have > 0 instances and others have 0 instances", func() {
   156  				BeforeEach(func() {
   157  					summary = v7action.DetailedApplicationSummary{
   158  						ApplicationSummary: v7action.ApplicationSummary{
   159  							Application: v7action.Application{
   160  								GUID:  "some-app-guid",
   161  								State: constant.ApplicationStarted,
   162  							},
   163  							ProcessSummaries: v7action.ProcessSummaries{
   164  								{
   165  									Process: v7action.Process{
   166  										Type:       constant.ProcessTypeWeb,
   167  										MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   168  										DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   169  									},
   170  									Sidecars: []v7action.Sidecar{},
   171  									InstanceDetails: []v7action.ProcessInstance{
   172  										v7action.ProcessInstance{
   173  											Index:       0,
   174  											State:       constant.ProcessInstanceRunning,
   175  											MemoryUsage: 1000000,
   176  											DiskUsage:   1000000,
   177  											MemoryQuota: 33554432,
   178  											DiskQuota:   2000000,
   179  											Uptime:      time.Since(time.Unix(267321600, 0)),
   180  										},
   181  									},
   182  								},
   183  								{
   184  									Process: v7action.Process{
   185  										Type:       "console",
   186  										MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
   187  										DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
   188  									},
   189  									Sidecars: []v7action.Sidecar{},
   190  								},
   191  							},
   192  						},
   193  					}
   194  				})
   195  
   196  				It("lists instance stats for process types that have > 0 instances", func() {
   197  					Expect(testUI.Out).To(Say(`type:\s+web`))
   198  					Expect(testUI.Out).To(Say(`sidecars: `))
   199  					Expect(testUI.Out).To(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   200  				})
   201  
   202  				It("does not show the instance stats table for process types with 0 instances", func() {
   203  					Expect(testUI.Out).To(Say(`type:\s+console`))
   204  					Expect(testUI.Out).To(Say(`sidecars: `))
   205  					Expect(testUI.Out).To(Say("There are no running instances of this process."))
   206  				})
   207  			})
   208  
   209  			When("all the instances for a process are down (but scaled to > 0 instances)", func() {
   210  				BeforeEach(func() {
   211  					summary = v7action.DetailedApplicationSummary{
   212  						ApplicationSummary: v7action.ApplicationSummary{
   213  							ProcessSummaries: []v7action.ProcessSummary{
   214  								{
   215  									Process: v7action.Process{
   216  										Type:       constant.ProcessTypeWeb,
   217  										MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   218  									},
   219  									Sidecars:        []v7action.Sidecar{},
   220  									InstanceDetails: []v7action.ProcessInstance{{State: constant.ProcessInstanceDown}},
   221  								}},
   222  						},
   223  					}
   224  				})
   225  
   226  				It("displays the instances table", func() {
   227  					Expect(testUI.Out).To(Say(`type:\s+web`))
   228  					Expect(testUI.Out).To(Say(`sidecars: `))
   229  					Expect(testUI.Out).To(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   230  				})
   231  			})
   232  
   233  			Describe("start command", func() {
   234  				BeforeEach(func() {
   235  					summary = v7action.DetailedApplicationSummary{
   236  						ApplicationSummary: v7action.ApplicationSummary{
   237  							Application: v7action.Application{
   238  								GUID:  "some-app-guid",
   239  								State: constant.ApplicationStarted,
   240  							},
   241  							ProcessSummaries: v7action.ProcessSummaries{
   242  								{
   243  									Process: v7action.Process{
   244  										Type:    constant.ProcessTypeWeb,
   245  										Command: *types.NewFilteredString("some-command-1"),
   246  									},
   247  									Sidecars: []v7action.Sidecar{},
   248  								},
   249  								{
   250  									Process: v7action.Process{
   251  										Type:    "console",
   252  										Command: *types.NewFilteredString("some-command-2"),
   253  									},
   254  									Sidecars: []v7action.Sidecar{},
   255  								},
   256  								{
   257  									Process: v7action.Process{
   258  										Type: "random",
   259  									},
   260  									Sidecars: []v7action.Sidecar{},
   261  								},
   262  							},
   263  						},
   264  					}
   265  				})
   266  
   267  				When("displayStartCommand is true", func() {
   268  					BeforeEach(func() {
   269  						displayStartCommand = true
   270  					})
   271  
   272  					It("displays the non-empty start command for each process", func() {
   273  						Expect(testUI.Out).To(Say(`type:\s+web`))
   274  						Expect(testUI.Out).To(Say(`sidecars: `))
   275  						Expect(testUI.Out).To(Say(`start command:\s+some-command-1`))
   276  
   277  						Expect(testUI.Out).To(Say(`type:\s+console`))
   278  						Expect(testUI.Out).To(Say(`sidecars: `))
   279  						Expect(testUI.Out).To(Say(`start command:\s+some-command-2`))
   280  
   281  						Expect(testUI.Out).To(Say(`type:\s+random`))
   282  						Expect(testUI.Out).To(Say(`sidecars: `))
   283  						Expect(testUI.Out).ToNot(Say("start command:"))
   284  					})
   285  				})
   286  
   287  				When("displayStartCommand is false", func() {
   288  					BeforeEach(func() {
   289  						displayStartCommand = false
   290  					})
   291  
   292  					It("hides the start command", func() {
   293  						Expect(testUI.Out).ToNot(Say("start command:"))
   294  					})
   295  				})
   296  			})
   297  		})
   298  
   299  		When("the app has no instances", func() {
   300  			BeforeEach(func() {
   301  				summary = v7action.DetailedApplicationSummary{
   302  					ApplicationSummary: v7action.ApplicationSummary{
   303  						Application: v7action.Application{
   304  							GUID:  "some-app-guid",
   305  							State: constant.ApplicationStarted,
   306  						},
   307  						ProcessSummaries: v7action.ProcessSummaries{
   308  							{
   309  								Process: v7action.Process{
   310  									Type:       constant.ProcessTypeWeb,
   311  									MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   312  									DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   313  								},
   314  								Sidecars: []v7action.Sidecar{},
   315  							},
   316  							{
   317  								Process: v7action.Process{
   318  									Type:       "console",
   319  									MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
   320  									DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
   321  								},
   322  								Sidecars: []v7action.Sidecar{},
   323  							},
   324  						},
   325  					},
   326  				}
   327  			})
   328  
   329  			It("lists information for each of the processes", func() {
   330  				Expect(testUI.Out).To(Say(`type:\s+web`))
   331  				Expect(testUI.Out).To(Say(`sidecars: `))
   332  				Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   333  				Expect(testUI.Out).To(Say(`memory usage:\s+32M`))
   334  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   335  
   336  				Expect(testUI.Out).To(Say(`type:\s+console`))
   337  				Expect(testUI.Out).To(Say(`sidecars: `))
   338  				Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   339  				Expect(testUI.Out).To(Say(`memory usage:\s+16M`))
   340  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   341  			})
   342  
   343  			It("does not display the instance table", func() {
   344  				Expect(testUI.Out).NotTo(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   345  			})
   346  		})
   347  
   348  		When("the app has sidecars", func() {
   349  			BeforeEach(func() {
   350  				summary = v7action.DetailedApplicationSummary{
   351  					ApplicationSummary: v7action.ApplicationSummary{
   352  						Application: v7action.Application{
   353  							GUID:  "some-app-guid",
   354  							State: constant.ApplicationStarted,
   355  						},
   356  						ProcessSummaries: v7action.ProcessSummaries{
   357  							{
   358  								Process: v7action.Process{
   359  									Type:       constant.ProcessTypeWeb,
   360  									MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   361  									DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   362  								},
   363  								Sidecars: []v7action.Sidecar{
   364  									{Name: "authenticator"},
   365  									{Name: "clock"},
   366  								},
   367  							},
   368  						},
   369  					},
   370  				}
   371  			})
   372  
   373  			It("lists information for each of the processes", func() {
   374  				Expect(testUI.Out).To(Say(`type:\s+web`))
   375  				Expect(testUI.Out).To(Say(`sidecars:\s+authenticator, clock`))
   376  				Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   377  				Expect(testUI.Out).To(Say(`memory usage:\s+32M`))
   378  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   379  			})
   380  
   381  			It("does not display the instance table", func() {
   382  				Expect(testUI.Out).NotTo(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   383  			})
   384  		})
   385  
   386  		When("the app is stopped", func() {
   387  			BeforeEach(func() {
   388  				summary = v7action.DetailedApplicationSummary{
   389  					ApplicationSummary: v7action.ApplicationSummary{
   390  						Application: v7action.Application{
   391  							GUID:  "some-app-guid",
   392  							State: constant.ApplicationStopped,
   393  						},
   394  						ProcessSummaries: v7action.ProcessSummaries{
   395  							{
   396  								Process: v7action.Process{
   397  									Type: constant.ProcessTypeWeb,
   398  								},
   399  								Sidecars: []v7action.Sidecar{},
   400  							},
   401  							{
   402  								Process: v7action.Process{
   403  									Type: "console",
   404  								},
   405  								Sidecars: []v7action.Sidecar{},
   406  							},
   407  						},
   408  					},
   409  				}
   410  			})
   411  
   412  			It("lists information for each of the processes", func() {
   413  				Expect(testUI.Out).To(Say(`type:\s+web`))
   414  				Expect(testUI.Out).To(Say(`sidecars: `))
   415  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   416  
   417  				Expect(testUI.Out).To(Say(`type:\s+console`))
   418  				Expect(testUI.Out).To(Say(`sidecars: `))
   419  				Expect(testUI.Out).To(Say("There are no running instances of this process."))
   420  			})
   421  
   422  			It("does not display the instance table", func() {
   423  				Expect(testUI.Out).NotTo(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`))
   424  			})
   425  		})
   426  
   427  		Describe("isolation segments", func() {
   428  			When("the isolation segment name is provided", func() {
   429  				var isolationSegmentName string
   430  				BeforeEach(func() {
   431  					isolationSegmentName = "potato beans"
   432  					summary.ProcessSummaries = v7action.ProcessSummaries{
   433  						v7action.ProcessSummary{
   434  							InstanceDetails: []v7action.ProcessInstance{
   435  								{IsolationSegment: isolationSegmentName},
   436  							},
   437  						},
   438  					}
   439  				})
   440  
   441  				It("should output the isolation segment name", func() {
   442  					Expect(testUI.Out).To(Say(`isolation segment:\s+%s`, isolationSegmentName))
   443  				})
   444  			})
   445  
   446  			When("the application summary has no isolation segment information", func() {
   447  				BeforeEach(func() {
   448  					summary = v7action.DetailedApplicationSummary{
   449  						ApplicationSummary: v7action.ApplicationSummary{
   450  							Application: v7action.Application{
   451  								GUID:  "some-app-guid",
   452  								State: constant.ApplicationStopped,
   453  							},
   454  						},
   455  					}
   456  				})
   457  
   458  				It("should not output isolation segment header", func() {
   459  					Expect(testUI.Out).ToNot(Say("isolation segment:"))
   460  				})
   461  			})
   462  		})
   463  
   464  		Describe("last upload time", func() {
   465  			When("the application has a last uploaded time", func() {
   466  				var createdTime string
   467  
   468  				BeforeEach(func() {
   469  					createdTime = "2006-01-02T15:04:05-07:00"
   470  					summary.CurrentDroplet.CreatedAt = createdTime
   471  				})
   472  
   473  				It("displays the uploaded time", func() {
   474  					t, err := time.Parse(time.RFC3339, createdTime)
   475  					Expect(err).To(Not(HaveOccurred()))
   476  
   477  					time := t.Local().Format("Mon 02 Jan 15:04:05 MST 2006")
   478  					Expect(testUI.Out).To(Say(`last uploaded:\s+%s`, time))
   479  				})
   480  			})
   481  
   482  			When("the application does not have a last uploaded time", func() {
   483  				BeforeEach(func() {
   484  					summary.CurrentDroplet.CreatedAt = ""
   485  				})
   486  
   487  				It("leaves last uploaded blank", func() {
   488  					Expect(testUI.Out).To(Say(`(?m)last uploaded:\s*\n`))
   489  				})
   490  			})
   491  		})
   492  
   493  		When("the application has routes", func() {
   494  			BeforeEach(func() {
   495  				summary.Routes = []v7action.Route{
   496  					{Host: "route1", URL: "route1.example.com"},
   497  					{Host: "route2", URL: "route2.example.com"},
   498  				}
   499  			})
   500  
   501  			It("displays routes", func() {
   502  				Expect(testUI.Out).To(Say(`routes:\s+%s, %s`, "route1.example.com", "route2.example.com"))
   503  			})
   504  		})
   505  
   506  		When("the application has a stack", func() {
   507  			BeforeEach(func() {
   508  				summary.CurrentDroplet.Stack = "some-stack"
   509  			})
   510  
   511  			It("displays stack", func() {
   512  				Expect(testUI.Out).To(Say(`stack:\s+some-stack`))
   513  			})
   514  		})
   515  
   516  		When("the application is a docker app", func() {
   517  			BeforeEach(func() {
   518  				summary = v7action.DetailedApplicationSummary{
   519  					ApplicationSummary: v7action.ApplicationSummary{
   520  						Application: v7action.Application{
   521  							GUID:          "some-guid",
   522  							Name:          "some-app",
   523  							State:         constant.ApplicationStarted,
   524  							LifecycleType: constant.AppLifecycleTypeDocker,
   525  						},
   526  					},
   527  					CurrentDroplet: v7action.Droplet{
   528  						Image: "docker/some-image",
   529  					},
   530  				}
   531  			})
   532  
   533  			It("displays the app information", func() {
   534  				Expect(testUI.Out).To(Say(`name:\s+some-app`))
   535  				Expect(testUI.Out).To(Say(`requested state:\s+started`))
   536  				Expect(testUI.Out).To(Say(`routes:\s+\n`))
   537  				Expect(testUI.Out).To(Say(`stack:\s+\n`))
   538  				Expect(testUI.Out).To(Say(`(?m)docker image:\s+docker/some-image$\n`))
   539  			})
   540  		})
   541  
   542  		When("the application is a buildpack app", func() {
   543  			BeforeEach(func() {
   544  				summary = v7action.DetailedApplicationSummary{
   545  					CurrentDroplet: v7action.Droplet{
   546  						Stack: "cflinuxfs2",
   547  						Buildpacks: []v7action.DropletBuildpack{
   548  							{
   549  								Name:         "ruby_buildpack",
   550  								DetectOutput: "some-detect-output",
   551  							},
   552  							{
   553  								Name:         "some-buildpack",
   554  								DetectOutput: "",
   555  							},
   556  						},
   557  					},
   558  				}
   559  			})
   560  
   561  			It("displays stack and buildpacks", func() {
   562  				Expect(testUI.Out).To(Say(`stack:\s+cflinuxfs2`))
   563  				Expect(testUI.Out).To(Say(`buildpacks:\s+some-detect-output, some-buildpack`))
   564  			})
   565  		})
   566  	})
   567  })