github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/topgun/both/build_container_gc_test.go (about) 1 package topgun_test 2 3 import ( 4 "fmt" 5 "time" 6 7 sq "github.com/Masterminds/squirrel" 8 . "github.com/pf-qiu/concourse/v6/topgun/common" 9 _ "github.com/lib/pq" 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 "github.com/onsi/gomega/gbytes" 13 ) 14 15 var _ = Describe("Garbage collecting build containers", func() { 16 BeforeEach(func() { 17 Deploy("deployments/concourse.yml") 18 }) 19 20 getContainers := func(condition, value string) []string { 21 containers := FlyTable("containers") 22 23 var handles []string 24 for _, c := range containers { 25 if c[condition] == value { 26 handles = append(handles, c["handle"]) 27 } 28 } 29 30 return handles 31 } 32 33 Describe("A container that belonged to a build that succeeded", func() { 34 Context("one-off builds", func() { 35 It("is removed from the database and worker [#129725995]", func() { 36 By("running a task with container having a rootfs, input, and output volume") 37 Fly.Run("execute", "-c", "tasks/input-output.yml", "-i", "some-input=./tasks") 38 39 By("collecting the build containers") 40 buildContainerHandles := getContainers("build id", "1") 41 42 By(fmt.Sprintf("eventually expiring the build containers: %v", buildContainerHandles)) 43 Eventually(func() int { 44 var containerNum int 45 err := Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": buildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 46 Expect(err).ToNot(HaveOccurred()) 47 48 return containerNum 49 }, 10*time.Minute, time.Second).Should(BeZero()) 50 51 By("having removed the containers from the worker") 52 containers, err := WorkerGardenClient.Containers(nil) 53 Expect(err).ToNot(HaveOccurred()) 54 55 existingHandles := []string{} 56 for _, c := range containers { 57 existingHandles = append(existingHandles, c.Handle()) 58 } 59 60 for _, handle := range buildContainerHandles { 61 Expect(existingHandles).ToNot(ContainElement(handle)) 62 } 63 }) 64 }) 65 66 Context("pipeline builds", func() { 67 It("is removed from the database and worker [#129725995]", func() { 68 By("setting pipeline that creates containers for check, get, task, put") 69 Fly.Run("set-pipeline", "-n", "-c", "pipelines/get-task-put.yml", "-p", "build-container-gc") 70 71 By("unpausing the pipeline") 72 Fly.Run("unpause-pipeline", "-p", "build-container-gc") 73 74 By("triggering job") 75 Fly.Run("trigger-job", "-w", "-j", "build-container-gc/simple-job") 76 77 By("collecting the build containers") 78 buildContainerHandles := getContainers("type", "task") 79 80 By(fmt.Sprintf("eventually expiring the build containers: %v", buildContainerHandles)) 81 Eventually(func() int { 82 var containerNum int 83 err := Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": buildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 84 Expect(err).ToNot(HaveOccurred()) 85 86 return containerNum 87 }, 10*time.Minute, time.Second).Should(BeZero()) 88 89 By("having removed the containers from the worker") 90 containers, err := WorkerGardenClient.Containers(nil) 91 Expect(err).ToNot(HaveOccurred()) 92 93 existingHandles := []string{} 94 for _, c := range containers { 95 existingHandles = append(existingHandles, c.Handle()) 96 } 97 98 for _, handle := range buildContainerHandles { 99 Expect(existingHandles).ToNot(ContainElement(handle)) 100 } 101 }) 102 }) 103 }) 104 105 Describe("A container that belonged to a build that fails", func() { 106 Context("pipeline builds", func() { 107 It("keeps in the database and worker [#129725995]", func() { 108 By("setting pipeline that creates containers for check, get, task, put") 109 Fly.Run("set-pipeline", "-n", "-c", "pipelines/get-task-put-failing.yml", "-p", "build-container-gc") 110 111 By("unpausing the pipeline") 112 Fly.Run("unpause-pipeline", "-p", "build-container-gc") 113 114 By("triggering job") 115 <-Fly.Start("trigger-job", "-w", "-j", "build-container-gc/simple-job").Exited 116 117 By("collecting the build containers") 118 buildContainerHandles := getContainers("type", "task") 119 120 By(fmt.Sprintf("not expiring the build containers: %v", buildContainerHandles)) 121 Consistently(func() int { 122 var containerNum int 123 err := Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": buildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 124 Expect(err).ToNot(HaveOccurred()) 125 126 return containerNum 127 }, 2*time.Minute, time.Second).Should(Equal(len(buildContainerHandles))) 128 129 By("not removing the containers from the worker") 130 containers, err := WorkerGardenClient.Containers(nil) 131 Expect(err).ToNot(HaveOccurred()) 132 133 existingHandles := []string{} 134 for _, c := range containers { 135 existingHandles = append(existingHandles, c.Handle()) 136 } 137 138 for _, handle := range buildContainerHandles { 139 Expect(existingHandles).To(ContainElement(handle)) 140 } 141 }) 142 }) 143 144 Context("pipeline builds that fail subsequently", func() { 145 It("keeps the latest build containers in the database and worker, removes old build containers from database and worker [#129725995]", func() { 146 By("setting pipeline that creates containers for check, get, task, put") 147 Fly.Run("set-pipeline", "-n", "-c", "pipelines/get-task-put-failing.yml", "-p", "build-container-gc") 148 149 By("unpausing the pipeline") 150 Fly.Run("unpause-pipeline", "-p", "build-container-gc") 151 152 By("triggering first job") 153 <-Fly.Start("trigger-job", "-w", "-j", "build-container-gc/simple-job").Exited 154 155 By("collecting the first build containers") 156 firstBuildContainerHandles := getContainers("type", "task") 157 158 By("triggering second job") 159 <-Fly.Start("trigger-job", "-w", "-j", "build-container-gc/simple-job").Exited 160 161 By("collecting the second build containers") 162 allBuildContainerHandles := getContainers("type", "task") 163 164 var secondBuildContainerHandles []string 165 for _, handle := range allBuildContainerHandles { 166 alreadyExisted := false 167 for _, preHandle := range firstBuildContainerHandles { 168 if preHandle == handle { 169 alreadyExisted = true 170 break 171 } 172 } 173 174 if !alreadyExisted { 175 secondBuildContainerHandles = append(secondBuildContainerHandles, handle) 176 } 177 } 178 179 By(fmt.Sprintf("eventually expiring the first build containers: %v", firstBuildContainerHandles)) 180 Eventually(func() int { 181 var containerNum int 182 err := Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": firstBuildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 183 Expect(err).ToNot(HaveOccurred()) 184 185 return containerNum 186 }, 10*time.Minute, time.Second).Should(BeZero()) 187 188 By("having removed the first build containers from the worker") 189 containers, err := WorkerGardenClient.Containers(nil) 190 Expect(err).ToNot(HaveOccurred()) 191 192 existingHandles := []string{} 193 for _, c := range containers { 194 existingHandles = append(existingHandles, c.Handle()) 195 } 196 197 for _, handle := range firstBuildContainerHandles { 198 Expect(existingHandles).NotTo(ContainElement(handle)) 199 } 200 201 By(fmt.Sprintf("not expiring the second build containers: %v", secondBuildContainerHandles)) 202 Consistently(func() int { 203 var containerNum int 204 err := Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": secondBuildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 205 Expect(err).ToNot(HaveOccurred()) 206 207 return containerNum 208 }, 2*time.Minute, time.Second).Should(Equal(len(secondBuildContainerHandles))) 209 210 By("not removing the containers from the worker") 211 for _, handle := range secondBuildContainerHandles { 212 Expect(existingHandles).To(ContainElement(handle)) 213 } 214 }) 215 }) 216 217 Context("pipeline builds that is running and previous build failed", func() { 218 It("keeps both the latest and previous build containers in the database and worker [#129725995]", func() { 219 By("setting pipeline that creates containers for check, get, task, put") 220 Fly.Run("set-pipeline", "-n", "-c", "pipelines/get-task-put-failing.yml", "-p", "build-container-gc") 221 222 By("unpausing the pipeline") 223 Fly.Run("unpause-pipeline", "-p", "build-container-gc") 224 225 By("triggering first failing job") 226 <-Fly.Start("trigger-job", "-w", "-j", "build-container-gc/simple-job").Exited 227 228 By("collecting the first build containers") 229 firstBuildContainerHandles := getContainers("type", "task") 230 231 By("triggering second long running job") 232 Fly.Run("set-pipeline", "-n", "-c", "pipelines/get-task-put-waiting.yml", "-p", "build-container-gc") 233 runningBuildSession := Fly.Start("trigger-job", "-w", "-j", "build-container-gc/simple-job") 234 Eventually(runningBuildSession).Should(gbytes.Say("waiting for /tmp/stop-waiting")) 235 236 By("collecting the second build containers") 237 allBuildContainerHandles := getContainers("type", "task") 238 239 var secondBuildContainerHandles []string 240 for _, handle := range allBuildContainerHandles { 241 alreadyExisted := false 242 for _, preHandle := range firstBuildContainerHandles { 243 if preHandle == handle { 244 alreadyExisted = true 245 break 246 } 247 } 248 249 if !alreadyExisted { 250 secondBuildContainerHandles = append(secondBuildContainerHandles, handle) 251 } 252 } 253 254 By(fmt.Sprintf("not expiring the first build containers: %v", firstBuildContainerHandles)) 255 Consistently(func() int { 256 var containerNum int 257 err := Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": firstBuildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 258 Expect(err).ToNot(HaveOccurred()) 259 260 return containerNum 261 }, 2*time.Minute, time.Second).Should(Equal(len(firstBuildContainerHandles))) 262 263 By("not removing the first build containers from the worker") 264 containers, err := WorkerGardenClient.Containers(nil) 265 Expect(err).ToNot(HaveOccurred()) 266 267 existingHandles := []string{} 268 for _, c := range containers { 269 existingHandles = append(existingHandles, c.Handle()) 270 } 271 272 for _, handle := range firstBuildContainerHandles { 273 Expect(existingHandles).To(ContainElement(handle)) 274 } 275 276 By(fmt.Sprintf("not expiring the second build containers: %v", secondBuildContainerHandles)) 277 Consistently(func() int { 278 var containerNum int 279 err = Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"handle": secondBuildContainerHandles}).RunWith(DbConn).QueryRow().Scan(&containerNum) 280 Expect(err).ToNot(HaveOccurred()) 281 282 return containerNum 283 }, 2*time.Minute, time.Second).Should(Equal(len(secondBuildContainerHandles))) 284 285 By("not removing the second build containers from the worker") 286 for _, handle := range secondBuildContainerHandles { 287 Expect(existingHandles).To(ContainElement(handle)) 288 } 289 290 Fly.Run("abort-build", "-j", "build-container-gc/simple-job", "-b", "2") 291 292 <-runningBuildSession.Exited 293 }) 294 }) 295 }) 296 })