github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+incompatible/actor/v7action/application_summary_test.go (about)

     1  package v7action_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/resources"
     5  	"errors"
     6  
     7  	"code.cloudfoundry.org/cli/actor/v2action"
     8  	. "code.cloudfoundry.org/cli/actor/v7action"
     9  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    13  	"code.cloudfoundry.org/cli/types"
    14  
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/ginkgo/extensions/table"
    17  	. "github.com/onsi/gomega"
    18  )
    19  
    20  var _ = Describe("Application Summary Actions", func() {
    21  	var (
    22  		actor                     *Actor
    23  		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient)
    28  		actor = NewActor(fakeCloudControllerClient, nil, nil, nil)
    29  	})
    30  
    31  	Describe("ApplicationSummary", func() {
    32  		DescribeTable("GetIsolationSegmentName",
    33  			func(summary ApplicationSummary, isoName string, exists bool) {
    34  				name, ok := summary.GetIsolationSegmentName()
    35  				Expect(ok).To(Equal(exists))
    36  				Expect(name).To(Equal(isoName))
    37  			},
    38  
    39  			Entry("when the there are application instances and the isolationSegmentName is set",
    40  				ApplicationSummary{
    41  					ProcessSummaries: ProcessSummaries{
    42  						ProcessSummary{
    43  							InstanceDetails: []ProcessInstance{
    44  								{IsolationSegment: "some-name"},
    45  							},
    46  						},
    47  					},
    48  				},
    49  				"some-name",
    50  				true,
    51  			),
    52  
    53  			Entry("when the there are application instances and the isolationSegmentName is blank",
    54  				ApplicationSummary{
    55  					ProcessSummaries: ProcessSummaries{
    56  						ProcessSummary{InstanceDetails: []ProcessInstance{{}}},
    57  					},
    58  				},
    59  				"",
    60  				false,
    61  			),
    62  
    63  			Entry("when the there are no application instances", ApplicationSummary{ProcessSummaries: ProcessSummaries{{}}}, "", false),
    64  			Entry("when the there are no processes", ApplicationSummary{}, "", false),
    65  		)
    66  	})
    67  
    68  	Describe("GetApplicationSummaryByNameAndSpace", func() {
    69  		var (
    70  			appName              string
    71  			spaceGUID            string
    72  			withObfuscatedValues bool
    73  			fakeRouteActor       *v7actionfakes.FakeRouteActor
    74  
    75  			summary    ApplicationSummary
    76  			warnings   Warnings
    77  			executeErr error
    78  		)
    79  
    80  		BeforeEach(func() {
    81  			appName = "some-app-name"
    82  			spaceGUID = "some-space-guid"
    83  			withObfuscatedValues = true
    84  			fakeRouteActor = new(v7actionfakes.FakeRouteActor)
    85  		})
    86  
    87  		Context("when a route actor is not provided", func() {
    88  			JustBeforeEach(func() {
    89  				summary, warnings, executeErr = actor.GetApplicationSummaryByNameAndSpace(appName, spaceGUID, withObfuscatedValues, nil)
    90  			})
    91  
    92  			When("retrieving the application is successful", func() {
    93  				BeforeEach(func() {
    94  					fakeCloudControllerClient.GetApplicationsReturns(
    95  						[]resources.Application{
    96  							{
    97  								Name:  "some-app-name",
    98  								GUID:  "some-app-guid",
    99  								State: constant.ApplicationStarted,
   100  							},
   101  						},
   102  						ccv3.Warnings{"some-warning"},
   103  						nil,
   104  					)
   105  				})
   106  
   107  				When("retrieving the process information is successful", func() {
   108  					BeforeEach(func() {
   109  						listedProcesses := []resources.Process{
   110  							{
   111  								GUID:       "some-process-guid",
   112  								Type:       "some-type",
   113  								Command:    *types.NewFilteredString("[Redacted Value]"),
   114  								MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   115  							},
   116  							{
   117  								GUID:       "some-process-web-guid",
   118  								Type:       "web",
   119  								Command:    *types.NewFilteredString("[Redacted Value]"),
   120  								MemoryInMB: types.NullUint64{Value: 64, IsSet: true},
   121  							},
   122  						}
   123  						fakeCloudControllerClient.GetApplicationProcessesReturns(
   124  							listedProcesses,
   125  							ccv3.Warnings{"some-process-warning"},
   126  							nil,
   127  						)
   128  
   129  						explicitlyCalledProcess := listedProcesses[0]
   130  						explicitlyCalledProcess.Command = *types.NewFilteredString("some-start-command")
   131  						fakeCloudControllerClient.GetApplicationProcessByTypeReturnsOnCall(
   132  							0,
   133  							explicitlyCalledProcess,
   134  							ccv3.Warnings{"get-process-by-type-warning"},
   135  							nil,
   136  						)
   137  
   138  						fakeCloudControllerClient.GetApplicationProcessByTypeReturnsOnCall(
   139  							1,
   140  							listedProcesses[1],
   141  							ccv3.Warnings{"get-process-by-type-warning"},
   142  							nil,
   143  						)
   144  
   145  						fakeCloudControllerClient.GetProcessInstancesReturns(
   146  							[]ccv3.ProcessInstance{
   147  								{
   148  									State:       constant.ProcessInstanceRunning,
   149  									CPU:         0.01,
   150  									MemoryUsage: 1000000,
   151  									DiskUsage:   2000000,
   152  									MemoryQuota: 3000000,
   153  									DiskQuota:   4000000,
   154  									Index:       0,
   155  								},
   156  							},
   157  							ccv3.Warnings{"some-process-stats-warning"},
   158  							nil,
   159  						)
   160  					})
   161  
   162  					When("app has droplet", func() {
   163  						BeforeEach(func() {
   164  							fakeCloudControllerClient.GetApplicationDropletCurrentReturns(
   165  								resources.Droplet{
   166  									Stack: "some-stack",
   167  									Buildpacks: []resources.DropletBuildpack{
   168  										{
   169  											Name: "some-buildpack",
   170  										},
   171  									},
   172  									Image: "docker/some-image",
   173  								},
   174  								ccv3.Warnings{"some-droplet-warning"},
   175  								nil,
   176  							)
   177  						})
   178  
   179  						It("returns the summary and warnings with droplet information", func() {
   180  							Expect(executeErr).ToNot(HaveOccurred())
   181  							Expect(summary).To(Equal(ApplicationSummary{
   182  								Application: Application{
   183  									Name:  "some-app-name",
   184  									GUID:  "some-app-guid",
   185  									State: constant.ApplicationStarted,
   186  								},
   187  								CurrentDroplet: Droplet{
   188  									Stack: "some-stack",
   189  									Image: "docker/some-image",
   190  									Buildpacks: []DropletBuildpack{
   191  										{
   192  											Name: "some-buildpack",
   193  										},
   194  									},
   195  								},
   196  								ProcessSummaries: []ProcessSummary{
   197  									{
   198  										Process: Process{
   199  											GUID:       "some-process-web-guid",
   200  											Type:       "web",
   201  											Command:    *types.NewFilteredString("[Redacted Value]"),
   202  											MemoryInMB: types.NullUint64{Value: 64, IsSet: true},
   203  										},
   204  										InstanceDetails: []ProcessInstance{
   205  											{
   206  												State:       constant.ProcessInstanceRunning,
   207  												CPU:         0.01,
   208  												MemoryUsage: 1000000,
   209  												DiskUsage:   2000000,
   210  												MemoryQuota: 3000000,
   211  												DiskQuota:   4000000,
   212  												Index:       0,
   213  											},
   214  										},
   215  									},
   216  									{
   217  										Process: Process{
   218  											GUID:       "some-process-guid",
   219  											MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   220  											Type:       "some-type",
   221  											Command:    *types.NewFilteredString("some-start-command"),
   222  										},
   223  										InstanceDetails: []ProcessInstance{
   224  											{
   225  												State:       constant.ProcessInstanceRunning,
   226  												CPU:         0.01,
   227  												MemoryUsage: 1000000,
   228  												DiskUsage:   2000000,
   229  												MemoryQuota: 3000000,
   230  												DiskQuota:   4000000,
   231  												Index:       0,
   232  											},
   233  										},
   234  									},
   235  								},
   236  							}))
   237  							Expect(warnings).To(ConsistOf("some-warning", "some-process-warning", "get-process-by-type-warning", "get-process-by-type-warning", "some-process-stats-warning", "some-process-stats-warning", "some-droplet-warning"))
   238  
   239  							Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   240  							Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   241  								ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}},
   242  								ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   243  							))
   244  
   245  							Expect(fakeCloudControllerClient.GetApplicationDropletCurrentCallCount()).To(Equal(1))
   246  							Expect(fakeCloudControllerClient.GetApplicationDropletCurrentArgsForCall(0)).To(Equal("some-app-guid"))
   247  
   248  							Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(1))
   249  							Expect(fakeCloudControllerClient.GetApplicationProcessesArgsForCall(0)).To(Equal("some-app-guid"))
   250  
   251  							Expect(fakeCloudControllerClient.GetApplicationProcessByTypeCallCount()).To(Equal(2))
   252  							appGUID, processType := fakeCloudControllerClient.GetApplicationProcessByTypeArgsForCall(0)
   253  							Expect(appGUID).To(Equal("some-app-guid"))
   254  							Expect(processType).To(Equal("some-type"))
   255  
   256  							Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(2))
   257  							Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("some-process-guid"))
   258  						})
   259  
   260  						When("getting the current droplet returns an error", func() {
   261  							var expectedErr error
   262  
   263  							BeforeEach(func() {
   264  								expectedErr = errors.New("some error")
   265  								fakeCloudControllerClient.GetApplicationDropletCurrentReturns(
   266  									resources.Droplet{},
   267  									ccv3.Warnings{"some-droplet-warning"},
   268  									expectedErr,
   269  								)
   270  							})
   271  
   272  							It("returns the error", func() {
   273  								Expect(executeErr).To(Equal(expectedErr))
   274  								Expect(warnings).To(ConsistOf("some-warning", "some-process-warning", "get-process-by-type-warning", "get-process-by-type-warning", "some-process-stats-warning", "some-process-stats-warning", "some-droplet-warning"))
   275  							})
   276  						})
   277  					})
   278  
   279  					When("app does not have current droplet", func() {
   280  						BeforeEach(func() {
   281  							fakeCloudControllerClient.GetApplicationDropletCurrentReturns(
   282  								resources.Droplet{},
   283  								ccv3.Warnings{"some-droplet-warning"},
   284  								ccerror.DropletNotFoundError{},
   285  							)
   286  						})
   287  
   288  						It("returns the summary and warnings without droplet information", func() {
   289  							Expect(executeErr).ToNot(HaveOccurred())
   290  							Expect(summary).To(Equal(ApplicationSummary{
   291  								Application: Application{
   292  									Name:  "some-app-name",
   293  									GUID:  "some-app-guid",
   294  									State: constant.ApplicationStarted,
   295  								},
   296  								ProcessSummaries: []ProcessSummary{
   297  									{
   298  										Process: Process{
   299  											GUID:       "some-process-web-guid",
   300  											Type:       "web",
   301  											Command:    *types.NewFilteredString("[Redacted Value]"),
   302  											MemoryInMB: types.NullUint64{Value: 64, IsSet: true},
   303  										},
   304  										InstanceDetails: []ProcessInstance{
   305  											{
   306  												State:       constant.ProcessInstanceRunning,
   307  												CPU:         0.01,
   308  												MemoryUsage: 1000000,
   309  												DiskUsage:   2000000,
   310  												MemoryQuota: 3000000,
   311  												DiskQuota:   4000000,
   312  												Index:       0,
   313  											},
   314  										},
   315  									},
   316  									{
   317  										Process: Process{
   318  											GUID:       "some-process-guid",
   319  											MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   320  											Type:       "some-type",
   321  											Command:    *types.NewFilteredString("some-start-command"),
   322  										},
   323  										InstanceDetails: []ProcessInstance{
   324  											{
   325  												State:       constant.ProcessInstanceRunning,
   326  												CPU:         0.01,
   327  												MemoryUsage: 1000000,
   328  												DiskUsage:   2000000,
   329  												MemoryQuota: 3000000,
   330  												DiskQuota:   4000000,
   331  												Index:       0,
   332  											},
   333  										},
   334  									},
   335  								},
   336  							}))
   337  							Expect(warnings).To(ConsistOf("some-warning", "some-process-warning", "get-process-by-type-warning", "get-process-by-type-warning", "some-process-stats-warning", "some-process-stats-warning", "some-droplet-warning"))
   338  						})
   339  					})
   340  
   341  				})
   342  
   343  				When("getting the app process instances returns an error", func() {
   344  					var expectedErr error
   345  
   346  					BeforeEach(func() {
   347  						fakeCloudControllerClient.GetApplicationProcessesReturns(
   348  							[]resources.Process{
   349  								{
   350  									GUID: "some-process-guid",
   351  									Type: "some-type",
   352  								},
   353  							},
   354  							ccv3.Warnings{"some-process-warning"},
   355  							nil,
   356  						)
   357  
   358  						fakeCloudControllerClient.GetApplicationProcessByTypeReturns(
   359  							resources.Process{},
   360  							ccv3.Warnings{"get-process-by-type-warning"},
   361  							nil,
   362  						)
   363  
   364  						expectedErr = errors.New("some error")
   365  						fakeCloudControllerClient.GetProcessInstancesReturns(
   366  							[]ccv3.ProcessInstance{},
   367  							ccv3.Warnings{"some-process-stats-warning"},
   368  							expectedErr,
   369  						)
   370  					})
   371  
   372  					It("returns the error", func() {
   373  						Expect(executeErr).To(Equal(expectedErr))
   374  						Expect(warnings).To(ConsistOf("some-warning", "some-process-warning", "get-process-by-type-warning", "some-process-stats-warning"))
   375  					})
   376  				})
   377  			})
   378  
   379  			When("getting the app processes returns an error", func() {
   380  				var expectedErr error
   381  
   382  				BeforeEach(func() {
   383  					fakeCloudControllerClient.GetApplicationsReturns(
   384  						[]resources.Application{
   385  							{
   386  								Name:  "some-app-name",
   387  								GUID:  "some-app-guid",
   388  								State: constant.ApplicationStarted,
   389  							},
   390  						},
   391  						ccv3.Warnings{"some-warning"},
   392  						nil,
   393  					)
   394  
   395  					expectedErr = errors.New("some error")
   396  					fakeCloudControllerClient.GetApplicationProcessesReturns(
   397  						[]resources.Process{{Type: constant.ProcessTypeWeb}},
   398  						ccv3.Warnings{"some-process-warning"},
   399  						expectedErr,
   400  					)
   401  				})
   402  
   403  				It("returns the error", func() {
   404  					Expect(executeErr).To(Equal(expectedErr))
   405  					Expect(warnings).To(ConsistOf("some-warning", "some-process-warning"))
   406  				})
   407  			})
   408  		})
   409  
   410  		When("passed with a routeActor", func() {
   411  			BeforeEach(func() {
   412  				fakeCloudControllerClient.GetApplicationsReturns(
   413  					[]resources.Application{
   414  						{
   415  							Name:  "some-app-name",
   416  							GUID:  "some-app-guid",
   417  							State: constant.ApplicationStarted,
   418  						},
   419  					},
   420  					ccv3.Warnings{"some-warning"},
   421  					nil,
   422  				)
   423  			})
   424  
   425  			JustBeforeEach(func() {
   426  				summary, warnings, executeErr = actor.GetApplicationSummaryByNameAndSpace(appName, spaceGUID, withObfuscatedValues, fakeRouteActor)
   427  			})
   428  
   429  			When("getting the routes is successful", func() {
   430  				BeforeEach(func() {
   431  					routes := v2action.Routes{
   432  						{GUID: "some-route-guid"},
   433  						{GUID: "some-other-route-guid"},
   434  					}
   435  
   436  					fakeRouteActor.GetApplicationRoutesReturns(routes, v2action.Warnings{"v2-routes-warnings"}, nil)
   437  				})
   438  
   439  				It("retrieves and sets the application routes", func() {
   440  					Expect(warnings).To(ConsistOf("some-warning", "v2-routes-warnings"))
   441  					Expect(summary.Routes).To(ConsistOf(
   442  						v2action.Route{GUID: "some-route-guid"},
   443  						v2action.Route{GUID: "some-other-route-guid"},
   444  					))
   445  
   446  					Expect(fakeRouteActor.GetApplicationRoutesCallCount()).To(Equal(1))
   447  					Expect(fakeRouteActor.GetApplicationRoutesArgsForCall(0)).To(Equal("some-app-guid"))
   448  				})
   449  			})
   450  
   451  			When("getting the application routes errors", func() {
   452  				When("a generic error is returned", func() {
   453  					BeforeEach(func() {
   454  						fakeRouteActor.GetApplicationRoutesReturns(nil, v2action.Warnings{"v2-routes-warnings"}, errors.New("some-error"))
   455  					})
   456  
   457  					It("returns warnings and the error", func() {
   458  						Expect(executeErr).To(MatchError("some-error"))
   459  						Expect(warnings).To(ConsistOf("some-warning", "v2-routes-warnings"))
   460  					})
   461  				})
   462  
   463  				When("a ResourceNotFoundError is returned", func() {
   464  					BeforeEach(func() {
   465  						fakeRouteActor.GetApplicationRoutesReturns(nil, v2action.Warnings{"v2-routes-warnings"}, ccerror.ResourceNotFoundError{})
   466  					})
   467  
   468  					It("adds warnings and continues", func() {
   469  						Expect(executeErr).ToNot(HaveOccurred())
   470  						Expect(warnings).To(ConsistOf("some-warning", "v2-routes-warnings"))
   471  					})
   472  				})
   473  			})
   474  		})
   475  	})
   476  })