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