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  })