From 94121711b77f33d1395702e33cf3b70c445fbfdf Mon Sep 17 00:00:00 2001 From: Felisia Martini Date: Fri, 19 Feb 2021 12:27:55 +0000 Subject: [PATCH] cf service: Show last operation for UPSI [#176779842](https://www.pivotaltracker.com/story/show/176779842) --- command/v7/service_command.go | 23 ++++-- command/v7/service_command_test.go | 77 ++++++++++++++++++- .../v7/isolated/service_command_test.go | 7 ++ 3 files changed, 95 insertions(+), 12 deletions(-) diff --git a/command/v7/service_command.go b/command/v7/service_command.go index 9861aaa0f0e..88cfca23abe 100644 --- a/command/v7/service_command.go +++ b/command/v7/service_command.go @@ -81,6 +81,7 @@ func (cmd ServiceCommand) fetchAndDisplayDetails() error { switch { case serviceInstanceWithDetails.Type == resources.UserProvidedServiceInstance: cmd.displayPropertiesUserProvided(serviceInstanceWithDetails) + cmd.displayLastOperation(serviceInstanceWithDetails) cmd.displayBoundApps(serviceInstanceWithDetails) default: cmd.displayPropertiesManaged(serviceInstanceWithDetails) @@ -184,16 +185,22 @@ func (cmd ServiceCommand) displayLastOperation(serviceInstanceWithDetails v7acti "ServiceInstanceName": serviceInstanceWithDetails.Name, }, ) - cmd.UI.DisplayNewline() - status := fmt.Sprintf("%s %s", serviceInstanceWithDetails.LastOperation.Type, serviceInstanceWithDetails.LastOperation.State) - table := [][]string{ - {cmd.UI.TranslateText("status:"), status}, - {cmd.UI.TranslateText("message:"), serviceInstanceWithDetails.LastOperation.Description}, - {cmd.UI.TranslateText("started:"), serviceInstanceWithDetails.LastOperation.CreatedAt}, - {cmd.UI.TranslateText("updated:"), serviceInstanceWithDetails.LastOperation.UpdatedAt}, + if serviceInstanceWithDetails.LastOperation == (resources.LastOperation{}) { + cmd.UI.DisplayText("There is no last operation available for this service instance.") + } else { + cmd.UI.DisplayNewline() + + status := fmt.Sprintf("%s %s", serviceInstanceWithDetails.LastOperation.Type, serviceInstanceWithDetails.LastOperation.State) + table := [][]string{ + {cmd.UI.TranslateText("status:"), status}, + {cmd.UI.TranslateText("message:"), serviceInstanceWithDetails.LastOperation.Description}, + {cmd.UI.TranslateText("started:"), serviceInstanceWithDetails.LastOperation.CreatedAt}, + {cmd.UI.TranslateText("updated:"), serviceInstanceWithDetails.LastOperation.UpdatedAt}, + } + cmd.UI.DisplayKeyValueTable("", table, 3) } - cmd.UI.DisplayKeyValueTable("", table, 3) + cmd.UI.DisplayNewline() } diff --git a/command/v7/service_command_test.go b/command/v7/service_command_test.go index 72ec2d67ee0..03a858bcd8e 100644 --- a/command/v7/service_command_test.go +++ b/command/v7/service_command_test.go @@ -135,9 +135,14 @@ var _ = Describe("service command", func() { When("it is a user-provided service instance", func() { const ( - routeServiceURL = "https://route.com" - syslogURL = "https://syslog.com" - tags = "foo, bar" + routeServiceURL = "https://route.com" + syslogURL = "https://syslog.com" + tags = "foo, bar" + lastOperationType = "update" + lastOperationState = "succeeded" + lastOperationDescription = "doing amazing work" + lastOperationStartTime = "a second ago" + lastOperationUpdatedTime = "just now" ) BeforeEach(func() { @@ -150,6 +155,13 @@ var _ = Describe("service command", func() { SyslogDrainURL: types.NewOptionalString(syslogURL), RouteServiceURL: types.NewOptionalString(routeServiceURL), Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), + LastOperation: resources.LastOperation{ + Type: lastOperationType, + State: lastOperationState, + Description: lastOperationDescription, + CreatedAt: lastOperationStartTime, + UpdatedAt: lastOperationUpdatedTime, + }, }, }, v7action.Warnings{"warning one", "warning two"}, @@ -176,6 +188,13 @@ var _ = Describe("service command", func() { Say(`route service url:\s+%s\n`, routeServiceURL), Say(`syslog drain url:\s+%s\n`, syslogURL), Say(`\n`), + Say(`Showing status of last operation from service instance %s...\n`, serviceInstanceName), + Say(`\n`), + Say(`status:\s+%s %s\n`, lastOperationType, lastOperationState), + Say(`message:\s+%s\n`, lastOperationDescription), + Say(`started:\s+%s\n`, lastOperationStartTime), + Say(`updated:\s+%s\n`, lastOperationUpdatedTime), + Say(`\n`), Say(`Bound apps:\n`), Say(`There are no bound apps for this service instance\.\n`), )) @@ -186,6 +205,57 @@ var _ = Describe("service command", func() { )) }) + When("last operation is not set", func() { + BeforeEach(func() { + fakeActor.GetServiceInstanceDetailsReturns( + v7action.ServiceInstanceDetails{ + ServiceInstance: resources.ServiceInstance{ + GUID: serviceInstanceGUID, + Name: serviceInstanceName, + Type: resources.UserProvidedServiceInstance, + SyslogDrainURL: types.NewOptionalString(syslogURL), + RouteServiceURL: types.NewOptionalString(routeServiceURL), + Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), + }, + }, + v7action.Warnings{"warning one", "warning two"}, + nil, + ) + }) + + It("when last operation does not exist", func() { + Expect(executeErr).NotTo(HaveOccurred()) + + Expect(fakeActor.GetServiceInstanceDetailsCallCount()).To(Equal(1)) + actualName, actualSpaceGUID, actualOmitApps := fakeActor.GetServiceInstanceDetailsArgsForCall(0) + Expect(actualName).To(Equal(serviceInstanceName)) + Expect(actualSpaceGUID).To(Equal(spaceGUID)) + Expect(actualOmitApps).To(BeFalse()) + + Expect(testUI.Out).To(SatisfyAll( + Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), + Say(`\n`), + Say(`name:\s+%s\n`, serviceInstanceName), + Say(`guid:\s+\S+\n`), + Say(`type:\s+user-provided`), + Say(`tags:\s+%s\n`, tags), + Say(`route service url:\s+%s\n`, routeServiceURL), + Say(`syslog drain url:\s+%s\n`, syslogURL), + Say(`\n`), + Say(`Showing status of last operation from service instance %s...\n`, serviceInstanceName), + Say(`There is no last operation available for this service instance\.\n`), + Say(`\n`), + Say(`Bound apps:\n`), + Say(`There are no bound apps for this service instance\.\n`), + )) + + Expect(testUI.Err).To(SatisfyAll( + Say("warning one"), + Say("warning two"), + )) + }) + }) + When("there are bound apps", func() { BeforeEach(func() { fakeActor.GetServiceInstanceDetailsReturns( @@ -248,7 +318,6 @@ var _ = Describe("service command", func() { lastOperationDescription = "doing amazing work" lastOperationStartTime = "a second ago" lastOperationUpdatedTime = "just now" - parameters = `{"foo":"bar"}` ) BeforeEach(func() { diff --git a/integration/v7/isolated/service_command_test.go b/integration/v7/isolated/service_command_test.go index 04e1e027fab..e32eb390165 100644 --- a/integration/v7/isolated/service_command_test.go +++ b/integration/v7/isolated/service_command_test.go @@ -137,6 +137,13 @@ var _ = Describe("service command", func() { Say(`route service url:\s+%s\n`, routeServiceURL), Say(`syslog drain url:\s+%s\n`, syslogURL), Say(`\n`), + Say(`Showing status of last operation from service instance %s...\n`, serviceInstanceName), + Say(`\n`), + Say(`status:\s+create succeeded\n`), + Say(`message:\s+Operation succeeded\n`), + Say(`started:\s+%s\n`, helpers.TimestampRegex), + Say(`updated:\s+%s\n`, helpers.TimestampRegex), + Say(`\n`), Say(`Bound apps:\n`), Say(`There are no bound apps for this service instance\.\n`), ))