From b88aead478c501987166b188d4cb91964c55ab92 Mon Sep 17 00:00:00 2001 From: James Myers Date: Wed, 23 Sep 2015 10:07:19 -0700 Subject: [PATCH] Keep Alive for non-interactive sessions [#101789464] Signed-off-by: Andrew Edgar --- cf-plugin/cmd/ssh.go | 5 +++++ cf-plugin/cmd/ssh_test.go | 47 +++++++++++++++++++++++++++++++++++---- cf-plugin/ssh_plugin.go | 2 +- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/cf-plugin/cmd/ssh.go b/cf-plugin/cmd/ssh.go index fc134bd..1002d1a 100644 --- a/cf-plugin/cmd/ssh.go +++ b/cf-plugin/cmd/ssh.go @@ -300,6 +300,11 @@ func (c *secureShell) InteractiveSession() error { } func (c *secureShell) Wait() error { + keepaliveStopCh := make(chan struct{}) + defer close(keepaliveStopCh) + + go keepalive(c.secureClient.Conn(), time.NewTicker(c.keepAliveInterval), keepaliveStopCh) + return c.secureClient.Wait() } diff --git a/cf-plugin/cmd/ssh_test.go b/cf-plugin/cmd/ssh_test.go index bebd738..9df1c1e 100644 --- a/cf-plugin/cmd/ssh_test.go +++ b/cf-plugin/cmd/ssh_test.go @@ -1159,6 +1159,7 @@ var _ = Describe("Diego SSH Plugin", func() { Describe("Wait", func() { var opts *options.SSHOptions + var waitErr error BeforeEach(func() { opts = &options.SSHOptions{ @@ -1176,14 +1177,52 @@ var _ = Describe("Diego SSH Plugin", func() { JustBeforeEach(func() { connectErr := secureShell.Connect(opts) Expect(connectErr).NotTo(HaveOccurred()) - }) - It("calls close on the secureClient", func() { - err := secureShell.Wait() - Expect(err).NotTo(HaveOccurred()) + waitErr = secureShell.Wait() + }) + It("calls wait on the secureClient", func() { + Expect(waitErr).NotTo(HaveOccurred()) Expect(fakeSecureClient.WaitCallCount()).To(Equal(1)) }) + + Describe("keep alive messages", func() { + var times []time.Time + var timesCh chan []time.Time + var done chan struct{} + + BeforeEach(func() { + keepAliveDuration = 100 * time.Millisecond + + times = []time.Time{} + timesCh = make(chan []time.Time, 1) + done = make(chan struct{}, 1) + + fakeConnection.SendRequestStub = func(reqName string, wantReply bool, message []byte) (bool, []byte, error) { + Expect(reqName).To(Equal("keepalive@cloudfoundry.org")) + Expect(wantReply).To(BeTrue()) + Expect(message).To(BeNil()) + + times = append(times, time.Now()) + if len(times) == 3 { + timesCh <- times + close(done) + } + return true, nil, nil + } + + fakeSecureClient.WaitStub = func() error { + Eventually(done).Should(BeClosed()) + return nil + } + }) + + It("sends keep alive messages at the expected interval", func() { + Expect(waitErr).NotTo(HaveOccurred()) + times := <-timesCh + Expect(times[2]).To(BeTemporally("~", times[0].Add(200*time.Millisecond), 100*time.Millisecond)) + }) + }) }) Describe("Close", func() { diff --git a/cf-plugin/ssh_plugin.go b/cf-plugin/ssh_plugin.go index deda225..01a730c 100644 --- a/cf-plugin/ssh_plugin.go +++ b/cf-plugin/ssh_plugin.go @@ -28,7 +28,7 @@ func (p *SSHPlugin) GetMetadata() plugin.PluginMetadata { Version: plugin.VersionType{ Major: 0, Minor: 2, - Build: 0, + Build: 1, }, Commands: []plugin.Command{ {