github.com/chenbh/concourse/v6@v6.4.2/fly/integration/check_resource_type_test.go (about) 1 package integration_test 2 3 import ( 4 "net/http" 5 "os/exec" 6 7 "github.com/chenbh/concourse/v6/atc" 8 "github.com/chenbh/concourse/v6/fly/ui" 9 "github.com/fatih/color" 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 13 "github.com/onsi/gomega/gbytes" 14 "github.com/onsi/gomega/gexec" 15 "github.com/onsi/gomega/ghttp" 16 ) 17 18 var _ = Describe("CheckResourceType", func() { 19 var ( 20 flyCmd *exec.Cmd 21 check atc.Check 22 resourceTypes atc.VersionedResourceTypes 23 expectedHeaders ui.TableRow 24 ) 25 26 BeforeEach(func() { 27 check = atc.Check{ 28 ID: 123, 29 Status: "started", 30 CreateTime: 100000000000, 31 } 32 33 resourceTypes = atc.VersionedResourceTypes{{ 34 ResourceType: atc.ResourceType{ 35 Name: "myresource", 36 Type: "myresourcetype", 37 }, 38 }, { 39 ResourceType: atc.ResourceType{ 40 Name: "myresourcetype", 41 Type: "mybaseresourcetype", 42 }, 43 }} 44 45 expectedHeaders = ui.TableRow{ 46 {Contents: "id", Color: color.New(color.Bold)}, 47 {Contents: "name", Color: color.New(color.Bold)}, 48 {Contents: "status", Color: color.New(color.Bold)}, 49 {Contents: "check_error", Color: color.New(color.Bold)}, 50 } 51 }) 52 53 Context("when version is specified", func() { 54 BeforeEach(func() { 55 expectedURL := "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check" 56 atcServer.AppendHandlers( 57 ghttp.CombineHandlers( 58 ghttp.VerifyRequest("POST", expectedURL), 59 ghttp.VerifyJSON(`{"from":{"ref":"fake-ref"}}`), 60 ghttp.RespondWithJSONEncoded(http.StatusOK, check), 61 ), 62 ) 63 }) 64 65 It("sends check resource request to ATC", func() { 66 Expect(func() { 67 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "-f", "ref:fake-ref", "--shallow", "-a") 68 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 69 Expect(err).NotTo(HaveOccurred()) 70 71 Eventually(sess).Should(gexec.Exit(0)) 72 73 Eventually(sess.Out).Should(PrintTable(ui.Table{ 74 Headers: expectedHeaders, 75 Data: []ui.TableRow{ 76 { 77 {Contents: "123"}, 78 {Contents: "myresource"}, 79 {Contents: "started"}, 80 {Contents: ""}, 81 }, 82 }, 83 })) 84 85 }).To(Change(func() int { 86 return len(atcServer.ReceivedRequests()) 87 }).By(2)) 88 }) 89 }) 90 91 Context("when version is omitted", func() { 92 BeforeEach(func() { 93 expectedURL := "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check" 94 atcServer.AppendHandlers( 95 ghttp.CombineHandlers( 96 ghttp.VerifyRequest("POST", expectedURL), 97 ghttp.VerifyJSON(`{"from":null}`), 98 ghttp.RespondWithJSONEncoded(http.StatusOK, check), 99 ), 100 ) 101 }) 102 103 It("sends check resource request to ATC", func() { 104 Expect(func() { 105 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "--shallow", "-a") 106 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 107 Expect(err).NotTo(HaveOccurred()) 108 109 Eventually(sess).Should(gexec.Exit(0)) 110 111 Eventually(sess.Out).Should(PrintTable(ui.Table{ 112 Headers: expectedHeaders, 113 Data: []ui.TableRow{ 114 { 115 {Contents: "123"}, 116 {Contents: "myresource"}, 117 {Contents: "started"}, 118 {Contents: ""}, 119 }, 120 }, 121 })) 122 123 }).To(Change(func() int { 124 return len(atcServer.ReceivedRequests()) 125 }).By(2)) 126 }) 127 }) 128 129 Context("when the check succeed", func() { 130 BeforeEach(func() { 131 expectedURL := "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check" 132 atcServer.AppendHandlers( 133 ghttp.CombineHandlers( 134 ghttp.VerifyRequest("POST", expectedURL), 135 ghttp.VerifyJSON(`{"from":null}`), 136 ghttp.RespondWithJSONEncoded(http.StatusOK, check), 137 ), 138 ghttp.CombineHandlers( 139 ghttp.VerifyRequest("GET", "/api/v1/checks/123"), 140 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Check{ 141 ID: 123, 142 Status: "succeeded", 143 CreateTime: 100000000000, 144 StartTime: 100000000000, 145 EndTime: 100000000000, 146 }), 147 ), 148 ) 149 }) 150 151 It("sends check resource request to ATC", func() { 152 Expect(func() { 153 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "--shallow") 154 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 155 Expect(err).NotTo(HaveOccurred()) 156 157 Eventually(sess).Should(gexec.Exit(0)) 158 159 Eventually(sess.Out).Should(PrintTable(ui.Table{ 160 Headers: expectedHeaders, 161 Data: []ui.TableRow{ 162 { 163 {Contents: "123"}, 164 {Contents: "myresource"}, 165 {Contents: "succeeded"}, 166 }, 167 }, 168 })) 169 170 }).To(Change(func() int { 171 return len(atcServer.ReceivedRequests()) 172 }).By(3)) 173 }) 174 }) 175 176 Context("when the check fail", func() { 177 BeforeEach(func() { 178 expectedURL := "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check" 179 atcServer.AppendHandlers( 180 ghttp.CombineHandlers( 181 ghttp.VerifyRequest("POST", expectedURL), 182 ghttp.VerifyJSON(`{"from":null}`), 183 ghttp.RespondWithJSONEncoded(http.StatusOK, check), 184 ), 185 ghttp.CombineHandlers( 186 ghttp.VerifyRequest("GET", "/api/v1/checks/123"), 187 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Check{ 188 ID: 123, 189 Status: "errored", 190 CreateTime: 100000000000, 191 StartTime: 100000000000, 192 EndTime: 100000000000, 193 CheckError: "some-check-error", 194 }), 195 ), 196 ) 197 }) 198 199 It("sends check resource request to ATC", func() { 200 Expect(func() { 201 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "--shallow") 202 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 203 Expect(err).NotTo(HaveOccurred()) 204 205 Eventually(sess).Should(gexec.Exit(1)) 206 207 Eventually(sess.Out).Should(PrintTable(ui.Table{ 208 Headers: expectedHeaders, 209 Data: []ui.TableRow{ 210 { 211 {Contents: "123"}, 212 {Contents: "myresource"}, 213 {Contents: "errored"}, 214 {Contents: "some-check-error"}, 215 }, 216 }, 217 })) 218 219 }).To(Change(func() int { 220 return len(atcServer.ReceivedRequests()) 221 }).By(3)) 222 }) 223 }) 224 225 Context("when recursive check succeeds", func() { 226 BeforeEach(func() { 227 atcServer.AppendHandlers( 228 ghttp.CombineHandlers( 229 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/mypipeline/resource-types"), 230 ghttp.RespondWithJSONEncoded(http.StatusOK, resourceTypes), 231 ), 232 ghttp.CombineHandlers( 233 ghttp.VerifyRequest("GET", "/api/v1/info"), 234 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Info{Version: atcVersion, WorkerVersion: workerVersion}), 235 ), 236 ghttp.CombineHandlers( 237 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/mypipeline/resource-types"), 238 ghttp.RespondWithJSONEncoded(http.StatusOK, resourceTypes), 239 ), 240 ghttp.CombineHandlers( 241 ghttp.VerifyRequest("POST", "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresourcetype/check"), 242 ghttp.VerifyJSON(`{"from":null}`), 243 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Check{ 244 ID: 987, 245 Status: "started", 246 }), 247 ), 248 ghttp.CombineHandlers( 249 ghttp.VerifyRequest("GET", "/api/v1/checks/987"), 250 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Check{ 251 ID: 987, 252 Status: "succeeded", 253 CreateTime: 100000000000, 254 StartTime: 100000000000, 255 EndTime: 100000000000, 256 CheckError: "", 257 }), 258 ), 259 ghttp.CombineHandlers( 260 ghttp.VerifyRequest("POST", "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check"), 261 ghttp.VerifyJSON(`{"from":null}`), 262 ghttp.RespondWithJSONEncoded(http.StatusOK, check), 263 ), 264 ) 265 }) 266 267 It("sends check resource request to ATC", func() { 268 Expect(func() { 269 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "-a") 270 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 271 Expect(err).NotTo(HaveOccurred()) 272 273 Eventually(sess).Should(gexec.Exit(0)) 274 275 Eventually(sess.Out).Should(PrintTable(ui.Table{ 276 Headers: expectedHeaders, 277 Data: []ui.TableRow{ 278 { 279 {Contents: "987"}, 280 {Contents: "myresourcetype"}, 281 {Contents: "succeeded"}, 282 {Contents: ""}, 283 }, 284 }, 285 })) 286 287 Eventually(sess.Out).Should(PrintTable(ui.Table{ 288 Headers: expectedHeaders, 289 Data: []ui.TableRow{ 290 { 291 {Contents: "123"}, 292 {Contents: "myresource"}, 293 {Contents: "started"}, 294 {Contents: ""}, 295 }, 296 }, 297 })) 298 299 }).To(Change(func() int { 300 return len(atcServer.ReceivedRequests()) 301 }).By(7)) 302 }) 303 }) 304 305 Context("when recursive check fails", func() { 306 BeforeEach(func() { 307 atcServer.AppendHandlers( 308 ghttp.CombineHandlers( 309 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/mypipeline/resource-types"), 310 ghttp.RespondWithJSONEncoded(http.StatusOK, resourceTypes), 311 ), 312 ghttp.CombineHandlers( 313 ghttp.VerifyRequest("GET", "/api/v1/info"), 314 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Info{Version: atcVersion, WorkerVersion: workerVersion}), 315 ), 316 ghttp.CombineHandlers( 317 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/mypipeline/resource-types"), 318 ghttp.RespondWithJSONEncoded(http.StatusOK, resourceTypes), 319 ), 320 ghttp.CombineHandlers( 321 ghttp.VerifyRequest("POST", "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresourcetype/check"), 322 ghttp.VerifyJSON(`{"from":null}`), 323 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Check{ 324 ID: 987, 325 Status: "started", 326 }), 327 ), 328 ghttp.CombineHandlers( 329 ghttp.VerifyRequest("GET", "/api/v1/checks/987"), 330 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Check{ 331 ID: 987, 332 Status: "errored", 333 CreateTime: 100000000000, 334 StartTime: 100000000000, 335 EndTime: 100000000000, 336 CheckError: "failed to check", 337 }), 338 ), 339 ) 340 }) 341 342 It("sends check resource request to ATC", func() { 343 Expect(func() { 344 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "-a") 345 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 346 Expect(err).NotTo(HaveOccurred()) 347 348 Eventually(sess).Should(gexec.Exit(1)) 349 350 Eventually(sess.Out).Should(PrintTable(ui.Table{ 351 Headers: expectedHeaders, 352 Data: []ui.TableRow{ 353 { 354 {Contents: "987"}, 355 {Contents: "myresourcetype"}, 356 {Contents: "errored"}, 357 {Contents: "failed to check"}, 358 }, 359 }, 360 })) 361 362 }).To(Change(func() int { 363 return len(atcServer.ReceivedRequests()) 364 }).By(6)) 365 }) 366 }) 367 368 Context("when pipeline or resource-type is not found", func() { 369 BeforeEach(func() { 370 expectedURL := "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check" 371 atcServer.AppendHandlers( 372 ghttp.CombineHandlers( 373 ghttp.VerifyRequest("POST", expectedURL), 374 ghttp.RespondWithJSONEncoded(http.StatusNotFound, ""), 375 ), 376 ) 377 }) 378 379 It("fails with error", func() { 380 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "--shallow") 381 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 382 Expect(err).NotTo(HaveOccurred()) 383 384 Eventually(sess).Should(gexec.Exit(1)) 385 386 Expect(sess.Err).To(gbytes.Say("pipeline 'mypipeline' or resource-type 'myresource' not found")) 387 }) 388 }) 389 390 Context("When resource-type check returns internal server error", func() { 391 BeforeEach(func() { 392 expectedURL := "/api/v1/teams/main/pipelines/mypipeline/resource-types/myresource/check" 393 atcServer.AppendHandlers( 394 ghttp.CombineHandlers( 395 ghttp.VerifyRequest("POST", expectedURL), 396 ghttp.RespondWith(http.StatusInternalServerError, "unknown server error"), 397 ), 398 ) 399 }) 400 401 It("outputs error in response body", func() { 402 flyCmd = exec.Command(flyPath, "-t", targetName, "check-resource-type", "-r", "mypipeline/myresource", "--shallow") 403 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 404 Expect(err).NotTo(HaveOccurred()) 405 406 Eventually(sess).Should(gexec.Exit(1)) 407 408 Expect(sess.Err).To(gbytes.Say("unknown server error")) 409 }) 410 }) 411 })