github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/topgun/both/volume_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 ) 13 14 var _ = Describe("Garbage-collecting volumes", func() { 15 BeforeEach(func() { 16 Deploy("deployments/concourse.yml") 17 }) 18 19 Describe("A volume that belonged to a container that is now gone", func() { 20 It("is removed from the database and worker [#129726011]", func() { 21 By("running a task with container having a rootfs, input, and output volume") 22 Fly.Run("execute", "-c", "tasks/input-output.yml", "-i", "some-input=./tasks") 23 24 By("collecting the build containers") 25 rows, err := Psql.Select("id, handle").From("containers").Where(sq.Eq{"build_id": 1, "meta_step_name": "one-off"}).RunWith(DbConn).Query() 26 Expect(err).ToNot(HaveOccurred()) 27 28 buildContainers := map[int]string{} 29 containerIDs := []int{} 30 for rows.Next() { 31 var id int 32 var handle string 33 err := rows.Scan(&id, &handle) 34 Expect(err).ToNot(HaveOccurred()) 35 36 buildContainers[id] = handle 37 containerIDs = append(containerIDs, id) 38 } 39 40 Expect(containerIDs).To(HaveLen(1), "should only be testing one-off task container") 41 42 By("collecting the container volumes") 43 rows, err = Psql.Select("id, handle").From("volumes").Where(sq.Eq{"container_id": containerIDs}).RunWith(DbConn).Query() 44 Expect(err).ToNot(HaveOccurred()) 45 46 containerVolumes := map[int]string{} 47 volumeIDs := []int{} 48 for rows.Next() { 49 var id int 50 var handle string 51 err := rows.Scan(&id, &handle) 52 Expect(err).ToNot(HaveOccurred()) 53 54 containerVolumes[id] = handle 55 volumeIDs = append(volumeIDs, id) 56 } 57 58 By(fmt.Sprintf("eventually expiring the build containers: %v", containerIDs)) 59 Eventually(func() int { 60 var volNum int 61 err := Psql.Select("COUNT(id)").From("volumes").Where(sq.Eq{"id": volumeIDs}).RunWith(DbConn).QueryRow().Scan(&volNum) 62 Expect(err).ToNot(HaveOccurred()) 63 64 var containerNum int 65 err = Psql.Select("COUNT(id)").From("containers").Where(sq.Eq{"id": containerIDs}).RunWith(DbConn).QueryRow().Scan(&containerNum) 66 Expect(err).ToNot(HaveOccurred()) 67 68 if containerNum == len(containerIDs) { 69 By(fmt.Sprintf("not expiring volumes so long as their containers are there (%d remaining)", containerNum)) 70 Expect(volNum).To(Equal(len(volumeIDs))) 71 } 72 73 return containerNum 74 }, 10*time.Minute, time.Second).Should(BeZero()) 75 76 By("having removed the containers from the worker") 77 containers, err := WorkerGardenClient.Containers(nil) 78 Expect(err).ToNot(HaveOccurred()) 79 80 existingHandles := []string{} 81 for _, c := range containers { 82 existingHandles = append(existingHandles, c.Handle()) 83 } 84 85 for _, handle := range buildContainers { 86 Expect(existingHandles).ToNot(ContainElement(handle)) 87 } 88 89 By(fmt.Sprintf("eventually expiring the container volumes: %v", volumeIDs)) 90 Eventually(func() int { 91 var num int 92 err := Psql.Select("COUNT(id)").From("volumes").Where(sq.Eq{"id": volumeIDs}).RunWith(DbConn).QueryRow().Scan(&num) 93 Expect(err).ToNot(HaveOccurred()) 94 return num 95 }, 10*time.Minute, time.Second).Should(BeZero()) 96 97 By("having removed the volumes from the worker") 98 volumes, err := WorkerBaggageclaimClient.ListVolumes(Logger, nil) 99 Expect(err).ToNot(HaveOccurred()) 100 101 existingHandles = []string{} 102 for _, v := range volumes { 103 existingHandles = append(existingHandles, v.Handle()) 104 } 105 106 for _, handle := range containerVolumes { 107 Expect(existingHandles).ToNot(ContainElement(handle)) 108 } 109 }) 110 }) 111 112 Describe("A volume that belonged to a resource cache that is no longer in use", func() { 113 It("is removed from the database and worker [#129726933]", func() { 114 By("setting pipeline that creates resource cache") 115 Fly.Run("set-pipeline", "-n", "-c", "pipelines/get-task-changing-resource.yml", "-p", "volume-gc-test") 116 117 By("unpausing the pipeline") 118 Fly.Run("unpause-pipeline", "-p", "volume-gc-test") 119 120 By("triggering job") 121 Fly.Run("trigger-job", "-w", "-j", "volume-gc-test/simple-job") 122 123 By("getting resource cache") 124 var resourceCacheID int 125 err := Psql.Select("rch.id"). 126 From("resource_caches rch"). 127 LeftJoin("resource_configs rcf ON rch.resource_config_id = rcf.id"). 128 LeftJoin("base_resource_types brt ON rcf.base_resource_type_id = brt.id"). 129 Where("brt.name = 'time'"). 130 RunWith(DbConn). 131 QueryRow().Scan(&resourceCacheID) 132 Expect(err).ToNot(HaveOccurred()) 133 134 By("getting volume for resource cache") 135 var volumeID int 136 var volumeHandle string 137 err = Psql.Select("v.id, v.handle"). 138 From("volumes v"). 139 LeftJoin("worker_resource_caches wrc ON wrc.id = v.worker_resource_cache_id"). 140 Where(sq.Eq{"wrc.resource_cache_id": resourceCacheID}). 141 RunWith(DbConn). 142 QueryRow(). 143 Scan(&volumeID, &volumeHandle) 144 Expect(err).ToNot(HaveOccurred()) 145 146 By("creating a new version of resource") 147 Fly.Run("check-resource", "-r", "volume-gc-test/tick-tock") 148 149 By(fmt.Sprintf("eventually expiring the resource cache: %d", resourceCacheID)) 150 Eventually(func() int { 151 var resourceCacheNum int 152 err := Psql.Select("COUNT(id)").From("resource_caches").Where(sq.Eq{"id": resourceCacheID}).RunWith(DbConn).QueryRow().Scan(&resourceCacheNum) 153 Expect(err).ToNot(HaveOccurred()) 154 155 var volumeNum int 156 err = Psql.Select("COUNT(id)").From("volumes").Where(sq.Eq{"id": volumeID}).RunWith(DbConn).QueryRow().Scan(&volumeNum) 157 Expect(err).ToNot(HaveOccurred()) 158 159 if resourceCacheNum == 1 { 160 By(fmt.Sprintf("not expiring volume so long as its resource cache is there")) 161 Expect(volumeNum).To(Equal(1)) 162 } 163 164 return resourceCacheNum 165 }, 10*time.Minute, time.Second).Should(BeZero()) 166 167 By(fmt.Sprintf("eventually expiring the resource cache volumes: %d", resourceCacheID)) 168 Eventually(func() int { 169 var volumeNum int 170 err := Psql.Select("COUNT(id)").From("volumes").Where(sq.Eq{"id": volumeID}).RunWith(DbConn).QueryRow().Scan(&volumeNum) 171 Expect(err).ToNot(HaveOccurred()) 172 return volumeNum 173 }, 10*time.Minute, time.Second).Should(BeZero()) 174 175 By("having removed the volumes from the worker") 176 volumes, err := WorkerBaggageclaimClient.ListVolumes(Logger, nil) 177 Expect(err).ToNot(HaveOccurred()) 178 179 existingHandles := []string{} 180 for _, v := range volumes { 181 existingHandles = append(existingHandles, v.Handle()) 182 } 183 184 Expect(existingHandles).ToNot(ContainElement(volumeHandle)) 185 }) 186 }) 187 })