github.com/chenbh/concourse/v6@v6.4.2/fly/integration/trigger_job_test.go (about) 1 package integration_test 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "os" 8 "os/exec" 9 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 "github.com/vito/go-sse/sse" 13 14 "github.com/chenbh/concourse/v6/atc" 15 "github.com/chenbh/concourse/v6/atc/event" 16 "github.com/onsi/gomega/gbytes" 17 "github.com/onsi/gomega/gexec" 18 "github.com/onsi/gomega/ghttp" 19 "github.com/tedsuo/rata" 20 ) 21 22 var _ = Describe("Fly CLI", func() { 23 Describe("trigger-job", func() { 24 var ( 25 mainPath string 26 otherPath string 27 otherRandomPath string 28 err error 29 ) 30 31 BeforeEach(func() { 32 mainPath, err = atc.Routes.CreatePathForRoute(atc.CreateJobBuild, rata.Params{"pipeline_name": "awesome-pipeline", "job_name": "awesome-job", "team_name": "main"}) 33 Expect(err).NotTo(HaveOccurred()) 34 35 otherPath, err = atc.Routes.CreatePathForRoute(atc.CreateJobBuild, rata.Params{"pipeline_name": "awesome-pipeline", "job_name": "awesome-job", "team_name": "other-team"}) 36 Expect(err).NotTo(HaveOccurred()) 37 38 otherRandomPath, err = atc.Routes.CreatePathForRoute(atc.CreateJobBuild, rata.Params{"pipeline_name": "awesome-pipeline", "job_name": "awesome-job", "team_name": "random-team"}) 39 Expect(err).NotTo(HaveOccurred()) 40 }) 41 42 Context("when the pipeline and job name are specified", func() { 43 Context("when the pipeline and job exists", func() { 44 Context("user and pipeline are part of the main team", func() { 45 Context("user is targeting the same team that the pipeline belongs to", func() { 46 47 BeforeEach(func() { 48 atcServer.AppendHandlers( 49 ghttp.CombineHandlers( 50 ghttp.VerifyRequest("POST", mainPath), 51 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Build{ID: 57, Name: "42"}), 52 ), 53 ) 54 }) 55 56 It("starts the build", func() { 57 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job", "-j", "awesome-pipeline/awesome-job") 58 59 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 60 Expect(err).NotTo(HaveOccurred()) 61 62 Eventually(sess).Should(gbytes.Say(`started awesome-pipeline/awesome-job #42`)) 63 64 <-sess.Exited 65 Expect(sess.ExitCode()).To(Equal(0)) 66 }) 67 }) 68 69 Context("user is NOT targeting the same team that the pipeline belongs to", func() { 70 71 BeforeEach(func() { 72 atcServer.AppendHandlers( 73 ghttp.CombineHandlers( 74 ghttp.VerifyRequest("GET", "/api/v1/teams/other-team"), 75 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Team{ 76 Name: "other-team", 77 }), 78 ), 79 ghttp.CombineHandlers( 80 ghttp.VerifyRequest("POST", otherPath), 81 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Build{ID: 57, Name: "42"}), 82 ), 83 ) 84 }) 85 86 It("starts the build", func() { 87 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job", "-j", "awesome-pipeline/awesome-job", "--team", "other-team") 88 89 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 90 Expect(err).NotTo(HaveOccurred()) 91 92 Eventually(sess).Should(gbytes.Say(`started awesome-pipeline/awesome-job #42`)) 93 94 <-sess.Exited 95 Expect(sess.ExitCode()).To(Equal(0)) 96 }) 97 98 }) 99 }) 100 101 Context("when -w option is provided", func() { 102 var streaming chan struct{} 103 var events chan atc.Event 104 105 BeforeEach(func() { 106 streaming = make(chan struct{}) 107 events = make(chan atc.Event) 108 atcServer.AppendHandlers( 109 ghttp.CombineHandlers( 110 ghttp.VerifyRequest("POST", mainPath), 111 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Build{ID: 57, Name: "42"}), 112 ), 113 ghttp.CombineHandlers( 114 ghttp.VerifyRequest("GET", "/api/v1/builds/57/events"), 115 func(w http.ResponseWriter, r *http.Request) { 116 flusher := w.(http.Flusher) 117 118 w.Header().Add("Content-Type", "text/event-stream; charset=utf-8") 119 w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate") 120 w.Header().Add("Connection", "keep-alive") 121 122 w.WriteHeader(http.StatusOK) 123 124 flusher.Flush() 125 126 close(streaming) 127 128 id := 0 129 130 for e := range events { 131 payload, err := json.Marshal(event.Message{Event: e}) 132 Expect(err).NotTo(HaveOccurred()) 133 134 event := sse.Event{ 135 ID: fmt.Sprintf("%d", id), 136 Name: "event", 137 Data: payload, 138 } 139 140 err = event.Write(w) 141 Expect(err).NotTo(HaveOccurred()) 142 143 flusher.Flush() 144 145 id++ 146 } 147 148 err := sse.Event{ 149 Name: "end", 150 }.Write(w) 151 Expect(err).NotTo(HaveOccurred()) 152 }, 153 ), 154 ) 155 }) 156 157 It("watches the build", func() { 158 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job", "-j", "awesome-pipeline/awesome-job", "-w") 159 160 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 161 Expect(err).NotTo(HaveOccurred()) 162 163 Eventually(sess).Should(gbytes.Say(`started awesome-pipeline/awesome-job #42`)) 164 Eventually(streaming).Should(BeClosed()) 165 166 events <- event.Log{Payload: "sup"} 167 168 Eventually(sess.Out).Should(gbytes.Say("sup")) 169 170 close(events) 171 172 <-sess.Exited 173 Expect(sess.ExitCode()).To(Equal(0)) 174 }) 175 }) 176 }) 177 178 Context("when the pipeline/job doesn't exist", func() { 179 BeforeEach(func() { 180 atcServer.AppendHandlers( 181 ghttp.CombineHandlers( 182 ghttp.VerifyRequest("GET", "/api/v1/teams/random-team"), 183 ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Team{ 184 Name: "random-team", 185 ID: 0, 186 Auth: atc.TeamAuth{}, 187 }), 188 ), 189 ghttp.CombineHandlers( 190 ghttp.VerifyRequest("POST", otherRandomPath), 191 ghttp.RespondWith(http.StatusNotFound, nil), 192 ), 193 ) 194 }) 195 196 It("prints an error message", func() { 197 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job", "-j", "awesome-pipeline/awesome-job", "--team", "random-team") 198 199 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 200 Expect(err).NotTo(HaveOccurred()) 201 202 Eventually(sess.Err).Should(gbytes.Say(`error: resource not found`)) 203 204 <-sess.Exited 205 Expect(sess.ExitCode()).To(Equal(1)) 206 }) 207 }) 208 }) 209 210 Context("when the pipeline/job name is not specified", func() { 211 It("errors", func() { 212 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job") 213 214 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 215 Expect(err).NotTo(HaveOccurred()) 216 217 <-sess.Exited 218 Expect(sess.ExitCode()).To(Equal(1)) 219 }) 220 }) 221 222 Context("completion", func() { 223 BeforeEach(func() { 224 os.Setenv("GO_FLAGS_COMPLETION", "1") 225 }) 226 227 AfterEach(func() { 228 os.Unsetenv("GO_FLAGS_COMPLETION") 229 }) 230 231 It("returns all matching pipelines", func() { 232 atcServer.AppendHandlers( 233 ghttp.CombineHandlers( 234 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 235 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{ 236 {Name: "some-pipeline-1", Paused: false, Public: false}, 237 {Name: "some-pipeline-2", Paused: false, Public: false}, 238 {Name: "another-pipeline", Paused: false, Public: false}, 239 }), 240 ), 241 ) 242 243 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job", "-j", "some-") 244 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 245 Expect(err).NotTo(HaveOccurred()) 246 Eventually(sess).Should(gexec.Exit(0)) 247 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-1/")) 248 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-2/")) 249 Eventually(sess.Out).ShouldNot(gbytes.Say("another-pipeline/")) 250 }) 251 252 It("returns all matching jobs", func() { 253 atcServer.AppendHandlers( 254 ghttp.CombineHandlers( 255 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/some-pipeline/jobs"), 256 ghttp.RespondWithJSONEncoded(200, []atc.Job{ 257 {Name: "some-job-1"}, 258 {Name: "some-job-2"}, 259 {Name: "another-job"}, 260 }), 261 ), 262 ) 263 264 flyCmd := exec.Command(flyPath, "-t", targetName, "trigger-job", "-j", "some-pipeline/some-") 265 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 266 Expect(err).NotTo(HaveOccurred()) 267 Eventually(sess).Should(gexec.Exit(0)) 268 Eventually(sess.Out).Should(gbytes.Say("some-pipeline/some-job-1")) 269 Eventually(sess.Out).Should(gbytes.Say("some-pipeline/some-job-2")) 270 Eventually(sess.Out).ShouldNot(gbytes.Say("some-pipeline/another-job")) 271 }) 272 }) 273 }) 274 })