github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/fly/integration/pipelines_test.go (about) 1 package integration_test 2 3 import ( 4 "os" 5 "os/exec" 6 "time" 7 8 "github.com/pf-qiu/concourse/v6/atc" 9 "github.com/pf-qiu/concourse/v6/fly/ui" 10 "github.com/fatih/color" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 "github.com/onsi/gomega/gbytes" 14 "github.com/onsi/gomega/gexec" 15 "github.com/onsi/gomega/ghttp" 16 ) 17 18 var _ = Describe("Fly CLI", func() { 19 Describe("pipelines", func() { 20 var ( 21 flyCmd *exec.Cmd 22 ) 23 24 JustBeforeEach(func() { 25 flyCmd.Args = append([]string{flyCmd.Args[0], "--print-table-headers"}, flyCmd.Args[1:]...) 26 }) 27 28 Context("when pipelines are returned from the API", func() { 29 BeforeEach(func() { 30 flyCmd = exec.Command(flyPath, "-t", targetName, "pipelines") 31 }) 32 Context("when no --all flag is given", func() { 33 BeforeEach(func() { 34 atcServer.AppendHandlers( 35 ghttp.CombineHandlers( 36 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 37 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{ 38 {Name: "pipeline-1-longer", Paused: false, Public: false, LastUpdated: 1}, 39 {Name: "pipeline-2", Paused: true, Public: false, LastUpdated: 1}, 40 {Name: "pipeline-3", Paused: false, Public: true, LastUpdated: 1}, 41 {Name: "archived-pipeline", Paused: false, Archived: true, Public: true, LastUpdated: 1}, 42 }), 43 ), 44 ) 45 }) 46 47 Context("when --json is given", func() { 48 BeforeEach(func() { 49 flyCmd.Args = append(flyCmd.Args, "--json") 50 }) 51 52 It("prints non-archived pipelines in json to stdout", func() { 53 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 54 Expect(err).NotTo(HaveOccurred()) 55 56 Eventually(sess).Should(gexec.Exit(0)) 57 Expect(sess.Out.Contents()).To(MatchJSON(`[ 58 { 59 "id": 0, 60 "name": "pipeline-1-longer", 61 "paused": false, 62 "public": false, 63 "archived": false, 64 "team_name": "", 65 "last_updated": 1 66 }, 67 { 68 "id": 0, 69 "name": "pipeline-2", 70 "paused": true, 71 "public": false, 72 "archived": false, 73 "team_name": "", 74 "last_updated": 1 75 }, 76 { 77 "id": 0, 78 "name": "pipeline-3", 79 "paused": false, 80 "public": true, 81 "archived": false, 82 "team_name": "", 83 "last_updated": 1 84 } 85 ]`)) 86 }) 87 }) 88 89 It("only shows the team's pipelines", func() { 90 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 91 Expect(err).NotTo(HaveOccurred()) 92 Eventually(sess).Should(gexec.Exit(0)) 93 94 Expect(sess.Out).To(PrintTableWithHeaders(ui.Table{ 95 Headers: ui.TableRow{ 96 {Contents: "name", Color: color.New(color.Bold)}, 97 {Contents: "paused", Color: color.New(color.Bold)}, 98 {Contents: "public", Color: color.New(color.Bold)}, 99 {Contents: "last updated", Color: color.New(color.Bold)}, 100 }, 101 Data: []ui.TableRow{ 102 {{Contents: "pipeline-1-longer"}, {Contents: "no"}, {Contents: "no"}, {Contents: time.Unix(1, 0).String()}}, 103 {{Contents: "pipeline-2"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: "no"}, {Contents: time.Unix(1, 0).String()}}, 104 {{Contents: "pipeline-3"}, {Contents: "no"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: time.Unix(1, 0).String()}}, 105 }, 106 })) 107 }) 108 109 It("does not print archived pipelines", func() { 110 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 111 Expect(err).NotTo(HaveOccurred()) 112 Eventually(sess).Should(gexec.Exit(0)) 113 114 Expect(sess.Out).ToNot(gbytes.Say("archived-pipeline")) 115 }) 116 }) 117 118 Context("when --all is specified", func() { 119 BeforeEach(func() { 120 flyCmd.Args = append(flyCmd.Args, "--all") 121 atcServer.AppendHandlers( 122 ghttp.CombineHandlers( 123 ghttp.VerifyRequest("GET", "/api/v1/pipelines"), 124 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{ 125 {Name: "pipeline-1-longer", Paused: false, Public: false, TeamName: "main", LastUpdated: 1}, 126 {Name: "pipeline-2", Paused: true, Public: false, TeamName: "main", LastUpdated: 1}, 127 {Name: "pipeline-3", Paused: false, Public: true, TeamName: "main", LastUpdated: 1}, 128 {Name: "archived-pipeline", Paused: false, Archived: true, Public: true, TeamName: "main", LastUpdated: 1}, 129 {Name: "foreign-pipeline-1", Paused: false, Public: true, TeamName: "other", LastUpdated: 1}, 130 {Name: "foreign-pipeline-2", Paused: false, Public: true, TeamName: "other", LastUpdated: 1}, 131 {Name: "foreign-archived-pipeline", Paused: false, Archived: true, Public: true, TeamName: "other", LastUpdated: 1}, 132 }), 133 ), 134 ) 135 }) 136 137 Context("when --json is given", func() { 138 BeforeEach(func() { 139 flyCmd.Args = append(flyCmd.Args, "--json") 140 }) 141 142 It("prints non-archived pipelines in json to stdout", func() { 143 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 144 Expect(err).NotTo(HaveOccurred()) 145 146 Eventually(sess).Should(gexec.Exit(0)) 147 Expect(sess.Out.Contents()).To(MatchJSON(`[ 148 { 149 "id": 0, 150 "name": "pipeline-1-longer", 151 "paused": false, 152 "public": false, 153 "archived": false, 154 "team_name": "main", 155 "last_updated": 1 156 }, 157 { 158 "id": 0, 159 "name": "pipeline-2", 160 "paused": true, 161 "public": false, 162 "archived": false, 163 "team_name": "main", 164 "last_updated": 1 165 }, 166 { 167 "id": 0, 168 "name": "pipeline-3", 169 "paused": false, 170 "public": true, 171 "archived": false, 172 "team_name": "main", 173 "last_updated": 1 174 }, 175 { 176 "id": 0, 177 "name": "foreign-pipeline-1", 178 "paused": false, 179 "public": true, 180 "archived": false, 181 "team_name": "other", 182 "last_updated": 1 183 }, 184 { 185 "id": 0, 186 "name": "foreign-pipeline-2", 187 "paused": false, 188 "public": true, 189 "archived": false, 190 "team_name": "other", 191 "last_updated": 1 192 } 193 ]`)) 194 }) 195 }) 196 197 It("outputs pipelines across all teams", func() { 198 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 199 Expect(err).NotTo(HaveOccurred()) 200 Eventually(sess).Should(gexec.Exit(0)) 201 202 Expect(sess.Out).To(PrintTableWithHeaders(ui.Table{ 203 Headers: ui.TableRow{ 204 {Contents: "name", Color: color.New(color.Bold)}, 205 {Contents: "team", Color: color.New(color.Bold)}, 206 {Contents: "paused", Color: color.New(color.Bold)}, 207 {Contents: "public", Color: color.New(color.Bold)}, 208 {Contents: "last updated", Color: color.New(color.Bold)}, 209 }, 210 Data: []ui.TableRow{ 211 {{Contents: "pipeline-1-longer"}, {Contents: "main"}, {Contents: "no"}, {Contents: "no"}, {Contents: time.Unix(1, 0).String()}}, 212 {{Contents: "pipeline-2"}, {Contents: "main"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: "no"}, {Contents: time.Unix(1, 0).String()}}, 213 {{Contents: "pipeline-3"}, {Contents: "main"}, {Contents: "no"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: time.Unix(1, 0).String()}}, 214 {{Contents: "foreign-pipeline-1"}, {Contents: "other"}, {Contents: "no"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: time.Unix(1, 0).String()}}, 215 {{Contents: "foreign-pipeline-2"}, {Contents: "other"}, {Contents: "no"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: time.Unix(1, 0).String()}}, 216 }, 217 })) 218 }) 219 220 It("does not print archived pipelines", func() { 221 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 222 Expect(err).NotTo(HaveOccurred()) 223 Eventually(sess).Should(gexec.Exit(0)) 224 225 Expect(sess.Out).ToNot(gbytes.Say("archived-pipeline")) 226 }) 227 }) 228 229 Context("when --include-archived is specified", func() { 230 BeforeEach(func() { 231 flyCmd.Args = append(flyCmd.Args, "--include-archived") 232 }) 233 234 It("includes archived pipelines in the output", func() { 235 atcServer.AppendHandlers( 236 ghttp.CombineHandlers( 237 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 238 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{ 239 {Name: "pipeline-1-longer", Paused: false, Public: false, TeamName: "main", LastUpdated: 1}, 240 {Name: "archived-pipeline", Paused: true, Archived: true, Public: true, TeamName: "main", LastUpdated: 1}, 241 }), 242 ), 243 ) 244 245 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 246 Expect(err).NotTo(HaveOccurred()) 247 Eventually(sess).Should(gexec.Exit(0)) 248 249 Expect(sess.Out).To(PrintTableWithHeaders(ui.Table{ 250 Headers: ui.TableRow{ 251 {Contents: "name", Color: color.New(color.Bold)}, 252 {Contents: "paused", Color: color.New(color.Bold)}, 253 {Contents: "public", Color: color.New(color.Bold)}, 254 {Contents: "archived", Color: color.New(color.Bold)}, 255 {Contents: "last updated", Color: color.New(color.Bold)}, 256 }, 257 Data: []ui.TableRow{ 258 {{Contents: "pipeline-1-longer"}, {Contents: "no"}, {Contents: "no"}, {Contents: "no"}, {Contents: time.Unix(1, 0).String()}}, 259 {{Contents: "archived-pipeline"}, {Contents: "yes"}, {Contents: "yes", Color: color.New(color.FgCyan)}, {Contents: "yes"}, {Contents: time.Unix(1, 0).String()}}, 260 }, 261 })) 262 }) 263 }) 264 265 Context("completion", func() { 266 BeforeEach(func() { 267 atcServer.AppendHandlers( 268 ghttp.CombineHandlers( 269 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 270 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{ 271 {Name: "some-pipeline-1", Paused: false, Public: false, LastUpdated: 1}, 272 {Name: "some-pipeline-2", Paused: false, Public: false, LastUpdated: 1}, 273 {Name: "another-pipeline", Paused: false, Public: false, LastUpdated: 1}, 274 {Name: "instanced-pipeline", InstanceVars: atc.InstanceVars{"branch": "master"}, Paused: false, Public: false, LastUpdated: 1}, 275 {Name: "instanced-pipeline", InstanceVars: atc.InstanceVars{"branch": "feature/foo"}, Paused: false, Public: false, LastUpdated: 1}, 276 }), 277 ), 278 ) 279 }) 280 281 It("returns all matching pipelines", func() { 282 flyCmd = exec.Command(flyPath, "-t", targetName, "get-pipeline", "-p", "some-") 283 flyCmd.Env = append(os.Environ(), "GO_FLAGS_COMPLETION=1") 284 285 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 286 Expect(err).NotTo(HaveOccurred()) 287 Eventually(sess).Should(gexec.Exit(0)) 288 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-1")) 289 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-2")) 290 Eventually(sess.Out).ShouldNot(gbytes.Say("another-pipeline")) 291 }) 292 293 It("returns all matching pipeline instances", func() { 294 flyCmd = exec.Command(flyPath, "-t", targetName, "get-pipeline", "-p", "instanced-pipeline/") 295 flyCmd.Env = append(os.Environ(), "GO_FLAGS_COMPLETION=1") 296 297 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 298 Expect(err).NotTo(HaveOccurred()) 299 Eventually(sess).Should(gexec.Exit(0)) 300 Eventually(sess.Out).Should(gbytes.Say("instanced-pipeline/branch:feature/foo")) 301 Eventually(sess.Out).Should(gbytes.Say("instanced-pipeline/branch:master")) 302 Eventually(sess.Out).ShouldNot(gbytes.Say("some-pipeline-1")) 303 Eventually(sess.Out).ShouldNot(gbytes.Say("some-pipeline-2")) 304 Eventually(sess.Out).ShouldNot(gbytes.Say("another-pipeline")) 305 306 }) 307 308 It("works with other application level flags", func() { 309 flyCmd = exec.Command(flyPath, "--verbose", "-t", targetName, "get-pipeline", "-p", "some-") 310 flyCmd.Env = append(os.Environ(), "GO_FLAGS_COMPLETION=1") 311 312 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 313 Expect(err).NotTo(HaveOccurred()) 314 Eventually(sess).Should(gexec.Exit(0)) 315 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-1")) 316 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-2")) 317 Eventually(sess.Out).ShouldNot(gbytes.Say("another-pipeline")) 318 }) 319 }) 320 }) 321 322 Context("when there are no pipelines", func() { 323 BeforeEach(func() { 324 flyCmd = exec.Command(flyPath, "-t", targetName, "pipelines") 325 atcServer.AppendHandlers( 326 ghttp.CombineHandlers( 327 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 328 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{}), 329 ), 330 ) 331 }) 332 333 Context("when --json is given", func() { 334 BeforeEach(func() { 335 flyCmd.Args = append(flyCmd.Args, "--json") 336 }) 337 338 It("prints an empty list", func() { 339 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 340 Expect(err).NotTo(HaveOccurred()) 341 Eventually(sess).Should(gexec.Exit(0)) 342 343 Expect(sess.Out.Contents()).To(MatchJSON(`[]`)) 344 }) 345 }) 346 }) 347 348 Context("and the api returns an internal server error", func() { 349 BeforeEach(func() { 350 flyCmd = exec.Command(flyPath, "-t", targetName, "pipelines") 351 atcServer.AppendHandlers( 352 ghttp.CombineHandlers( 353 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 354 ghttp.RespondWith(500, ""), 355 ), 356 ) 357 }) 358 359 It("writes an error message to stderr", func() { 360 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 361 Expect(err).NotTo(HaveOccurred()) 362 363 Eventually(sess).Should(gexec.Exit(1)) 364 Eventually(sess.Err).Should(gbytes.Say("Unexpected Response")) 365 }) 366 }) 367 }) 368 })