291 lines
8.5 KiB
Go
291 lines
8.5 KiB
Go
package gc_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
sq "github.com/Masterminds/squirrel"
|
|
"github.com/concourse/concourse/atc"
|
|
"github.com/concourse/concourse/atc/db"
|
|
"github.com/concourse/concourse/atc/db/algorithm"
|
|
"github.com/concourse/concourse/atc/gc"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("ResourceCacheCollector", func() {
|
|
var collector gc.Collector
|
|
var buildCollector gc.Collector
|
|
|
|
BeforeEach(func() {
|
|
collector = gc.NewResourceCacheCollector(resourceCacheLifecycle)
|
|
buildCollector = gc.NewBuildCollector(buildFactory)
|
|
})
|
|
|
|
Describe("Run", func() {
|
|
Describe("resource caches", func() {
|
|
var resourceCacheUseCollector gc.Collector
|
|
|
|
var oneOffBuild db.Build
|
|
var jobBuild db.Build
|
|
|
|
var oneOffCache db.UsedResourceCache
|
|
var jobCache db.UsedResourceCache
|
|
|
|
var resource db.Resource
|
|
|
|
BeforeEach(func() {
|
|
resourceCacheUseCollector = gc.NewResourceCacheUseCollector(resourceCacheLifecycle)
|
|
|
|
oneOffBuild, err = defaultTeam.CreateOneOffBuild()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
oneOffCache, err = resourceCacheFactory.FindOrCreateResourceCache(
|
|
db.ForBuild(oneOffBuild.ID()),
|
|
"some-base-type",
|
|
atc.Version{"some": "version"},
|
|
atc.Source{
|
|
"some": "source",
|
|
},
|
|
nil,
|
|
atc.VersionedResourceTypes{},
|
|
)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
jobBuild, err = defaultJob.CreateBuild()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
jobCache, err = resourceCacheFactory.FindOrCreateResourceCache(
|
|
db.ForBuild(jobBuild.ID()),
|
|
"some-base-type",
|
|
atc.Version{"some": "version"},
|
|
atc.Source{
|
|
"some": "source",
|
|
},
|
|
nil,
|
|
atc.VersionedResourceTypes{},
|
|
)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var found bool
|
|
resource, found, err = defaultPipeline.Resource("some-resource")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
_, err = resource.SetResourceConfig(
|
|
atc.Source{
|
|
"some": "source",
|
|
},
|
|
atc.VersionedResourceTypes{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
resourceCacheExists := func(resourceCache db.UsedResourceCache) bool {
|
|
var count int
|
|
err = psql.Select("COUNT(*)").
|
|
From("resource_caches").
|
|
Where(sq.Eq{"id": resourceCache.ID()}).
|
|
RunWith(dbConn).
|
|
QueryRow().
|
|
Scan(&count)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
return count == 1
|
|
}
|
|
|
|
JustBeforeEach(func() {
|
|
Expect(buildCollector.Run(context.TODO())).To(Succeed())
|
|
Expect(resourceCacheUseCollector.Run(context.TODO())).To(Succeed())
|
|
Expect(collector.Run(context.TODO())).To(Succeed())
|
|
})
|
|
|
|
Context("when the resource cache is still in use", func() {
|
|
It("does not delete the cache", func() {
|
|
Expect(collector.Run(context.TODO())).To(Succeed())
|
|
Expect(resourceCacheExists(oneOffCache)).To(BeTrue())
|
|
Expect(resourceCacheExists(jobCache)).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("when the cache is no longer in use", func() {
|
|
BeforeEach(func() {
|
|
Expect(oneOffBuild.Finish(db.BuildStatusSucceeded)).To(Succeed())
|
|
Expect(jobBuild.Finish(db.BuildStatusSucceeded)).To(Succeed())
|
|
})
|
|
|
|
Context("when the cache is an input to a job", func() {
|
|
BeforeEach(func() {
|
|
var versionID int
|
|
version := `{"some":"version"}`
|
|
err = psql.Insert("resource_config_versions").
|
|
Columns("version", "version_md5", "metadata", "resource_config_scope_id").
|
|
Values(version, sq.Expr(fmt.Sprintf("md5('%s')", version)), `null`, jobCache.ResourceConfig().ID()).
|
|
Suffix("RETURNING id").
|
|
RunWith(dbConn).QueryRow().Scan(&versionID)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(defaultJob.SaveNextInputMapping(algorithm.InputMapping{
|
|
"whatever": algorithm.InputVersion{
|
|
VersionID: versionID,
|
|
ResourceID: resource.ID(),
|
|
},
|
|
})).To(Succeed())
|
|
})
|
|
|
|
Context("when pipeline is paused", func() {
|
|
BeforeEach(func() {
|
|
err := defaultPipeline.Pause()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("removes the cache", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeFalse())
|
|
})
|
|
})
|
|
|
|
Context("when pipeline is not paused", func() {
|
|
It("leaves it alone", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeTrue())
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when the cache is an image resource version for a job build", func() {
|
|
BeforeEach(func() {
|
|
err := jobBuild.SaveImageResourceVersion(jobCache)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("leaves it alone", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeTrue())
|
|
})
|
|
|
|
Context("when another build of the same job exists with a different image cache", func() {
|
|
var secondJobBuild db.Build
|
|
var secondJobCache db.UsedResourceCache
|
|
|
|
BeforeEach(func() {
|
|
secondJobBuild, err = defaultJob.CreateBuild()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
secondJobCache, err = resourceCacheFactory.FindOrCreateResourceCache(
|
|
db.ForBuild(secondJobBuild.ID()),
|
|
"some-base-type",
|
|
atc.Version{"some": "new-version"},
|
|
atc.Source{
|
|
"some": "source",
|
|
},
|
|
nil,
|
|
atc.VersionedResourceTypes{},
|
|
)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(secondJobBuild.SaveImageResourceVersion(secondJobCache)).To(Succeed())
|
|
})
|
|
|
|
Context("when the second build succeeds", func() {
|
|
BeforeEach(func() {
|
|
Expect(secondJobBuild.Finish(db.BuildStatusSucceeded)).To(Succeed())
|
|
})
|
|
|
|
It("keeps the new cache and removes the old one", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeFalse())
|
|
Expect(resourceCacheExists(secondJobCache)).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("when the second build fails", func() {
|
|
BeforeEach(func() {
|
|
Expect(secondJobBuild.Finish(db.BuildStatusFailed)).To(Succeed())
|
|
})
|
|
|
|
It("keeps the new cache and the old one", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeTrue())
|
|
Expect(resourceCacheExists(secondJobCache)).To(BeTrue())
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when another build of a different job exists with a different image cache", func() {
|
|
var secondJobBuild db.Build
|
|
var secondJobCache db.UsedResourceCache
|
|
|
|
BeforeEach(func() {
|
|
secondJob, found, err := defaultPipeline.Job("some-other-job")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(found).To(BeTrue())
|
|
|
|
secondJobBuild, err = secondJob.CreateBuild()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
secondJobCache, err = resourceCacheFactory.FindOrCreateResourceCache(
|
|
db.ForBuild(secondJobBuild.ID()),
|
|
"some-base-type",
|
|
atc.Version{"some": "new-version"},
|
|
atc.Source{
|
|
"some": "source",
|
|
},
|
|
nil,
|
|
atc.VersionedResourceTypes{},
|
|
)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(secondJobBuild.SaveImageResourceVersion(secondJobCache)).To(Succeed())
|
|
})
|
|
|
|
Context("when the second build succeeds", func() {
|
|
BeforeEach(func() {
|
|
Expect(secondJobBuild.Finish(db.BuildStatusSucceeded)).To(Succeed())
|
|
})
|
|
|
|
It("keeps the new cache and the old one", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeTrue())
|
|
Expect(resourceCacheExists(secondJobCache)).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("when the second build fails", func() {
|
|
BeforeEach(func() {
|
|
Expect(secondJobBuild.Finish(db.BuildStatusFailed)).To(Succeed())
|
|
})
|
|
|
|
It("keeps the new cache and the old one", func() {
|
|
Expect(resourceCacheExists(jobCache)).To(BeTrue())
|
|
Expect(resourceCacheExists(secondJobCache)).To(BeTrue())
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when the cache is an image resource version for a one-off build", func() {
|
|
BeforeEach(func() {
|
|
err := oneOffBuild.SaveImageResourceVersion(oneOffCache)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when the build finished recently", func() {
|
|
It("leaves it alone", func() {
|
|
Expect(resourceCacheExists(oneOffCache)).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Context("when the build finished a day ago", func() {
|
|
BeforeEach(func() {
|
|
_, err := psql.Update("builds").
|
|
Set("end_time", sq.Expr("NOW() - '25 hours'::interval")).
|
|
Where(sq.Eq{"id": oneOffBuild.ID()}).
|
|
RunWith(dbConn).
|
|
Exec()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("removes the cache", func() {
|
|
Expect(resourceCacheExists(oneOffCache)).To(BeFalse())
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|