/director/ssh_test.go

https://github.com/cloudfoundry/bosh-cli · Go · 405 lines · 347 code · 55 blank · 3 comment · 0 complexity · ab89e5095e267c2088d5c9ada555447b MD5 · raw file

  1. package director_test
  2. import (
  3. "net/http"
  4. . "github.com/onsi/ginkgo"
  5. . "github.com/onsi/gomega"
  6. "github.com/onsi/gomega/ghttp"
  7. . "github.com/cloudfoundry/bosh-cli/director"
  8. )
  9. var _ = Describe("NewSSHOpts", func() {
  10. var (
  11. director Director
  12. deployment Deployment
  13. server *ghttp.Server
  14. )
  15. BeforeEach(func() {
  16. director, server = BuildServer()
  17. var err error
  18. deployment, err = director.FindDeployment("dep")
  19. Expect(err).ToNot(HaveOccurred())
  20. })
  21. AfterEach(func() {
  22. server.Close()
  23. })
  24. Describe("SetUpSSH", func() {
  25. It("sets up SSH sessions without gateway configuration", func() {
  26. respBody := `[
  27. {
  28. "index": 1,
  29. "host_public_key": "host1-pub-key",
  30. "ip": "host1-ip",
  31. "status": "success",
  32. "command": "setup"
  33. },
  34. {
  35. "index": 2,
  36. "host_public_key": "host2-pub-key",
  37. "ip": "host2-ip",
  38. "status": "success",
  39. "command": "setup"
  40. }
  41. ]`
  42. ConfigureTaskResult(
  43. ghttp.CombineHandlers(
  44. ghttp.VerifyRequest("POST", "/deployments/dep/ssh"),
  45. ghttp.VerifyBasicAuth("username", "password"),
  46. ghttp.VerifyJSONRepresenting(map[string]interface{}{
  47. "command": "setup",
  48. "params": map[string]string{
  49. "user": "user",
  50. "public_key": "pub-key",
  51. },
  52. "deployment_name": "dep",
  53. "target": map[string]interface{}{
  54. "job": "job",
  55. "indexes": []string{"index"},
  56. "ids": []string{"index"},
  57. },
  58. }),
  59. ),
  60. respBody,
  61. server,
  62. )
  63. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  64. opts := SSHOpts{
  65. Username: "user",
  66. PublicKey: "pub-key",
  67. }
  68. result, err := deployment.SetUpSSH(slug, opts)
  69. Expect(err).ToNot(HaveOccurred())
  70. Expect(result).To(Equal(SSHResult{
  71. Hosts: []Host{
  72. {
  73. Job: "",
  74. IndexOrID: "1",
  75. Username: "user",
  76. Host: "host1-ip",
  77. HostPublicKey: "host1-pub-key",
  78. },
  79. {
  80. Job: "",
  81. IndexOrID: "2",
  82. Username: "user",
  83. Host: "host2-ip",
  84. HostPublicKey: "host2-pub-key",
  85. },
  86. },
  87. GatewayUsername: "",
  88. GatewayHost: "",
  89. }))
  90. })
  91. It("sets up SSH sessions with Director provided gateway host and username", func() {
  92. respBody := `[
  93. {
  94. "index": 1,
  95. "host_public_key": "host1-pub-key",
  96. "ip": "host1-ip",
  97. "status": "success",
  98. "command": "setup",
  99. "gateway_user": "gw-user",
  100. "gateway_host": "gw-host"
  101. },
  102. {
  103. "index": 2,
  104. "host_public_key": "host2-pub-key",
  105. "ip": "host2-ip",
  106. "status": "success",
  107. "command": "setup"
  108. }
  109. ]`
  110. ConfigureTaskResult(ghttp.VerifyRequest("POST", "/deployments/dep/ssh"), respBody, server)
  111. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  112. opts := SSHOpts{
  113. Username: "user",
  114. PublicKey: "pub-key",
  115. }
  116. result, err := deployment.SetUpSSH(slug, opts)
  117. Expect(err).ToNot(HaveOccurred())
  118. Expect(result).To(Equal(SSHResult{
  119. Hosts: []Host{
  120. {
  121. Job: "",
  122. IndexOrID: "1",
  123. Username: "user",
  124. Host: "host1-ip",
  125. HostPublicKey: "host1-pub-key",
  126. },
  127. {
  128. Job: "",
  129. IndexOrID: "2",
  130. Username: "user",
  131. Host: "host2-ip",
  132. HostPublicKey: "host2-pub-key",
  133. },
  134. },
  135. // Assumes that Director returns same gateway information for each one of the hosts
  136. GatewayUsername: "gw-user",
  137. GatewayHost: "gw-host",
  138. }))
  139. })
  140. It("allows to use it with multiple jobs and indicies", func() {
  141. respBody := `[
  142. {
  143. "index": 1,
  144. "host_public_key": "host1-pub-key",
  145. "ip": "host1-ip",
  146. "status": "success",
  147. "command": "setup"
  148. }
  149. ]`
  150. ConfigureTaskResult(
  151. ghttp.CombineHandlers(
  152. ghttp.VerifyRequest("POST", "/deployments/dep/ssh"),
  153. ghttp.VerifyBasicAuth("username", "password"),
  154. ghttp.VerifyJSONRepresenting(map[string]interface{}{
  155. "command": "setup",
  156. "params": map[string]string{
  157. "user": "user",
  158. "public_key": "pub-key",
  159. },
  160. "deployment_name": "dep",
  161. "target": map[string]interface{}{
  162. // Empty string arrays are necessary for Director
  163. "indexes": []string{},
  164. "ids": []string{},
  165. },
  166. }),
  167. ),
  168. respBody,
  169. server,
  170. )
  171. slug := NewAllOrInstanceGroupOrInstanceSlug("", "")
  172. opts := SSHOpts{
  173. Username: "user",
  174. PublicKey: "pub-key",
  175. }
  176. result, err := deployment.SetUpSSH(slug, opts)
  177. Expect(err).ToNot(HaveOccurred())
  178. Expect(result).To(Equal(SSHResult{
  179. Hosts: []Host{
  180. {
  181. Job: "",
  182. IndexOrID: "1",
  183. Username: "user",
  184. Host: "host1-ip",
  185. HostPublicKey: "host1-pub-key",
  186. },
  187. },
  188. }))
  189. })
  190. It("picks up ID over index and ignores if index is null", func() {
  191. respBody := `[
  192. {
  193. "index": 1,
  194. "id": "host1-id",
  195. "host_public_key": "host1-pub-key",
  196. "ip": "host1-ip",
  197. "status": "success",
  198. "command": "setup"
  199. },
  200. {
  201. "id": "host2-id",
  202. "host_public_key": "host2-pub-key",
  203. "ip": "host2-ip",
  204. "status": "success",
  205. "command": "setup"
  206. }
  207. ]`
  208. ConfigureTaskResult(ghttp.VerifyRequest("POST", "/deployments/dep/ssh"), respBody, server)
  209. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  210. opts := SSHOpts{
  211. Username: "user",
  212. PublicKey: "pub-key",
  213. }
  214. result, err := deployment.SetUpSSH(slug, opts)
  215. Expect(err).ToNot(HaveOccurred())
  216. Expect(result).To(Equal(SSHResult{
  217. Hosts: []Host{
  218. {
  219. Job: "",
  220. IndexOrID: "host1-id",
  221. Username: "user",
  222. Host: "host1-ip",
  223. HostPublicKey: "host1-pub-key",
  224. },
  225. {
  226. Job: "",
  227. IndexOrID: "host2-id",
  228. Username: "user",
  229. Host: "host2-ip",
  230. HostPublicKey: "host2-pub-key",
  231. },
  232. },
  233. }))
  234. })
  235. It("returns error if no sessions were created", func() {
  236. ConfigureTaskResult(ghttp.VerifyRequest("POST", "/deployments/dep/ssh"), "[]", server)
  237. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  238. _, err := deployment.SetUpSSH(slug, SSHOpts{})
  239. Expect(err).To(HaveOccurred())
  240. Expect(err.Error()).To(ContainSubstring("Did not create any SSH sessions for the instances"))
  241. })
  242. It("returns error if any session creation fails", func() {
  243. respBody := `[
  244. {
  245. "index": 1,
  246. "host_public_key": "host1-pub-key",
  247. "ip": "host1-ip",
  248. "status": "success",
  249. "command": "setup"
  250. },
  251. {
  252. "index": 2,
  253. "host_public_key": "host2-pub-key",
  254. "ip": "host2-ip",
  255. "status": "not-success",
  256. "command": "setup"
  257. }
  258. ]`
  259. ConfigureTaskResult(ghttp.VerifyRequest("POST", "/deployments/dep/ssh"), respBody, server)
  260. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  261. _, err := deployment.SetUpSSH(slug, SSHOpts{})
  262. Expect(err).To(HaveOccurred())
  263. Expect(err.Error()).To(ContainSubstring("Failed to set up SSH session for one of the instances"))
  264. })
  265. It("returns error if response is non-200", func() {
  266. AppendBadRequest(ghttp.VerifyRequest("POST", "/deployments/dep/ssh"), server)
  267. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  268. _, err := deployment.SetUpSSH(slug, SSHOpts{})
  269. Expect(err).To(HaveOccurred())
  270. Expect(err.Error()).To(ContainSubstring("Setting up SSH in deployment"))
  271. })
  272. It("returns error if response cannot be unmarshalled", func() {
  273. server.AppendHandlers(
  274. ghttp.CombineHandlers(
  275. ghttp.VerifyRequest("POST", "/deployments/dep/ssh"),
  276. ghttp.RespondWith(http.StatusOK, ""),
  277. ),
  278. )
  279. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  280. _, err := deployment.SetUpSSH(slug, SSHOpts{})
  281. Expect(err).To(HaveOccurred())
  282. Expect(err.Error()).To(ContainSubstring(
  283. "Setting up SSH in deployment 'dep': Unmarshaling Director response"))
  284. })
  285. })
  286. Describe("CleanUpSSH", func() {
  287. It("cleans up SSH for specific job and index-or-id", func() {
  288. server.AppendHandlers(
  289. ghttp.CombineHandlers(
  290. ghttp.VerifyRequest("POST", "/deployments/dep/ssh"),
  291. ghttp.VerifyBasicAuth("username", "password"),
  292. ghttp.VerifyJSONRepresenting(map[string]interface{}{
  293. "command": "cleanup",
  294. "params": map[string]string{
  295. "user_regex": "^user",
  296. },
  297. "deployment_name": "dep",
  298. "target": map[string]interface{}{
  299. "job": "job",
  300. "indexes": []string{"index"},
  301. "ids": []string{"index"},
  302. },
  303. }),
  304. ),
  305. )
  306. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  307. opts := SSHOpts{
  308. Username: "user",
  309. PublicKey: "pub-key",
  310. }
  311. err := deployment.CleanUpSSH(slug, opts)
  312. Expect(err).ToNot(HaveOccurred())
  313. })
  314. It("allows to use it with multiple jobs and indicies", func() {
  315. server.AppendHandlers(
  316. ghttp.CombineHandlers(
  317. ghttp.VerifyRequest("POST", "/deployments/dep/ssh"),
  318. ghttp.VerifyBasicAuth("username", "password"),
  319. ghttp.VerifyJSONRepresenting(map[string]interface{}{
  320. "command": "cleanup",
  321. "params": map[string]string{
  322. "user_regex": "^user",
  323. },
  324. "deployment_name": "dep",
  325. "target": map[string]interface{}{
  326. // Empty string arrays are necessary for Director
  327. "indexes": []string{},
  328. "ids": []string{},
  329. },
  330. }),
  331. ),
  332. )
  333. slug := NewAllOrInstanceGroupOrInstanceSlug("", "")
  334. opts := SSHOpts{
  335. Username: "user",
  336. PublicKey: "pub-key",
  337. }
  338. err := deployment.CleanUpSSH(slug, opts)
  339. Expect(err).ToNot(HaveOccurred())
  340. })
  341. It("returns error if response is non-200", func() {
  342. AppendBadRequest(ghttp.VerifyRequest("POST", "/deployments/dep/ssh"), server)
  343. slug := NewAllOrInstanceGroupOrInstanceSlug("job", "index")
  344. err := deployment.CleanUpSSH(slug, SSHOpts{})
  345. Expect(err).To(HaveOccurred())
  346. Expect(err.Error()).To(ContainSubstring("Cleaning up SSH in deployment"))
  347. })
  348. })
  349. })