github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/build_factory_test.go (about)

     1  package db_test
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/pf-qiu/concourse/v6/atc"
     7  	"github.com/pf-qiu/concourse/v6/atc/db"
     8  	. "github.com/onsi/ginkgo"
     9  	. "github.com/onsi/ginkgo/extensions/table"
    10  	. "github.com/onsi/gomega"
    11  	"github.com/onsi/gomega/types"
    12  )
    13  
    14  var _ = Describe("BuildFactory", func() {
    15  	var team db.Team
    16  
    17  	BeforeEach(func() {
    18  		var err error
    19  		team, err = teamFactory.CreateTeam(atc.Team{Name: "some-team"})
    20  		Expect(err).ToNot(HaveOccurred())
    21  	})
    22  
    23  	Describe("Build", func() {
    24  		var (
    25  			foundBuild   db.Build
    26  			createdBuild db.Build
    27  			found        bool
    28  		)
    29  
    30  		BeforeEach(func() {
    31  			var err error
    32  			createdBuild, err = team.CreateOneOffBuild()
    33  			Expect(err).ToNot(HaveOccurred())
    34  
    35  			foundBuild, found, err = buildFactory.Build(createdBuild.ID())
    36  			Expect(err).ToNot(HaveOccurred())
    37  		})
    38  
    39  		It("returns the correct build", func() {
    40  			Expect(found).To(BeTrue())
    41  			Expect(foundBuild).To(Equal(createdBuild))
    42  		})
    43  	})
    44  
    45  	Describe("MarkNonInterceptibleBuilds", func() {
    46  		Context("one-off builds", func() {
    47  			DescribeTable("completed and within grace period",
    48  				func(status db.BuildStatus, matcher types.GomegaMatcher) {
    49  					b, err := defaultTeam.CreateOneOffBuild()
    50  					Expect(err).NotTo(HaveOccurred())
    51  
    52  					var i bool
    53  					err = b.Finish(status)
    54  					Expect(err).NotTo(HaveOccurred())
    55  
    56  					err = buildFactory.MarkNonInterceptibleBuilds()
    57  					Expect(err).NotTo(HaveOccurred())
    58  
    59  					i, err = b.Interceptible()
    60  					Expect(err).NotTo(HaveOccurred())
    61  					Expect(i).To(matcher)
    62  				},
    63  				Entry("succeeded is interceptible", db.BuildStatusSucceeded, BeTrue()),
    64  				Entry("aborted is interceptible", db.BuildStatusAborted, BeTrue()),
    65  				Entry("errored is interceptible", db.BuildStatusErrored, BeTrue()),
    66  				Entry("failed is interceptible", db.BuildStatusFailed, BeTrue()),
    67  			)
    68  			DescribeTable("completed and past the grace period",
    69  				func(status db.BuildStatus, matcher types.GomegaMatcher) {
    70  					//set grace period to 0 for this test
    71  					buildFactory = db.NewBuildFactory(dbConn, lockFactory, 0, 0)
    72  					b, err := defaultTeam.CreateOneOffBuild()
    73  					Expect(err).NotTo(HaveOccurred())
    74  
    75  					var i bool
    76  					err = b.Finish(status)
    77  					Expect(err).NotTo(HaveOccurred())
    78  
    79  					err = buildFactory.MarkNonInterceptibleBuilds()
    80  					Expect(err).NotTo(HaveOccurred())
    81  
    82  					i, err = b.Interceptible()
    83  					Expect(err).NotTo(HaveOccurred())
    84  					Expect(i).To(matcher)
    85  				},
    86  				Entry("succeeded is non-interceptible", db.BuildStatusSucceeded, BeFalse()),
    87  				Entry("aborted is non-interceptible", db.BuildStatusAborted, BeFalse()),
    88  				Entry("errored is non-interceptible", db.BuildStatusErrored, BeFalse()),
    89  				Entry("failed is non-interceptible", db.BuildStatusFailed, BeFalse()),
    90  			)
    91  
    92  			It("non-completed is interceptible", func() {
    93  				b, err := defaultTeam.CreateOneOffBuild()
    94  				Expect(err).NotTo(HaveOccurred())
    95  
    96  				var i bool
    97  				err = buildFactory.MarkNonInterceptibleBuilds()
    98  				Expect(err).NotTo(HaveOccurred())
    99  				i, err = b.Interceptible()
   100  				Expect(err).NotTo(HaveOccurred())
   101  				Expect(i).To(BeTrue())
   102  			})
   103  		})
   104  
   105  		Context("pipeline builds", func() {
   106  
   107  			It("[#139963615] marks builds that aren't the latest as non-interceptible, ", func() {
   108  				build1, err := defaultJob.CreateBuild()
   109  				Expect(err).NotTo(HaveOccurred())
   110  
   111  				build2, err := defaultJob.CreateBuild()
   112  				Expect(err).NotTo(HaveOccurred())
   113  
   114  				err = build1.Finish(db.BuildStatusErrored)
   115  				Expect(err).NotTo(HaveOccurred())
   116  				err = build2.Finish(db.BuildStatusErrored)
   117  				Expect(err).NotTo(HaveOccurred())
   118  
   119  				p, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{
   120  					Jobs: atc.JobConfigs{
   121  						{
   122  							Name: "some-other-job",
   123  						},
   124  					},
   125  				}, db.ConfigVersion(0), false)
   126  				Expect(err).NotTo(HaveOccurred())
   127  
   128  				j, found, err := p.Job("some-other-job")
   129  				Expect(err).NotTo(HaveOccurred())
   130  				Expect(found).To(BeTrue())
   131  
   132  				pb1, err := j.CreateBuild()
   133  				Expect(err).NotTo(HaveOccurred())
   134  
   135  				pb2, err := j.CreateBuild()
   136  				Expect(err).NotTo(HaveOccurred())
   137  
   138  				err = pb1.Finish(db.BuildStatusErrored)
   139  				Expect(err).NotTo(HaveOccurred())
   140  				err = pb2.Finish(db.BuildStatusErrored)
   141  				Expect(err).NotTo(HaveOccurred())
   142  
   143  				err = buildFactory.MarkNonInterceptibleBuilds()
   144  				Expect(err).NotTo(HaveOccurred())
   145  
   146  				var i bool
   147  				i, err = build1.Interceptible()
   148  				Expect(err).NotTo(HaveOccurred())
   149  				Expect(i).To(BeFalse())
   150  
   151  				i, err = build2.Interceptible()
   152  				Expect(err).NotTo(HaveOccurred())
   153  				Expect(i).To(BeTrue())
   154  
   155  				i, err = pb1.Interceptible()
   156  				Expect(err).NotTo(HaveOccurred())
   157  				Expect(i).To(BeFalse())
   158  
   159  				i, err = pb2.Interceptible()
   160  				Expect(err).NotTo(HaveOccurred())
   161  				Expect(i).To(BeTrue())
   162  
   163  			})
   164  
   165  			DescribeTable("completed builds",
   166  				func(status db.BuildStatus, matcher types.GomegaMatcher) {
   167  					b, err := defaultJob.CreateBuild()
   168  					Expect(err).NotTo(HaveOccurred())
   169  
   170  					var i bool
   171  
   172  					err = b.Finish(status)
   173  					Expect(err).NotTo(HaveOccurred())
   174  
   175  					err = buildFactory.MarkNonInterceptibleBuilds()
   176  					Expect(err).NotTo(HaveOccurred())
   177  					i, err = b.Interceptible()
   178  					Expect(err).NotTo(HaveOccurred())
   179  					Expect(i).To(matcher)
   180  				},
   181  				Entry("succeeded is non-interceptible", db.BuildStatusSucceeded, BeFalse()),
   182  				Entry("aborted is interceptible", db.BuildStatusAborted, BeTrue()),
   183  				Entry("errored is interceptible", db.BuildStatusErrored, BeTrue()),
   184  				Entry("failed is interceptible", db.BuildStatusFailed, BeTrue()),
   185  			)
   186  
   187  			It("does not mark non-completed builds", func() {
   188  				b, err := defaultJob.CreateBuild()
   189  				Expect(err).NotTo(HaveOccurred())
   190  
   191  				var i bool
   192  				i, err = b.Interceptible()
   193  				Expect(err).NotTo(HaveOccurred())
   194  				Expect(i).To(BeTrue())
   195  
   196  				err = buildFactory.MarkNonInterceptibleBuilds()
   197  				Expect(err).NotTo(HaveOccurred())
   198  				i, err = b.Interceptible()
   199  				Expect(err).NotTo(HaveOccurred())
   200  				Expect(i).To(BeTrue())
   201  
   202  				_, err = b.Start(atc.Plan{})
   203  				Expect(err).NotTo(HaveOccurred())
   204  
   205  				err = buildFactory.MarkNonInterceptibleBuilds()
   206  				Expect(err).NotTo(HaveOccurred())
   207  				i, err = b.Interceptible()
   208  				Expect(err).NotTo(HaveOccurred())
   209  				Expect(i).To(BeTrue())
   210  			})
   211  		})
   212  		Context("GC failed builds", func() {
   213  			It("marks failed builds non-interceptible after failed-grace-period", func() {
   214  				buildFactory = db.NewBuildFactory(dbConn, lockFactory, 0, 2*time.Second) // 1 second could create a flaky test
   215  				build, err := defaultJob.CreateBuild()
   216  				Expect(err).NotTo(HaveOccurred())
   217  
   218  				err = build.Finish(db.BuildStatusFailed)
   219  				Expect(err).NotTo(HaveOccurred())
   220  
   221  				err = buildFactory.MarkNonInterceptibleBuilds()
   222  				Expect(err).NotTo(HaveOccurred())
   223  
   224  				var i bool
   225  				i, err = build.Interceptible()
   226  				Expect(err).NotTo(HaveOccurred())
   227  				Expect(i).To(BeTrue())
   228  
   229  				time.Sleep(3 * time.Second) // Wait is too long, only second granularity, better method?
   230  
   231  				err = buildFactory.MarkNonInterceptibleBuilds()
   232  				Expect(err).NotTo(HaveOccurred())
   233  
   234  				i, err = build.Interceptible()
   235  				Expect(err).NotTo(HaveOccurred())
   236  				Expect(i).To(BeFalse())
   237  			})
   238  		})
   239  	})
   240  
   241  	Describe("VisibleBuilds", func() {
   242  		var err error
   243  		var build1 db.Build
   244  		var build2 db.Build
   245  		var build3 db.Build
   246  		var build4 db.Build
   247  		var build5 db.Build
   248  
   249  		BeforeEach(func() {
   250  			build1, err = team.CreateOneOffBuild()
   251  			Expect(err).NotTo(HaveOccurred())
   252  
   253  			config := atc.Config{Jobs: atc.JobConfigs{{Name: "some-job"}}}
   254  			privatePipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, config, db.ConfigVersion(1), false)
   255  			Expect(err).NotTo(HaveOccurred())
   256  
   257  			privateJob, found, err := privatePipeline.Job("some-job")
   258  			Expect(err).NotTo(HaveOccurred())
   259  			Expect(found).To(BeTrue())
   260  
   261  			build2, err = privateJob.CreateBuild()
   262  			Expect(err).NotTo(HaveOccurred())
   263  
   264  			publicPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "public-pipeline"}, config, db.ConfigVersion(1), false)
   265  			Expect(err).NotTo(HaveOccurred())
   266  			err = publicPipeline.Expose()
   267  			Expect(err).NotTo(HaveOccurred())
   268  
   269  			publicJob, found, err := publicPipeline.Job("some-job")
   270  			Expect(err).NotTo(HaveOccurred())
   271  			Expect(found).To(BeTrue())
   272  
   273  			build3, err = publicJob.CreateBuild()
   274  			Expect(err).NotTo(HaveOccurred())
   275  
   276  			otherTeam, err := teamFactory.CreateTeam(atc.Team{Name: "some-other-team"})
   277  			Expect(err).NotTo(HaveOccurred())
   278  
   279  			build4, err = otherTeam.CreateOneOffBuild()
   280  			Expect(err).NotTo(HaveOccurred())
   281  
   282  			build5, err = privateJob.RerunBuild(build2)
   283  			Expect(err).NotTo(HaveOccurred())
   284  		})
   285  
   286  		It("returns visible builds for the given teams", func() {
   287  			builds, _, err := buildFactory.VisibleBuilds([]string{"some-team"}, db.Page{Limit: 10})
   288  			Expect(err).NotTo(HaveOccurred())
   289  
   290  			Expect(builds).To(HaveLen(4))
   291  
   292  			buildIDs := []int{}
   293  			for _, build := range builds {
   294  				buildIDs = append(buildIDs, build.ID())
   295  			}
   296  			Expect(buildIDs).To(Equal([]int{build3.ID(), build5.ID(), build2.ID(), build1.ID()}))
   297  			Expect(builds).NotTo(ContainElement(build4))
   298  		})
   299  	})
   300  
   301  	Describe("AllBuilds", func() {
   302  		var err error
   303  		var build1 db.Build
   304  		var build2 db.Build
   305  		var build3 db.Build
   306  		var build4 db.Build
   307  
   308  		BeforeEach(func() {
   309  			build1, err = team.CreateOneOffBuild()
   310  			Expect(err).NotTo(HaveOccurred())
   311  
   312  			config := atc.Config{Jobs: atc.JobConfigs{{Name: "some-job"}}}
   313  			privatePipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, config, db.ConfigVersion(1), false)
   314  			Expect(err).NotTo(HaveOccurred())
   315  
   316  			privateJob, found, err := privatePipeline.Job("some-job")
   317  			Expect(err).NotTo(HaveOccurred())
   318  			Expect(found).To(BeTrue())
   319  
   320  			build2, err = privateJob.CreateBuild()
   321  			Expect(err).NotTo(HaveOccurred())
   322  
   323  			publicPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "public-pipeline"}, config, db.ConfigVersion(1), false)
   324  			Expect(err).NotTo(HaveOccurred())
   325  			err = publicPipeline.Expose()
   326  			Expect(err).NotTo(HaveOccurred())
   327  
   328  			publicJob, found, err := publicPipeline.Job("some-job")
   329  			Expect(err).NotTo(HaveOccurred())
   330  			Expect(found).To(BeTrue())
   331  
   332  			build3, err = publicJob.CreateBuild()
   333  			Expect(err).NotTo(HaveOccurred())
   334  
   335  			otherTeam, err := teamFactory.CreateTeam(atc.Team{Name: "some-other-team"})
   336  			Expect(err).NotTo(HaveOccurred())
   337  
   338  			build4, err = otherTeam.CreateOneOffBuild()
   339  			Expect(err).NotTo(HaveOccurred())
   340  		})
   341  
   342  		It("returns all builds from all teams private and public pipelines", func() {
   343  			builds, _, err := buildFactory.AllBuilds(db.Page{Limit: 10})
   344  			Expect(err).NotTo(HaveOccurred())
   345  
   346  			Expect(builds).To(HaveLen(4))
   347  			Expect(builds).To(ConsistOf(build1, build2, build3, build4))
   348  		})
   349  	})
   350  
   351  	Describe("PublicBuilds", func() {
   352  		var publicBuild db.Build
   353  
   354  		BeforeEach(func() {
   355  			_, err := team.CreateOneOffBuild()
   356  			Expect(err).NotTo(HaveOccurred())
   357  
   358  			config := atc.Config{Jobs: atc.JobConfigs{{Name: "some-job"}}}
   359  			privatePipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, config, db.ConfigVersion(1), false)
   360  			Expect(err).NotTo(HaveOccurred())
   361  
   362  			privateJob, found, err := privatePipeline.Job("some-job")
   363  			Expect(err).NotTo(HaveOccurred())
   364  			Expect(found).To(BeTrue())
   365  
   366  			_, err = privateJob.CreateBuild()
   367  			Expect(err).NotTo(HaveOccurred())
   368  
   369  			publicPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "public-pipeline"}, config, db.ConfigVersion(1), false)
   370  			Expect(err).NotTo(HaveOccurred())
   371  			err = publicPipeline.Expose()
   372  			Expect(err).NotTo(HaveOccurred())
   373  
   374  			publicJob, found, err := publicPipeline.Job("some-job")
   375  			Expect(err).NotTo(HaveOccurred())
   376  			Expect(found).To(BeTrue())
   377  
   378  			publicBuild, err = publicJob.CreateBuild()
   379  			Expect(err).NotTo(HaveOccurred())
   380  		})
   381  
   382  		It("returns public builds", func() {
   383  			builds, _, err := buildFactory.PublicBuilds(db.Page{Limit: 10})
   384  			Expect(err).NotTo(HaveOccurred())
   385  
   386  			Expect(builds).To(HaveLen(1))
   387  			Expect(builds).To(ConsistOf(publicBuild))
   388  		})
   389  	})
   390  
   391  	Describe("GetDrainableBuilds", func() {
   392  		var build2DB, build3DB, build4DB db.Build
   393  
   394  		BeforeEach(func() {
   395  			pipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{
   396  				Jobs: atc.JobConfigs{
   397  					{
   398  						Name: "some-job",
   399  					},
   400  				},
   401  			}, db.ConfigVersion(0), false)
   402  			Expect(err).NotTo(HaveOccurred())
   403  
   404  			job, found, err := pipeline.Job("some-job")
   405  			Expect(err).NotTo(HaveOccurred())
   406  			Expect(found).To(BeTrue())
   407  
   408  			_, err = team.CreateOneOffBuild()
   409  			Expect(err).NotTo(HaveOccurred())
   410  
   411  			build2DB, err = team.CreateOneOffBuild()
   412  			Expect(err).NotTo(HaveOccurred())
   413  
   414  			build3DB, err = job.CreateBuild()
   415  			Expect(err).NotTo(HaveOccurred())
   416  
   417  			build4DB, err = job.CreateBuild()
   418  			Expect(err).NotTo(HaveOccurred())
   419  
   420  			started, err := build2DB.Start(atc.Plan{})
   421  			Expect(err).NotTo(HaveOccurred())
   422  			Expect(started).To(BeTrue())
   423  
   424  			err = build3DB.Finish("succeeded")
   425  			Expect(err).NotTo(HaveOccurred())
   426  
   427  			err = build3DB.SetDrained(true)
   428  			Expect(err).NotTo(HaveOccurred())
   429  
   430  			err = build4DB.Finish("failed")
   431  			Expect(err).NotTo(HaveOccurred())
   432  		})
   433  
   434  		It("returns all builds that have been completed and not drained", func() {
   435  			builds, err := buildFactory.GetDrainableBuilds()
   436  			Expect(err).NotTo(HaveOccurred())
   437  
   438  			_, err = build4DB.Reload()
   439  			Expect(err).NotTo(HaveOccurred())
   440  
   441  			Expect(builds).To(ConsistOf(build4DB))
   442  		})
   443  	})
   444  
   445  	Describe("GetAllStartedBuilds", func() {
   446  		var build1DB db.Build
   447  		var build2DB db.Build
   448  
   449  		BeforeEach(func() {
   450  			pipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{
   451  				Jobs: atc.JobConfigs{
   452  					{
   453  						Name: "some-job",
   454  					},
   455  				},
   456  			}, db.ConfigVersion(0), false)
   457  			Expect(err).NotTo(HaveOccurred())
   458  
   459  			job, found, err := pipeline.Job("some-job")
   460  			Expect(err).NotTo(HaveOccurred())
   461  			Expect(found).To(BeTrue())
   462  
   463  			build1DB, err = team.CreateOneOffBuild()
   464  			Expect(err).NotTo(HaveOccurred())
   465  
   466  			build2DB, err = job.CreateBuild()
   467  			Expect(err).NotTo(HaveOccurred())
   468  
   469  			_, err = team.CreateOneOffBuild()
   470  			Expect(err).NotTo(HaveOccurred())
   471  
   472  			started, err := build1DB.Start(atc.Plan{})
   473  			Expect(err).NotTo(HaveOccurred())
   474  			Expect(started).To(BeTrue())
   475  
   476  			started, err = build2DB.Start(atc.Plan{})
   477  			Expect(err).NotTo(HaveOccurred())
   478  			Expect(started).To(BeTrue())
   479  		})
   480  
   481  		It("returns all builds that have been started, regardless of pipeline", func() {
   482  			builds, err := buildFactory.GetAllStartedBuilds()
   483  			Expect(err).NotTo(HaveOccurred())
   484  
   485  			_, err = build1DB.Reload()
   486  			Expect(err).NotTo(HaveOccurred())
   487  			_, err = build2DB.Reload()
   488  			Expect(err).NotTo(HaveOccurred())
   489  
   490  			Expect(builds).To(ConsistOf(build1DB, build2DB))
   491  		})
   492  	})
   493  
   494  	Describe("AllBuilds by date", func() {
   495  		var build1DB db.Build
   496  		var build2DB db.Build
   497  
   498  		BeforeEach(func() {
   499  			pipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{
   500  				Jobs: atc.JobConfigs{
   501  					{
   502  						Name: "some-job",
   503  					},
   504  				},
   505  			}, db.ConfigVersion(0), false)
   506  			Expect(err).NotTo(HaveOccurred())
   507  
   508  			job, found, err := pipeline.Job("some-job")
   509  			Expect(err).NotTo(HaveOccurred())
   510  			Expect(found).To(BeTrue())
   511  
   512  			build1DB, err = team.CreateOneOffBuild()
   513  			Expect(err).NotTo(HaveOccurred())
   514  
   515  			build2DB, err = job.CreateBuild()
   516  			Expect(err).NotTo(HaveOccurred())
   517  
   518  			_, err = team.CreateOneOffBuild()
   519  			Expect(err).NotTo(HaveOccurred())
   520  
   521  			started, err := build1DB.Start(atc.Plan{})
   522  			Expect(err).NotTo(HaveOccurred())
   523  			Expect(started).To(BeTrue())
   524  
   525  			started, err = build2DB.Start(atc.Plan{})
   526  			Expect(err).NotTo(HaveOccurred())
   527  			Expect(started).To(BeTrue())
   528  		})
   529  
   530  		It("returns builds started in the given timespan", func() {
   531  			page := db.Page{
   532  				Limit:   10,
   533  				From:    db.NewIntPtr(int(time.Now().Unix() - 10000)),
   534  				To:      db.NewIntPtr(int(time.Now().Unix() + 10)),
   535  				UseDate: true,
   536  			}
   537  			builds, _, err := buildFactory.AllBuilds(page)
   538  			Expect(err).NotTo(HaveOccurred())
   539  			Expect(len(builds)).To(Equal(2))
   540  		})
   541  
   542  		Describe("with a future date as Page.From", func() {
   543  			It("should return nothing", func() {
   544  				page := db.Page{
   545  					Limit:   10,
   546  					From:    db.NewIntPtr(int(time.Now().Unix() + 10)),
   547  					UseDate: true,
   548  				}
   549  				builds, _, err := buildFactory.AllBuilds(page)
   550  				Expect(err).NotTo(HaveOccurred())
   551  				Expect(len(builds)).To(Equal(0))
   552  			})
   553  		})
   554  
   555  		Describe("with a very old date as Page.To", func() {
   556  			It("should return nothing", func() {
   557  				page := db.Page{
   558  					Limit:   10,
   559  					To:      db.NewIntPtr(int(time.Now().Unix() - 10000)),
   560  					UseDate: true,
   561  				}
   562  				builds, _, err := buildFactory.AllBuilds(page)
   563  				Expect(err).NotTo(HaveOccurred())
   564  				Expect(len(builds)).To(Equal(0))
   565  			})
   566  		})
   567  	})
   568  })