diff --git a/actor/v7action/job.go b/actor/v7action/job.go index ac0741b606..fc6b6b0051 100644 --- a/actor/v7action/job.go +++ b/actor/v7action/job.go @@ -18,6 +18,7 @@ type PollJobEvent struct { State JobState Err error Warnings Warnings + JobGUID string } func (actor Actor) PollUploadBuildpackJob(jobURL ccv3.JobURL) (Warnings, error) { @@ -39,6 +40,7 @@ func (actor Actor) PollJobToEventStream(jobURL ccv3.JobURL) chan PollJobEvent { State: JobState(event.State), Err: event.Err, Warnings: Warnings(event.Warnings), + JobGUID: event.JobGUID, } } close(output) diff --git a/actor/v7action/job_test.go b/actor/v7action/job_test.go index ba91e8cb21..50f272fa06 100644 --- a/actor/v7action/job_test.go +++ b/actor/v7action/job_test.go @@ -81,16 +81,19 @@ var _ = Describe("Job Actions", func() { State: constant.JobProcessing, Err: nil, Warnings: ccv3.Warnings{"foo"}, + JobGUID: "job-guid", } fakeStream <- ccv3.PollJobEvent{ State: constant.JobPolling, Err: nil, Warnings: ccv3.Warnings{"bar"}, + JobGUID: "job-guid", } fakeStream <- ccv3.PollJobEvent{ State: constant.JobFailed, Err: errors.New("bad thing"), Warnings: ccv3.Warnings{"baz"}, + JobGUID: "job-guid", } close(fakeStream) }() @@ -105,16 +108,19 @@ var _ = Describe("Job Actions", func() { State: JobProcessing, Err: nil, Warnings: Warnings{"foo"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(Receive(Equal(PollJobEvent{ State: JobPolling, Err: nil, Warnings: Warnings{"bar"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(Receive(Equal(PollJobEvent{ State: JobFailed, Err: errors.New("bad thing"), Warnings: Warnings{"baz"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(BeClosed()) }) diff --git a/api/cloudcontroller/ccv3/job.go b/api/cloudcontroller/ccv3/job.go index 7f0cc31cf2..a1346a7e8c 100644 --- a/api/cloudcontroller/ccv3/job.go +++ b/api/cloudcontroller/ccv3/job.go @@ -150,6 +150,7 @@ type PollJobEvent struct { State constant.JobState Err error Warnings Warnings + JobGUID string } func (client *Client) PollJobToEventStream(jobURL JobURL) chan PollJobEvent { @@ -170,6 +171,7 @@ func (client *Client) PollJobToEventStream(jobURL JobURL) chan PollJobEvent { State: job.State, Err: err, Warnings: warnings, + JobGUID: job.GUID, } switch { diff --git a/api/cloudcontroller/ccv3/job_test.go b/api/cloudcontroller/ccv3/job_test.go index 71424bc5a1..262d938aaf 100644 --- a/api/cloudcontroller/ccv3/job_test.go +++ b/api/cloudcontroller/ccv3/job_test.go @@ -431,16 +431,19 @@ var _ = Describe("Job", func() { State: constant.JobProcessing, Err: nil, Warnings: Warnings{"warning-1"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(Receive(Equal(PollJobEvent{ State: constant.JobProcessing, Err: nil, Warnings: Warnings{"warning-2"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(Receive(Equal(PollJobEvent{ State: constant.JobComplete, Err: nil, Warnings: Warnings{"warning-3", "warning-4"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(BeClosed()) }) @@ -458,16 +461,19 @@ var _ = Describe("Job", func() { State: constant.JobProcessing, Err: nil, Warnings: Warnings{"warning-1"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(Receive(Equal(PollJobEvent{ State: constant.JobProcessing, Err: nil, Warnings: Warnings{"warning-2", "warning-3"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(Receive(Equal(PollJobEvent{ State: constant.JobFailed, Err: ccerror.BuildpackAlreadyExistsForStackError{Message: "some-message"}, Warnings: Warnings{"warning-4"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(BeClosed()) }) @@ -500,6 +506,7 @@ var _ = Describe("Job", func() { JobGUID: "job-guid", }, Warnings: Warnings{"warning-4"}, + JobGUID: "job-guid", }))) Eventually(stream).Should(BeClosed()) }) diff --git a/command/v7/bind_route_service_command.go b/command/v7/bind_route_service_command.go index b1c17cdc86..31c2fa0d81 100644 --- a/command/v7/bind_route_service_command.go +++ b/command/v7/bind_route_service_command.go @@ -46,7 +46,7 @@ func (cmd BindRouteServiceCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -56,6 +56,7 @@ func (cmd BindRouteServiceCommand) Execute(args []string) error { default: cmd.UI.DisplayOK() cmd.UI.DisplayText("Binding in progress.") + shared.DisplayJobHint(cmd.UI, jobGUID) return nil } } diff --git a/command/v7/bind_route_service_command_test.go b/command/v7/bind_route_service_command_test.go index dcd332e4a3..fb08e051f5 100644 --- a/command/v7/bind_route_service_command_test.go +++ b/command/v7/bind_route_service_command_test.go @@ -221,6 +221,7 @@ var _ = Describe("bind-route-service Command", func() { eventStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job polling warning"}, + JobGUID: "job-guid", } }() @@ -236,6 +237,7 @@ var _ = Describe("bind-route-service Command", func() { Say(`OK\n`), Say(`\n`), Say(`Binding in progress\.\n`), + Say(`Job \(job-guid\) is being processed\.\n`), )) Expect(testUI.Err).To(SatisfyAll( diff --git a/command/v7/bind_service_command.go b/command/v7/bind_service_command.go index c8a38f1f72..21df72b345 100644 --- a/command/v7/bind_service_command.go +++ b/command/v7/bind_service_command.go @@ -57,7 +57,7 @@ func (cmd BindServiceCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -68,6 +68,7 @@ func (cmd BindServiceCommand) Execute(args []string) error { default: cmd.UI.DisplayOK() cmd.UI.DisplayText("Binding in progress. Use 'cf service {{.ServiceInstanceName}}' to check operation status.", cmd.names()) + shared.DisplayJobHint(cmd.UI, jobGUID) cmd.UI.DisplayNewline() cmd.UI.DisplayText("TIP: Once this operation succeeds, use 'cf restage {{.AppName}}' to ensure your env variable changes take effect", cmd.names()) return nil diff --git a/command/v7/bind_service_command_test.go b/command/v7/bind_service_command_test.go index 6d7f79b3d1..f3142b3d21 100644 --- a/command/v7/bind_service_command_test.go +++ b/command/v7/bind_service_command_test.go @@ -222,6 +222,7 @@ var _ = Describe("bind-service Command", func() { eventStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job polling warning"}, + JobGUID: "job-guid", } }() @@ -237,6 +238,7 @@ var _ = Describe("bind-service Command", func() { Say(`OK\n`), Say(`\n`), Say(`Binding in progress. Use 'cf service %s' to check operation status.\n`, fakeServiceInstanceName), + Say(`Job \(job-guid\) is being processed\.\n`), Say(`\n`), Say(`TIP: Once this operation succeeds, use 'cf restage %s' to ensure your env variable changes take effect\n`, fakeAppName), )) diff --git a/command/v7/cleanup_outdated_service_bindings_command.go b/command/v7/cleanup_outdated_service_bindings_command.go index 0b0ab81832..db6cab8970 100644 --- a/command/v7/cleanup_outdated_service_bindings_command.go +++ b/command/v7/cleanup_outdated_service_bindings_command.go @@ -106,7 +106,7 @@ func (cmd CleanupOutdatedServiceBindingsCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -120,6 +120,7 @@ func (cmd CleanupOutdatedServiceBindingsCommand) Execute(args []string) error { } cmd.UI.DisplayOK() cmd.UI.DisplayText("Unbinding in progress. Use 'cf service {{.ServiceInstanceName}}' to check operation status.", map[string]interface{}{"ServiceInstanceName": si.Name}) + shared.DisplayJobHint(cmd.UI, jobGUID) } } diff --git a/command/v7/cleanup_outdated_service_bindings_command_test.go b/command/v7/cleanup_outdated_service_bindings_command_test.go index b3612111af..97bb55fe43 100644 --- a/command/v7/cleanup_outdated_service_bindings_command_test.go +++ b/command/v7/cleanup_outdated_service_bindings_command_test.go @@ -384,6 +384,7 @@ var _ = Describe("cleanup-outdated-service-bindings Command", func() { eventStream2 <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job 2 polling warning"}, + JobGUID: "job-guid", } }() @@ -423,6 +424,7 @@ var _ = Describe("cleanup-outdated-service-bindings Command", func() { Say(`OK\n`), Say(`\n`), Say(`Unbinding in progress. Use 'cf service %s' to check operation status\.\n`, fakeServiceInstanceName2), + Say(`Job \(job-guid\) is being processed\.\n`), )) Expect(testUI.Err).To(SatisfyAll( diff --git a/command/v7/create_service_command.go b/command/v7/create_service_command.go index 6260e84423..025da313af 100644 --- a/command/v7/create_service_command.go +++ b/command/v7/create_service_command.go @@ -95,7 +95,7 @@ func (cmd CreateServiceCommand) Execute(args []string) error { } cmd.UI.DisplayNewline() - complete, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + complete, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -103,6 +103,7 @@ func (cmd CreateServiceCommand) Execute(args []string) error { cmd.UI.DisplayTextWithFlavor("Service instance {{.ServiceInstanceName}} created.", cmd.serviceInstanceName()) default: cmd.UI.DisplayTextWithFlavor("Create in progress. Use 'cf services' or 'cf service {{.ServiceInstanceName}}' to check operation status.", cmd.serviceInstanceName()) + shared.DisplayJobHint(cmd.UI, jobGUID) } cmd.UI.DisplayOK() diff --git a/command/v7/create_service_command_test.go b/command/v7/create_service_command_test.go index 03980ec8f4..015e5fca20 100644 --- a/command/v7/create_service_command_test.go +++ b/command/v7/create_service_command_test.go @@ -202,6 +202,7 @@ var _ = Describe("create-service Command", func() { fakeStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"stream warning"}, + JobGUID: "job-guid", } }() }) @@ -211,6 +212,7 @@ var _ = Describe("create-service Command", func() { Say(`Creating service instance %s in org %s / space %s as %s\.\.\.\n`, requestedServiceInstanceName, fakeOrgName, fakeSpaceName, fakeUserName), Say(`\n`), Say(`Create in progress. Use 'cf services' or 'cf service %s' to check operation status\.\n`, requestedServiceInstanceName), + Say(`Job \(job-guid\) is being processed\.\n`), Say(`OK`), )) diff --git a/command/v7/create_service_key_command.go b/command/v7/create_service_key_command.go index 632d22c0e6..6c95a1645f 100644 --- a/command/v7/create_service_key_command.go +++ b/command/v7/create_service_key_command.go @@ -42,7 +42,7 @@ func (cmd CreateServiceKeyCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -52,6 +52,7 @@ func (cmd CreateServiceKeyCommand) Execute(args []string) error { default: cmd.UI.DisplayOK() cmd.UI.DisplayText("Create in progress.") + shared.DisplayJobHint(cmd.UI, jobGUID) return nil } } diff --git a/command/v7/create_service_key_command_test.go b/command/v7/create_service_key_command_test.go index ac21dd9831..1ea53a904d 100644 --- a/command/v7/create_service_key_command_test.go +++ b/command/v7/create_service_key_command_test.go @@ -167,6 +167,7 @@ var _ = Describe("create-service-key Command", func() { eventStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job polling warning"}, + JobGUID: "job-guid", } }() @@ -182,6 +183,7 @@ var _ = Describe("create-service-key Command", func() { Say(`OK\n`), Say(`\n`), Say(`Create in progress\.\n`), + Say(`Job \(job-guid\) is being processed\.\n`), )) Expect(testUI.Err).To(SatisfyAll( diff --git a/command/v7/delete_command.go b/command/v7/delete_command.go index 4556e0619a..cd93fa1b09 100644 --- a/command/v7/delete_command.go +++ b/command/v7/delete_command.go @@ -84,7 +84,7 @@ func (cmd DeleteCommand) Execute(args []string) error { } } - if _, err := shared.WaitForResult(stream, cmd.UI, true); err != nil { + if _, _, err := shared.WaitForResult(stream, cmd.UI, true); err != nil { return err } diff --git a/command/v7/delete_org_command.go b/command/v7/delete_org_command.go index 0e8288d97f..ba0e0ff72d 100644 --- a/command/v7/delete_org_command.go +++ b/command/v7/delete_org_command.go @@ -58,7 +58,7 @@ func (cmd *DeleteOrgCommand) Execute(args []string) error { default: return err } - } else if _, err := shared.WaitForResult(stream, cmd.UI, true); err != nil { + } else if _, _, err := shared.WaitForResult(stream, cmd.UI, true); err != nil { return err } diff --git a/command/v7/delete_service_command.go b/command/v7/delete_service_command.go index d5b6e51bb3..91e790312c 100644 --- a/command/v7/delete_service_command.go +++ b/command/v7/delete_service_command.go @@ -52,7 +52,7 @@ func (cmd DeleteServiceCommand) Execute(args []string) error { return err } - deleted, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + deleted, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) if err != nil { return err } @@ -62,6 +62,7 @@ func (cmd DeleteServiceCommand) Execute(args []string) error { cmd.UI.DisplayTextWithFlavor("Service instance {{.ServiceInstanceName}} deleted.", cmd.serviceInstanceName()) default: cmd.UI.DisplayText("Delete in progress. Use 'cf services' or 'cf service {{.ServiceInstanceName}}' to check operation status.", cmd.serviceInstanceName()) + shared.DisplayJobHint(cmd.UI, jobGUID) } cmd.UI.DisplayOK() diff --git a/command/v7/delete_service_command_test.go b/command/v7/delete_service_command_test.go index 890b34e4a3..7bb09afdfa 100644 --- a/command/v7/delete_service_command_test.go +++ b/command/v7/delete_service_command_test.go @@ -89,7 +89,8 @@ var _ = Describe("delete-service command", func() { go func() { stream <- v7action.PollJobEvent{ - State: v7action.JobPolling, + State: v7action.JobPolling, + JobGUID: "job-guid", } // channel not closed }() @@ -104,6 +105,7 @@ var _ = Describe("delete-service command", func() { Expect(testUI.Out).To(SatisfyAll( Say("\n"), Say(`Delete in progress. Use 'cf services' or 'cf service %s' to check operation status\.\n`, serviceInstanceName), + Say(`Job \(job-guid\) is being processed\.\n`), Say("OK\n"), )) }) diff --git a/command/v7/delete_service_key_command.go b/command/v7/delete_service_key_command.go index 9a3d5d2b92..60c4c222e8 100644 --- a/command/v7/delete_service_key_command.go +++ b/command/v7/delete_service_key_command.go @@ -53,7 +53,7 @@ func (cmd DeleteServiceKeyCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -63,6 +63,7 @@ func (cmd DeleteServiceKeyCommand) Execute(args []string) error { default: cmd.UI.DisplayOK() cmd.UI.DisplayText("Delete in progress.") + shared.DisplayJobHint(cmd.UI, jobGUID) return nil } } diff --git a/command/v7/delete_service_key_command_test.go b/command/v7/delete_service_key_command_test.go index 23d4e1ddbb..b002d388f2 100644 --- a/command/v7/delete_service_key_command_test.go +++ b/command/v7/delete_service_key_command_test.go @@ -241,6 +241,7 @@ var _ = Describe("delete-service-key Command", func() { eventStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job polling warning"}, + JobGUID: "job-guid", } }() @@ -256,6 +257,7 @@ var _ = Describe("delete-service-key Command", func() { Say(`OK\n`), Say(`\n`), Say(`Delete in progress\.\n`), + Say(`Job \(job-guid\) is being processed\.\n`), )) Expect(testUI.Err).To(SatisfyAll( diff --git a/command/v7/delete_space_command.go b/command/v7/delete_space_command.go index ce6f235319..22561d2ef8 100644 --- a/command/v7/delete_space_command.go +++ b/command/v7/delete_space_command.go @@ -74,7 +74,7 @@ func (cmd DeleteSpaceCommand) Execute(args []string) error { default: return err } - } else if _, err := shared.WaitForResult(stream, cmd.UI, true); err != nil { + } else if _, _, err := shared.WaitForResult(stream, cmd.UI, true); err != nil { return err } diff --git a/command/v7/shared/result_waiter.go b/command/v7/shared/result_waiter.go index 54be5d5db2..f24de2a259 100644 --- a/command/v7/shared/result_waiter.go +++ b/command/v7/shared/result_waiter.go @@ -7,9 +7,9 @@ import ( "code.cloudfoundry.org/cli/v9/command" ) -func WaitForResult(stream chan v7action.PollJobEvent, ui command.UI, waitForCompletion bool) (bool, error) { +func WaitForResult(stream chan v7action.PollJobEvent, ui command.UI, waitForCompletion bool) (bool, string, error) { if stream == nil { - return true, nil + return true, "", nil } if waitForCompletion { @@ -21,21 +21,32 @@ func WaitForResult(stream chan v7action.PollJobEvent, ui command.UI, waitForComp }() } + var jobGUID string seen := map[string]bool{} for event := range stream { ui.DisplayWarnings(dedupeSeenWarnings(event.Warnings, seen)) + if event.JobGUID != "" { + jobGUID = event.JobGUID + } if waitForCompletion { fmt.Fprint(ui.Writer(), ".") } if event.Err != nil { - return false, event.Err + return false, jobGUID, event.Err } if event.State == v7action.JobPolling && !waitForCompletion { - return false, nil + return false, jobGUID, nil } } - return true, nil + return true, jobGUID, nil +} + +func DisplayJobHint(ui command.UI, jobGUID string) { + if jobGUID == "" { + return + } + ui.DisplayText("Job ({{.JobGUID}}) is being processed.", map[string]interface{}{"JobGUID": jobGUID}) } // dedupeSeenWarnings prints each distinct warning at most once per operation: diff --git a/command/v7/shared/result_waiter_test.go b/command/v7/shared/result_waiter_test.go index b8f03f551f..f8db3cfaae 100644 --- a/command/v7/shared/result_waiter_test.go +++ b/command/v7/shared/result_waiter_test.go @@ -16,6 +16,7 @@ var _ = Describe("WaitForResult", func() { testUI *ui.UI stream chan v7action.PollJobEvent completed bool + jobGUID string err error ) @@ -24,10 +25,11 @@ var _ = Describe("WaitForResult", func() { }) When("the stream is nil (synchronous operation)", func() { - It("reports completion with no error", func() { - completed, err = WaitForResult(nil, testUI, false) + It("reports completion with no error and no job GUID", func() { + completed, jobGUID, err = WaitForResult(nil, testUI, false) Expect(err).NotTo(HaveOccurred()) Expect(completed).To(BeTrue()) + Expect(jobGUID).To(BeEmpty()) }) }) @@ -35,14 +37,15 @@ var _ = Describe("WaitForResult", func() { BeforeEach(func() { s := make(chan v7action.PollJobEvent, 1) stream = s - s <- v7action.PollJobEvent{State: v7action.JobPolling, Warnings: v7action.Warnings{"a warning"}} + s <- v7action.PollJobEvent{State: v7action.JobPolling, JobGUID: "the-job-guid", Warnings: v7action.Warnings{"a warning"}} // channel intentionally left open }) - It("returns not-completed and displays the warning", func() { - completed, err = WaitForResult(stream, testUI, false) + It("returns not-completed and hands back the observed job GUID", func() { + completed, jobGUID, err = WaitForResult(stream, testUI, false) Expect(err).NotTo(HaveOccurred()) Expect(completed).To(BeFalse()) + Expect(jobGUID).To(Equal("the-job-guid")) Expect(testUI.Err).To(Say("a warning")) }) }) @@ -51,14 +54,15 @@ var _ = Describe("WaitForResult", func() { BeforeEach(func() { s := make(chan v7action.PollJobEvent, 1) stream = s - s <- v7action.PollJobEvent{State: v7action.JobFailed, Err: errors.New("boom")} + s <- v7action.PollJobEvent{State: v7action.JobFailed, Err: errors.New("boom"), JobGUID: "err-job-guid"} close(s) }) - It("returns the error and not-completed", func() { - completed, err = WaitForResult(stream, testUI, false) + It("returns the error, not-completed, and the observed GUID", func() { + completed, jobGUID, err = WaitForResult(stream, testUI, false) Expect(err).To(MatchError("boom")) Expect(completed).To(BeFalse()) + Expect(jobGUID).To(Equal("err-job-guid")) }) }) @@ -66,14 +70,15 @@ var _ = Describe("WaitForResult", func() { BeforeEach(func() { s := make(chan v7action.PollJobEvent, 1) stream = s - s <- v7action.PollJobEvent{State: v7action.JobComplete} + s <- v7action.PollJobEvent{State: v7action.JobComplete, JobGUID: "complete-guid"} close(s) }) - It("returns completed with no error", func() { - completed, err = WaitForResult(stream, testUI, true) + It("returns completed with no error and the GUID", func() { + completed, jobGUID, err = WaitForResult(stream, testUI, true) Expect(err).NotTo(HaveOccurred()) Expect(completed).To(BeTrue()) + Expect(jobGUID).To(Equal("complete-guid")) }) }) @@ -89,7 +94,7 @@ var _ = Describe("WaitForResult", func() { }) It("prints the warning only once", func() { - completed, err = WaitForResult(stream, testUI, true) + completed, jobGUID, err = WaitForResult(stream, testUI, true) Expect(err).NotTo(HaveOccurred()) Expect(completed).To(BeTrue()) Expect(testUI.Err).To(Say("still in progress")) @@ -107,7 +112,7 @@ var _ = Describe("WaitForResult", func() { }) It("prints each distinct warning, preserving order", func() { - completed, err = WaitForResult(stream, testUI, true) + completed, jobGUID, err = WaitForResult(stream, testUI, true) Expect(err).NotTo(HaveOccurred()) Expect(testUI.Err).To(Say("first")) Expect(testUI.Err).To(Say("second")) @@ -125,7 +130,7 @@ var _ = Describe("WaitForResult", func() { }) It("prints each distinct warning only once for the whole operation", func() { - completed, err = WaitForResult(stream, testUI, true) + completed, jobGUID, err = WaitForResult(stream, testUI, true) Expect(err).NotTo(HaveOccurred()) Expect(testUI.Err).To(Say("persisted")) Expect(testUI.Err).To(Say("changed")) @@ -134,3 +139,25 @@ var _ = Describe("WaitForResult", func() { }) }) }) + +var _ = Describe("DisplayJobHint", func() { + var testUI *ui.UI + + BeforeEach(func() { + testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) + }) + + When("a job GUID is given", func() { + It("prints a hint naming the job", func() { + DisplayJobHint(testUI, "the-job-guid") + Expect(testUI.Out).To(Say(`Job \(the-job-guid\) is being processed\.`)) + }) + }) + + When("the job GUID is empty", func() { + It("prints nothing", func() { + DisplayJobHint(testUI, "") + Expect(testUI.Out).NotTo(Say("is being processed")) + }) + }) +}) diff --git a/command/v7/unbind_route_service_command.go b/command/v7/unbind_route_service_command.go index ab525bcb30..e2a4e20718 100644 --- a/command/v7/unbind_route_service_command.go +++ b/command/v7/unbind_route_service_command.go @@ -56,7 +56,7 @@ func (cmd UnbindRouteServiceCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -66,6 +66,7 @@ func (cmd UnbindRouteServiceCommand) Execute(args []string) error { default: cmd.UI.DisplayOK() cmd.UI.DisplayText("Unbinding in progress.") + shared.DisplayJobHint(cmd.UI, jobGUID) return nil } } diff --git a/command/v7/unbind_route_service_command_test.go b/command/v7/unbind_route_service_command_test.go index 00e5a270a0..6c25948f23 100644 --- a/command/v7/unbind_route_service_command_test.go +++ b/command/v7/unbind_route_service_command_test.go @@ -326,6 +326,7 @@ var _ = Describe("unbind-route-service Command", func() { eventStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job polling warning"}, + JobGUID: "job-guid", } }() @@ -341,6 +342,7 @@ var _ = Describe("unbind-route-service Command", func() { Say(`OK\n`), Say(`\n`), Say(`Unbinding in progress\.\n`), + Say(`Job \(job-guid\) is being processed\.\n`), )) Expect(testUI.Err).To(SatisfyAll( diff --git a/command/v7/unbind_service_command.go b/command/v7/unbind_service_command.go index 21936f590a..c9eb40b610 100644 --- a/command/v7/unbind_service_command.go +++ b/command/v7/unbind_service_command.go @@ -71,7 +71,7 @@ func (cmd UnbindServiceCommand) Execute(args []string) error { return err } - completed, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + completed, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -80,6 +80,7 @@ func (cmd UnbindServiceCommand) Execute(args []string) error { default: cmd.UI.DisplayOK() cmd.UI.DisplayText("Unbinding in progress. Use 'cf service {{.ServiceInstanceName}}' to check operation status.", cmd.names()) + shared.DisplayJobHint(cmd.UI, jobGUID) } } return nil diff --git a/command/v7/unbind_service_command_test.go b/command/v7/unbind_service_command_test.go index 9ce17f4135..6a3451bda2 100644 --- a/command/v7/unbind_service_command_test.go +++ b/command/v7/unbind_service_command_test.go @@ -209,6 +209,7 @@ var _ = Describe("unbind-service Command", func() { eventStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"job polling warning"}, + JobGUID: "job-guid", } }() @@ -225,6 +226,7 @@ var _ = Describe("unbind-service Command", func() { Say(`OK\n`), Say(`\n`), Say(`Unbinding in progress. Use 'cf service %s' to check operation status\.\n`, fakeServiceInstanceName), + Say(`Job \(job-guid\) is being processed\.\n`), )) Expect(testUI.Err).To(SatisfyAll( diff --git a/command/v7/update_service_command.go b/command/v7/update_service_command.go index 3a54a62f7b..7d0f5997fb 100644 --- a/command/v7/update_service_command.go +++ b/command/v7/update_service_command.go @@ -66,7 +66,7 @@ func (cmd UpdateServiceCommand) Execute(args []string) error { return err } - complete, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + complete, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -74,6 +74,7 @@ func (cmd UpdateServiceCommand) Execute(args []string) error { cmd.UI.DisplayTextWithFlavor("Update of service instance {{.ServiceInstance}} complete.", cmd.serviceInstanceName()) default: cmd.UI.DisplayTextWithFlavor("Update in progress. Use 'cf services' or 'cf service {{.ServiceInstance}}' to check operation status.", cmd.serviceInstanceName()) + shared.DisplayJobHint(cmd.UI, jobGUID) } cmd.UI.DisplayOK() diff --git a/command/v7/update_service_command_test.go b/command/v7/update_service_command_test.go index b6a117757f..436f9a6013 100644 --- a/command/v7/update_service_command_test.go +++ b/command/v7/update_service_command_test.go @@ -151,6 +151,7 @@ var _ = Describe("update-service command", func() { fakeStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"poll warning"}, + JobGUID: "job-guid", } }() }) @@ -160,6 +161,7 @@ var _ = Describe("update-service command", func() { Say(`Updating service instance %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), Say(`\n`), Say(`Update in progress. Use 'cf services' or 'cf service %s' to check operation status\.`, serviceInstanceName), + Say(`Job \(job-guid\) is being processed\.\n`), Say(`OK\n`), )) diff --git a/command/v7/upgrade_service_command.go b/command/v7/upgrade_service_command.go index 490b6e0d34..73551c87e1 100644 --- a/command/v7/upgrade_service_command.go +++ b/command/v7/upgrade_service_command.go @@ -57,7 +57,7 @@ func (cmd UpgradeServiceCommand) Execute(args []string) error { return actorError } - complete, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) + complete, jobGUID, err := shared.WaitForResult(stream, cmd.UI, cmd.Wait) switch { case err != nil: return err @@ -65,6 +65,7 @@ func (cmd UpgradeServiceCommand) Execute(args []string) error { cmd.UI.DisplayTextWithFlavor("Upgrade of service instance {{.ServiceInstanceName}} complete.", cmd.serviceInstanceName()) default: cmd.UI.DisplayTextWithFlavor("Upgrade in progress. Use 'cf services' or 'cf service {{.ServiceInstanceName}}' to check operation status.", cmd.serviceInstanceName()) + shared.DisplayJobHint(cmd.UI, jobGUID) } cmd.UI.DisplayOK() diff --git a/command/v7/upgrade_service_command_test.go b/command/v7/upgrade_service_command_test.go index 7f1441f65e..401d2d4bdc 100644 --- a/command/v7/upgrade_service_command_test.go +++ b/command/v7/upgrade_service_command_test.go @@ -119,6 +119,7 @@ var _ = Describe("upgrade-service command", func() { fakeStream <- v7action.PollJobEvent{ State: v7action.JobPolling, Warnings: v7action.Warnings{"poll warning"}, + JobGUID: "job-guid", } }() }) @@ -128,6 +129,7 @@ var _ = Describe("upgrade-service command", func() { Say(`Upgrading service instance %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), Say(`\n`), Say(`Upgrade in progress. Use 'cf services' or 'cf service %s' to check operation status\.`, serviceInstanceName), + Say(`Job \(job-guid\) is being processed\.\n`), Say(`OK\n`), ))