github.com/chenbh/concourse/v6@v6.4.2/fly/integration/pipelines_test.go (about) 1 package integration_test 2 3 import ( 4 "os" 5 "os/exec" 6 "time" 7 8 "github.com/chenbh/concourse/v6/atc" 9 "github.com/chenbh/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 }), 275 ), 276 ) 277 }) 278 It("returns all matching pipelines", func() { 279 flyCmd = exec.Command(flyPath, "-t", targetName, "get-pipeline", "-p", "some-") 280 flyCmd.Env = append(os.Environ(), "GO_FLAGS_COMPLETION=1") 281 282 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 283 Expect(err).NotTo(HaveOccurred()) 284 Eventually(sess).Should(gexec.Exit(0)) 285 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-1")) 286 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-2")) 287 Eventually(sess.Out).ShouldNot(gbytes.Say("another-pipeline")) 288 }) 289 It("works with other application level flags", func() { 290 flyCmd = exec.Command(flyPath, "--verbose", "-t", targetName, "get-pipeline", "-p", "some-") 291 flyCmd.Env = append(os.Environ(), "GO_FLAGS_COMPLETION=1") 292 293 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 294 Expect(err).NotTo(HaveOccurred()) 295 Eventually(sess).Should(gexec.Exit(0)) 296 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-1")) 297 Eventually(sess.Out).Should(gbytes.Say("some-pipeline-2")) 298 Eventually(sess.Out).ShouldNot(gbytes.Say("another-pipeline")) 299 }) 300 }) 301 }) 302 303 Context("when there are no pipelines", func() { 304 BeforeEach(func() { 305 flyCmd = exec.Command(flyPath, "-t", targetName, "pipelines") 306 atcServer.AppendHandlers( 307 ghttp.CombineHandlers( 308 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 309 ghttp.RespondWithJSONEncoded(200, []atc.Pipeline{}), 310 ), 311 ) 312 }) 313 314 Context("when --json is given", func() { 315 BeforeEach(func() { 316 flyCmd.Args = append(flyCmd.Args, "--json") 317 }) 318 319 It("prints an empty list", func() { 320 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 321 Expect(err).NotTo(HaveOccurred()) 322 Eventually(sess).Should(gexec.Exit(0)) 323 324 Expect(sess.Out.Contents()).To(MatchJSON(`[]`)) 325 }) 326 }) 327 }) 328 329 Context("and the api returns an internal server error", func() { 330 BeforeEach(func() { 331 flyCmd = exec.Command(flyPath, "-t", targetName, "pipelines") 332 atcServer.AppendHandlers( 333 ghttp.CombineHandlers( 334 ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines"), 335 ghttp.RespondWith(500, ""), 336 ), 337 ) 338 }) 339 340 It("writes an error message to stderr", func() { 341 sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter) 342 Expect(err).NotTo(HaveOccurred()) 343 344 Eventually(sess).Should(gexec.Exit(1)) 345 Eventually(sess.Err).Should(gbytes.Say("Unexpected Response")) 346 }) 347 }) 348 }) 349 })