1package ssh_test 2 3import ( 4 "errors" 5 6 boshsys "github.com/cloudfoundry/bosh-utils/system" 7 fakesys "github.com/cloudfoundry/bosh-utils/system/fakes" 8 . "github.com/onsi/ginkgo" 9 . "github.com/onsi/gomega" 10 11 boshdir "github.com/cloudfoundry/bosh-cli/director" 12 . "github.com/cloudfoundry/bosh-cli/ssh" 13) 14 15var _ = Describe("SessionImpl", func() { 16 var ( 17 connOpts ConnectionOpts 18 sessOpts SessionImplOpts 19 result boshdir.SSHResult 20 privKeyFile *fakesys.FakeFile 21 knownHostsFile *fakesys.FakeFile 22 fs *fakesys.FakeFileSystem 23 session *SessionImpl 24 ) 25 26 BeforeEach(func() { 27 connOpts = ConnectionOpts{} 28 sessOpts = SessionImplOpts{} 29 result = boshdir.SSHResult{} 30 fs = fakesys.NewFakeFileSystem() 31 privKeyFile = fakesys.NewFakeFile("/tmp/priv-key", fs) 32 knownHostsFile = fakesys.NewFakeFile("/tmp/known-hosts", fs) 33 fs.ReturnTempFilesByPrefix = map[string]boshsys.File{ 34 "ssh-priv-key": privKeyFile, 35 "ssh-known-hosts": knownHostsFile, 36 } 37 session = NewSessionImpl(connOpts, sessOpts, result, fs) 38 }) 39 40 Describe("Start", func() { 41 act := func() *SessionImpl { return NewSessionImpl(connOpts, sessOpts, result, fs) } 42 43 It("writes out private key", func() { 44 connOpts.PrivateKey = "priv-key" 45 46 _, err := act().Start() 47 Expect(err).ToNot(HaveOccurred()) 48 Expect(fs.ReadFileString("/tmp/priv-key")).To(Equal("priv-key")) 49 }) 50 51 It("returns error if cannot create private key temp file", func() { 52 fs.TempFileErrorsByPrefix = map[string]error{ 53 "ssh-priv-key": errors.New("fake-err"), 54 } 55 56 _, err := act().Start() 57 Expect(err).To(HaveOccurred()) 58 Expect(err.Error()).To(ContainSubstring("fake-err")) 59 }) 60 61 It("returns error if writing public key failed", func() { 62 privKeyFile.WriteErr = errors.New("fake-err") 63 64 _, err := act().Start() 65 Expect(err).To(HaveOccurred()) 66 Expect(err.Error()).To(ContainSubstring("fake-err")) 67 }) 68 69 It("writes out all known hosts", func() { 70 result.Hosts = []boshdir.Host{ 71 {Host: "127.0.0.1", HostPublicKey: "pub-key1"}, 72 {Host: "127.0.0.2", HostPublicKey: "pub-key2"}, 73 {Host: "::1", HostPublicKey: "pub-key3"}, 74 } 75 76 _, err := act().Start() 77 Expect(err).ToNot(HaveOccurred()) 78 Expect(fs.ReadFileString("/tmp/known-hosts")).To(Equal( 79 "127.0.0.1 pub-key1\n127.0.0.2 pub-key2\n::1 pub-key3\n")) 80 }) 81 82 It("returns error if cannot create known hosts temp file and deletes private key", func() { 83 fs.TempFileErrorsByPrefix = map[string]error{ 84 "ssh-known-hosts": errors.New("fake-err"), 85 } 86 87 _, err := act().Start() 88 Expect(err).To(HaveOccurred()) 89 Expect(err.Error()).To(ContainSubstring("fake-err")) 90 91 Expect(fs.FileExists("/tmp/priv-key")).To(BeFalse()) 92 }) 93 94 It("returns error if writing known hosts failed and deletes private key", func() { 95 result.Hosts = []boshdir.Host{ 96 {Host: "127.0.0.1", HostPublicKey: "pub-key1"}, 97 } 98 knownHostsFile.WriteErr = errors.New("fake-err") 99 100 _, err := act().Start() 101 Expect(err).To(HaveOccurred()) 102 Expect(err.Error()).To(ContainSubstring("fake-err")) 103 104 Expect(fs.FileExists("/tmp/priv-key")).To(BeFalse()) 105 }) 106 107 It("returns ssh arguments with appropriate configuration", func() { 108 result.Hosts = []boshdir.Host{{Host: "127.0.0.1"}} // populate results 109 connOpts.PrivateKey = "priv-key" // populate connOpts 110 111 args, err := act().Start() 112 Expect(err).ToNot(HaveOccurred()) 113 Expect(args.ConnOpts).To(Equal(connOpts)) 114 Expect(args.Result).To(Equal(result)) 115 Expect(args.ForceTTY).To(BeFalse()) 116 Expect(args.PrivKeyFile).To(Equal(privKeyFile)) 117 Expect(args.KnownHostsFile).To(Equal(knownHostsFile)) 118 119 sessOpts.ForceTTY = true 120 121 args, err = act().Start() 122 Expect(err).ToNot(HaveOccurred()) 123 Expect(args.ConnOpts).To(Equal(connOpts)) 124 Expect(args.Result).To(Equal(result)) 125 Expect(args.ForceTTY).To(BeTrue()) 126 Expect(args.PrivKeyFile).To(Equal(privKeyFile)) 127 Expect(args.KnownHostsFile).To(Equal(knownHostsFile)) 128 }) 129 }) 130 131 Describe("Finish", func() { 132 BeforeEach(func() { 133 _, err := session.Start() 134 Expect(err).ToNot(HaveOccurred()) 135 }) 136 137 It("removes private key and known hosts files", func() { 138 err := session.Finish() 139 Expect(err).ToNot(HaveOccurred()) 140 Expect(fs.FileExists("/tmp/priv-key")).To(BeFalse()) 141 Expect(fs.FileExists("/tmp/known-hosts")).To(BeFalse()) 142 }) 143 144 It("returns error if deleting private key file fails but still deletes known hosts file", func() { 145 fs.RemoveAllStub = func(path string) error { 146 if path == "/tmp/priv-key" { 147 return errors.New("fake-err") 148 } 149 return nil 150 } 151 err := session.Finish() 152 Expect(err).To(HaveOccurred()) 153 Expect(err.Error()).To(ContainSubstring("fake-err")) 154 Expect(fs.FileExists("/tmp/known-hosts")).To(BeFalse()) 155 }) 156 157 It("returns error if deleting known hosts file fails but still deletes private key file", func() { 158 fs.RemoveAllStub = func(path string) error { 159 if path == "/tmp/known-hosts" { 160 return errors.New("fake-err") 161 } 162 return nil 163 } 164 err := session.Finish() 165 Expect(err).To(HaveOccurred()) 166 Expect(err.Error()).To(ContainSubstring("fake-err")) 167 Expect(fs.FileExists("/tmp/priv-key")).To(BeFalse()) 168 }) 169 }) 170}) 171