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

     1  package db_test
     2  
     3  import (
     4  	"github.com/pf-qiu/concourse/v6/atc"
     5  	"github.com/pf-qiu/concourse/v6/atc/db"
     6  	. "github.com/onsi/ginkgo"
     7  	. "github.com/onsi/gomega"
     8  	. "github.com/onsi/gomega/gstruct"
     9  )
    10  
    11  var _ = Describe("JobFactory", func() {
    12  	var jobFactory db.JobFactory
    13  
    14  	BeforeEach(func() {
    15  		jobFactory = db.NewJobFactory(dbConn, lockFactory)
    16  	})
    17  
    18  	Context("when there are public and private pipelines", func() {
    19  		var publicPipeline db.Pipeline
    20  
    21  		BeforeEach(func() {
    22  			otherTeam, err := teamFactory.CreateTeam(atc.Team{Name: "other-team"})
    23  			Expect(err).NotTo(HaveOccurred())
    24  
    25  			publicPipeline, _, err = otherTeam.SavePipeline(atc.PipelineRef{Name: "public-pipeline", InstanceVars: atc.InstanceVars{"branch": "master"}}, atc.Config{
    26  				Jobs: atc.JobConfigs{
    27  					{
    28  						Name: "public-pipeline-job-1",
    29  						PlanSequence: []atc.Step{
    30  							{
    31  								Config: &atc.GetStep{
    32  									Name: "some-resource",
    33  								},
    34  							},
    35  							{
    36  								Config: &atc.GetStep{
    37  									Name: "some-other-resource",
    38  								},
    39  							},
    40  							{
    41  								Config: &atc.PutStep{
    42  									Name: "some-resource",
    43  								},
    44  							},
    45  						},
    46  					},
    47  					{
    48  						Name: "public-pipeline-job-2",
    49  						PlanSequence: []atc.Step{
    50  							{
    51  								Config: &atc.GetStep{
    52  									Name:   "some-resource",
    53  									Passed: []string{"public-pipeline-job-1"},
    54  								},
    55  							},
    56  							{
    57  								Config: &atc.GetStep{
    58  									Name:   "some-other-resource",
    59  									Passed: []string{"public-pipeline-job-1"},
    60  								},
    61  							},
    62  							{
    63  								Config: &atc.GetStep{
    64  									Name:     "resource",
    65  									Resource: "some-resource",
    66  								},
    67  							},
    68  							{
    69  								Config: &atc.PutStep{
    70  									Name:     "resource",
    71  									Resource: "some-resource",
    72  								},
    73  							},
    74  							{
    75  								Config: &atc.PutStep{
    76  									Name: "some-resource",
    77  								},
    78  							},
    79  						},
    80  					},
    81  					{
    82  						Name: "public-pipeline-job-3",
    83  						PlanSequence: []atc.Step{
    84  							{
    85  								Config: &atc.GetStep{
    86  									Name:   "some-resource",
    87  									Passed: []string{"public-pipeline-job-1", "public-pipeline-job-2"},
    88  								},
    89  							},
    90  						},
    91  					},
    92  				},
    93  				Resources: atc.ResourceConfigs{
    94  					{
    95  						Name: "some-resource",
    96  						Type: "some-type",
    97  					},
    98  					{
    99  						Name: "some-other-resource",
   100  						Type: "some-type",
   101  					},
   102  				},
   103  			}, db.ConfigVersion(0), false)
   104  			Expect(err).ToNot(HaveOccurred())
   105  			Expect(publicPipeline.Expose()).To(Succeed())
   106  
   107  			_, _, err = otherTeam.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, atc.Config{
   108  				Jobs: atc.JobConfigs{
   109  					{
   110  						Name: "private-pipeline-job",
   111  						PlanSequence: []atc.Step{
   112  							{
   113  								Config: &atc.GetStep{
   114  									Name: "some-resource",
   115  								},
   116  							},
   117  							{
   118  								Config: &atc.PutStep{
   119  									Name: "some-resource",
   120  								},
   121  							},
   122  						},
   123  					},
   124  				},
   125  				Resources: atc.ResourceConfigs{
   126  					{
   127  						Name: "some-resource",
   128  						Type: "some-type",
   129  					},
   130  				},
   131  			}, db.ConfigVersion(0), false)
   132  			Expect(err).ToNot(HaveOccurred())
   133  		})
   134  
   135  		Describe("VisibleJobs", func() {
   136  			It("returns jobs in the provided teams and jobs in public pipelines", func() {
   137  				visibleJobs, err := jobFactory.VisibleJobs([]string{"default-team"})
   138  				Expect(err).ToNot(HaveOccurred())
   139  
   140  				Expect(len(visibleJobs)).To(Equal(4))
   141  				Expect(visibleJobs[0].Name).To(Equal("some-job"))
   142  				Expect(visibleJobs[1].Name).To(Equal("public-pipeline-job-1"))
   143  				Expect(visibleJobs[2].Name).To(Equal("public-pipeline-job-2"))
   144  				Expect(visibleJobs[3].Name).To(Equal("public-pipeline-job-3"))
   145  
   146  				Expect(visibleJobs[0].Inputs).To(BeNil())
   147  				Expect(visibleJobs[1].Inputs).To(Equal([]atc.JobInputSummary{
   148  					{
   149  						Name:     "some-other-resource",
   150  						Resource: "some-other-resource",
   151  					},
   152  					{
   153  						Name:     "some-resource",
   154  						Resource: "some-resource",
   155  					},
   156  				}))
   157  				Expect(visibleJobs[2].Inputs).To(Equal([]atc.JobInputSummary{
   158  					{
   159  						Name:     "resource",
   160  						Resource: "some-resource",
   161  					},
   162  					{
   163  						Name:     "some-other-resource",
   164  						Resource: "some-other-resource",
   165  						Passed:   []string{"public-pipeline-job-1"},
   166  					},
   167  					{
   168  						Name:     "some-resource",
   169  						Resource: "some-resource",
   170  						Passed:   []string{"public-pipeline-job-1"},
   171  					},
   172  				}))
   173  				Expect(visibleJobs[3].Inputs).To(Equal([]atc.JobInputSummary{
   174  					{
   175  						Name:     "some-resource",
   176  						Resource: "some-resource",
   177  						Passed:   []string{"public-pipeline-job-1", "public-pipeline-job-2"},
   178  					},
   179  				}))
   180  
   181  				Expect(visibleJobs[0].Outputs).To(BeNil())
   182  				Expect(visibleJobs[1].Outputs).To(Equal([]atc.JobOutputSummary{
   183  					{
   184  						Name:     "some-resource",
   185  						Resource: "some-resource",
   186  					},
   187  				}))
   188  				Expect(visibleJobs[2].Outputs).To(Equal([]atc.JobOutputSummary{
   189  					{
   190  						Name:     "resource",
   191  						Resource: "some-resource",
   192  					},
   193  					{
   194  						Name:     "some-resource",
   195  						Resource: "some-resource",
   196  					},
   197  				}))
   198  				Expect(visibleJobs[3].Outputs).To(BeNil())
   199  			})
   200  
   201  			It("returns next build, latest completed build, and transition build for each job", func() {
   202  				job, found, err := defaultPipeline.Job("some-job")
   203  				Expect(err).ToNot(HaveOccurred())
   204  				Expect(found).To(BeTrue())
   205  
   206  				transitionBuild, err := job.CreateBuild()
   207  				Expect(err).ToNot(HaveOccurred())
   208  
   209  				err = transitionBuild.Finish(db.BuildStatusSucceeded)
   210  				Expect(err).ToNot(HaveOccurred())
   211  
   212  				found, err = transitionBuild.Reload()
   213  				Expect(err).ToNot(HaveOccurred())
   214  				Expect(found).To(BeTrue())
   215  
   216  				finishedBuild, err := job.CreateBuild()
   217  				Expect(err).ToNot(HaveOccurred())
   218  
   219  				err = finishedBuild.Finish(db.BuildStatusSucceeded)
   220  				Expect(err).ToNot(HaveOccurred())
   221  
   222  				found, err = finishedBuild.Reload()
   223  				Expect(err).ToNot(HaveOccurred())
   224  				Expect(found).To(BeTrue())
   225  
   226  				nextBuild, err := job.CreateBuild()
   227  				Expect(err).ToNot(HaveOccurred())
   228  
   229  				visibleJobs, err := jobFactory.VisibleJobs([]string{"default-team"})
   230  				Expect(err).ToNot(HaveOccurred())
   231  
   232  				Expect(visibleJobs[0].Name).To(Equal("some-job"))
   233  				Expect(visibleJobs[0].NextBuild.ID).To(Equal(nextBuild.ID()))
   234  				Expect(visibleJobs[0].NextBuild.Name).To(Equal(nextBuild.Name()))
   235  				Expect(visibleJobs[0].NextBuild.JobName).To(Equal(nextBuild.JobName()))
   236  				Expect(visibleJobs[0].NextBuild.PipelineID).To(Equal(nextBuild.PipelineID()))
   237  				Expect(visibleJobs[0].NextBuild.PipelineName).To(Equal(nextBuild.PipelineName()))
   238  				Expect(visibleJobs[0].NextBuild.PipelineInstanceVars).To(Equal(nextBuild.PipelineInstanceVars()))
   239  				Expect(visibleJobs[0].NextBuild.TeamName).To(Equal(nextBuild.TeamName()))
   240  				Expect(visibleJobs[0].NextBuild.Status).To(Equal(atc.BuildStatus(nextBuild.Status())))
   241  				Expect(visibleJobs[0].NextBuild.StartTime).To(Equal(nextBuild.StartTime().Unix()))
   242  				Expect(visibleJobs[0].NextBuild.EndTime).To(Equal(nextBuild.EndTime().Unix()))
   243  
   244  				Expect(visibleJobs[0].FinishedBuild.ID).To(Equal(finishedBuild.ID()))
   245  				Expect(visibleJobs[0].FinishedBuild.Name).To(Equal(finishedBuild.Name()))
   246  				Expect(visibleJobs[0].FinishedBuild.JobName).To(Equal(finishedBuild.JobName()))
   247  				Expect(visibleJobs[0].FinishedBuild.PipelineID).To(Equal(finishedBuild.PipelineID()))
   248  				Expect(visibleJobs[0].FinishedBuild.PipelineName).To(Equal(finishedBuild.PipelineName()))
   249  				Expect(visibleJobs[0].FinishedBuild.PipelineInstanceVars).To(Equal(finishedBuild.PipelineInstanceVars()))
   250  				Expect(visibleJobs[0].FinishedBuild.TeamName).To(Equal(finishedBuild.TeamName()))
   251  				Expect(visibleJobs[0].FinishedBuild.Status).To(Equal(atc.BuildStatus(finishedBuild.Status())))
   252  				Expect(visibleJobs[0].FinishedBuild.StartTime).To(Equal(finishedBuild.StartTime().Unix()))
   253  				Expect(visibleJobs[0].FinishedBuild.EndTime).To(Equal(finishedBuild.EndTime().Unix()))
   254  
   255  				Expect(visibleJobs[0].TransitionBuild.ID).To(Equal(transitionBuild.ID()))
   256  				Expect(visibleJobs[0].TransitionBuild.Name).To(Equal(transitionBuild.Name()))
   257  				Expect(visibleJobs[0].TransitionBuild.JobName).To(Equal(transitionBuild.JobName()))
   258  				Expect(visibleJobs[0].TransitionBuild.PipelineID).To(Equal(transitionBuild.PipelineID()))
   259  				Expect(visibleJobs[0].TransitionBuild.PipelineName).To(Equal(transitionBuild.PipelineName()))
   260  				Expect(visibleJobs[0].TransitionBuild.PipelineInstanceVars).To(Equal(transitionBuild.PipelineInstanceVars()))
   261  				Expect(visibleJobs[0].TransitionBuild.TeamName).To(Equal(transitionBuild.TeamName()))
   262  				Expect(visibleJobs[0].TransitionBuild.Status).To(Equal(atc.BuildStatus(transitionBuild.Status())))
   263  				Expect(visibleJobs[0].TransitionBuild.StartTime).To(Equal(transitionBuild.StartTime().Unix()))
   264  				Expect(visibleJobs[0].TransitionBuild.EndTime).To(Equal(transitionBuild.EndTime().Unix()))
   265  			})
   266  		})
   267  
   268  		Describe("AllActiveJobs", func() {
   269  			It("return all private and public pipelines", func() {
   270  				allJobs, err := jobFactory.AllActiveJobs()
   271  				Expect(err).ToNot(HaveOccurred())
   272  
   273  				Expect(len(allJobs)).To(Equal(5))
   274  				Expect(allJobs[0].Name).To(Equal("some-job"))
   275  				Expect(allJobs[1].Name).To(Equal("public-pipeline-job-1"))
   276  				Expect(allJobs[2].Name).To(Equal("public-pipeline-job-2"))
   277  				Expect(allJobs[3].Name).To(Equal("public-pipeline-job-3"))
   278  				Expect(allJobs[4].Name).To(Equal("private-pipeline-job"))
   279  
   280  				Expect(allJobs[0].Inputs).To(BeNil())
   281  				Expect(allJobs[1].Inputs).To(Equal([]atc.JobInputSummary{
   282  					{
   283  						Name:     "some-other-resource",
   284  						Resource: "some-other-resource",
   285  					},
   286  					{
   287  						Name:     "some-resource",
   288  						Resource: "some-resource",
   289  					},
   290  				}))
   291  				Expect(allJobs[2].Inputs).To(Equal([]atc.JobInputSummary{
   292  					{
   293  						Name:     "resource",
   294  						Resource: "some-resource",
   295  					},
   296  					{
   297  						Name:     "some-other-resource",
   298  						Resource: "some-other-resource",
   299  						Passed:   []string{"public-pipeline-job-1"},
   300  					},
   301  					{
   302  						Name:     "some-resource",
   303  						Resource: "some-resource",
   304  						Passed:   []string{"public-pipeline-job-1"},
   305  					},
   306  				}))
   307  				Expect(allJobs[3].Inputs).To(Equal([]atc.JobInputSummary{
   308  					{
   309  						Name:     "some-resource",
   310  						Resource: "some-resource",
   311  						Passed:   []string{"public-pipeline-job-1", "public-pipeline-job-2"},
   312  					},
   313  				}))
   314  				Expect(allJobs[4].Inputs).To(Equal([]atc.JobInputSummary{
   315  					{
   316  						Name:     "some-resource",
   317  						Resource: "some-resource",
   318  					},
   319  				}))
   320  
   321  				Expect(allJobs[0].Outputs).To(BeNil())
   322  				Expect(allJobs[1].Outputs).To(Equal([]atc.JobOutputSummary{
   323  					{
   324  						Name:     "some-resource",
   325  						Resource: "some-resource",
   326  					},
   327  				}))
   328  				Expect(allJobs[2].Outputs).To(Equal([]atc.JobOutputSummary{
   329  					{
   330  						Name:     "resource",
   331  						Resource: "some-resource",
   332  					},
   333  					{
   334  						Name:     "some-resource",
   335  						Resource: "some-resource",
   336  					},
   337  				}))
   338  				Expect(allJobs[3].Outputs).To(BeNil())
   339  				Expect(allJobs[4].Outputs).To(Equal([]atc.JobOutputSummary{
   340  					{
   341  						Name:     "some-resource",
   342  						Resource: "some-resource",
   343  					},
   344  				}))
   345  			})
   346  		})
   347  	})
   348  
   349  	Describe("JobsToSchedule", func() {
   350  		var (
   351  			job1 db.Job
   352  			job2 db.Job
   353  			job3 db.Job
   354  		)
   355  
   356  		BeforeEach(func() {
   357  			err := defaultPipeline.Destroy()
   358  			Expect(err).ToNot(HaveOccurred())
   359  		})
   360  
   361  		Context("when the job has a requested schedule time later than the last scheduled", func() {
   362  			BeforeEach(func() {
   363  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   364  					Jobs: atc.JobConfigs{
   365  						{Name: "job-name"},
   366  					},
   367  				}, db.ConfigVersion(1), false)
   368  				Expect(err).ToNot(HaveOccurred())
   369  
   370  				var found bool
   371  				job1, found, err = pipeline1.Job("job-name")
   372  				Expect(err).ToNot(HaveOccurred())
   373  				Expect(found).To(BeTrue())
   374  
   375  				err = job1.RequestSchedule()
   376  				Expect(err).ToNot(HaveOccurred())
   377  			})
   378  
   379  			It("fetches that job", func() {
   380  				jobs, err := jobFactory.JobsToSchedule()
   381  				Expect(err).ToNot(HaveOccurred())
   382  				Expect(len(jobs)).To(Equal(1))
   383  				Expect(jobs[0].Name()).To(Equal(job1.Name()))
   384  			})
   385  		})
   386  
   387  		Context("when the job has a requested schedule time earlier than the last scheduled", func() {
   388  			BeforeEach(func() {
   389  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   390  					Jobs: atc.JobConfigs{
   391  						{Name: "job-name"},
   392  					},
   393  				}, db.ConfigVersion(1), false)
   394  				Expect(err).ToNot(HaveOccurred())
   395  
   396  				var found bool
   397  				job1, found, err = pipeline1.Job("job-name")
   398  				Expect(err).ToNot(HaveOccurred())
   399  				Expect(found).To(BeTrue())
   400  
   401  				_, err = dbConn.Exec("UPDATE jobs SET last_scheduled = now() WHERE id = $1;", job1.ID())
   402  				Expect(err).ToNot(HaveOccurred())
   403  			})
   404  
   405  			It("does not fetch that job", func() {
   406  				jobs, err := jobFactory.JobsToSchedule()
   407  				Expect(err).ToNot(HaveOccurred())
   408  				Expect(len(jobs)).To(Equal(0))
   409  			})
   410  		})
   411  
   412  		Context("when the job has a requested schedule time is the same as the last scheduled", func() {
   413  			BeforeEach(func() {
   414  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   415  					Jobs: atc.JobConfigs{
   416  						{Name: "job-name"},
   417  					},
   418  				}, db.ConfigVersion(1), false)
   419  				Expect(err).ToNot(HaveOccurred())
   420  
   421  				var found bool
   422  				job1, found, err = pipeline1.Job("job-name")
   423  				Expect(err).ToNot(HaveOccurred())
   424  				Expect(found).To(BeTrue())
   425  
   426  				err = job1.RequestSchedule()
   427  				Expect(err).ToNot(HaveOccurred())
   428  
   429  				found, err = job1.Reload()
   430  				Expect(err).ToNot(HaveOccurred())
   431  				Expect(found).To(BeTrue())
   432  
   433  				err = job1.UpdateLastScheduled(job1.ScheduleRequestedTime())
   434  				Expect(err).ToNot(HaveOccurred())
   435  			})
   436  
   437  			It("does not fetch that job", func() {
   438  				jobs, err := jobFactory.JobsToSchedule()
   439  				Expect(err).ToNot(HaveOccurred())
   440  				Expect(len(jobs)).To(Equal(0))
   441  			})
   442  		})
   443  
   444  		Context("when there are multiple jobs with different times", func() {
   445  			BeforeEach(func() {
   446  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   447  					Jobs: atc.JobConfigs{
   448  						{Name: "job-name"},
   449  					},
   450  				}, db.ConfigVersion(1), false)
   451  				Expect(err).ToNot(HaveOccurred())
   452  
   453  				var found bool
   454  				job1, found, err = pipeline1.Job("job-name")
   455  				Expect(err).ToNot(HaveOccurred())
   456  				Expect(found).To(BeTrue())
   457  
   458  				err = job1.RequestSchedule()
   459  				Expect(err).ToNot(HaveOccurred())
   460  
   461  				team, err := teamFactory.CreateTeam(atc.Team{Name: "some-team"})
   462  				Expect(err).ToNot(HaveOccurred())
   463  
   464  				pipeline2, _, err := team.SavePipeline(atc.PipelineRef{Name: "fake-pipeline-two"}, atc.Config{
   465  					Jobs: atc.JobConfigs{
   466  						{Name: "job-fake"},
   467  					},
   468  				}, db.ConfigVersion(1), false)
   469  				Expect(err).ToNot(HaveOccurred())
   470  
   471  				job2, found, err = pipeline2.Job("job-fake")
   472  				Expect(err).ToNot(HaveOccurred())
   473  				Expect(found).To(BeTrue())
   474  
   475  				pipeline3, _, err := team.SavePipeline(atc.PipelineRef{Name: "fake-pipeline-three"}, atc.Config{
   476  					Jobs: atc.JobConfigs{
   477  						{Name: "job-fake-two"},
   478  					},
   479  				}, db.ConfigVersion(1), false)
   480  				Expect(err).ToNot(HaveOccurred())
   481  
   482  				job3, found, err = pipeline3.Job("job-fake-two")
   483  				Expect(err).ToNot(HaveOccurred())
   484  				Expect(found).To(BeTrue())
   485  
   486  				_, err = dbConn.Exec("UPDATE jobs SET last_scheduled = now() WHERE id = $1;", job2.ID())
   487  				Expect(err).ToNot(HaveOccurred())
   488  
   489  				err = job3.RequestSchedule()
   490  				Expect(err).ToNot(HaveOccurred())
   491  			})
   492  
   493  			It("fetches the jobs that have a requested schedule time later than it's last scheduled", func() {
   494  				jobs, err := jobFactory.JobsToSchedule()
   495  				Expect(err).ToNot(HaveOccurred())
   496  				Expect(len(jobs)).To(Equal(2))
   497  				jobNames := []string{jobs[0].Name(), jobs[1].Name()}
   498  				Expect(jobNames).To(ConsistOf(job1.Name(), job3.Name()))
   499  			})
   500  		})
   501  
   502  		Context("when the job is paused but has a later schedule requested time", func() {
   503  			BeforeEach(func() {
   504  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   505  					Jobs: atc.JobConfigs{
   506  						{Name: "job-name"},
   507  					},
   508  				}, db.ConfigVersion(1), false)
   509  				Expect(err).ToNot(HaveOccurred())
   510  
   511  				var found bool
   512  				job1, found, err = pipeline1.Job("job-name")
   513  				Expect(err).ToNot(HaveOccurred())
   514  				Expect(found).To(BeTrue())
   515  
   516  				err = job1.RequestSchedule()
   517  				Expect(err).ToNot(HaveOccurred())
   518  
   519  				err = job1.Pause()
   520  				Expect(err).ToNot(HaveOccurred())
   521  			})
   522  
   523  			It("does not fetch that job", func() {
   524  				jobs, err := jobFactory.JobsToSchedule()
   525  				Expect(err).ToNot(HaveOccurred())
   526  				Expect(len(jobs)).To(Equal(0))
   527  			})
   528  		})
   529  
   530  		Context("when the job is inactive but has a later schedule requested time", func() {
   531  			BeforeEach(func() {
   532  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   533  					Jobs: atc.JobConfigs{
   534  						{Name: "job-name"},
   535  					},
   536  				}, db.ConfigVersion(1), false)
   537  				Expect(err).ToNot(HaveOccurred())
   538  
   539  				var found bool
   540  				job1, found, err = pipeline1.Job("job-name")
   541  				Expect(err).ToNot(HaveOccurred())
   542  				Expect(found).To(BeTrue())
   543  
   544  				err = job1.RequestSchedule()
   545  				Expect(err).ToNot(HaveOccurred())
   546  
   547  				_, _, err = defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{}, pipeline1.ConfigVersion(), false)
   548  				Expect(err).ToNot(HaveOccurred())
   549  			})
   550  
   551  			It("does not fetch that job", func() {
   552  				jobs, err := jobFactory.JobsToSchedule()
   553  				Expect(err).ToNot(HaveOccurred())
   554  				Expect(len(jobs)).To(Equal(0))
   555  			})
   556  		})
   557  
   558  		Context("when the pipeline is paused but it's job has a later schedule requested time", func() {
   559  			BeforeEach(func() {
   560  				pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   561  					Jobs: atc.JobConfigs{
   562  						{Name: "job-name"},
   563  					},
   564  				}, db.ConfigVersion(1), false)
   565  				Expect(err).ToNot(HaveOccurred())
   566  
   567  				var found bool
   568  				job1, found, err = pipeline1.Job("job-name")
   569  				Expect(err).ToNot(HaveOccurred())
   570  				Expect(found).To(BeTrue())
   571  
   572  				err = job1.RequestSchedule()
   573  				Expect(err).ToNot(HaveOccurred())
   574  
   575  				err = pipeline1.Pause()
   576  				Expect(err).ToNot(HaveOccurred())
   577  			})
   578  
   579  			It("does not fetch that job", func() {
   580  				jobs, err := jobFactory.JobsToSchedule()
   581  				Expect(err).ToNot(HaveOccurred())
   582  				Expect(len(jobs)).To(Equal(0))
   583  			})
   584  		})
   585  
   586  		Describe("scheduler jobs resources", func() {
   587  			Context("when the job needed to be schedule has no resources", func() {
   588  				BeforeEach(func() {
   589  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   590  						Jobs: atc.JobConfigs{
   591  							{Name: "job-name"},
   592  						},
   593  					}, db.ConfigVersion(1), false)
   594  					Expect(err).ToNot(HaveOccurred())
   595  
   596  					var found bool
   597  					job1, found, err = pipeline1.Job("job-name")
   598  					Expect(err).ToNot(HaveOccurred())
   599  					Expect(found).To(BeTrue())
   600  
   601  					err = job1.RequestSchedule()
   602  					Expect(err).ToNot(HaveOccurred())
   603  				})
   604  
   605  				It("fetches that job and no resources", func() {
   606  					jobs, err := jobFactory.JobsToSchedule()
   607  					Expect(err).ToNot(HaveOccurred())
   608  					Expect(len(jobs)).To(Equal(1))
   609  					Expect(jobs[0].Name()).To(Equal(job1.Name()))
   610  					Expect(jobs[0].Resources).To(BeNil())
   611  				})
   612  			})
   613  
   614  			Context("when the job needed to be schedule uses resources", func() {
   615  				BeforeEach(func() {
   616  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   617  						Jobs: atc.JobConfigs{
   618  							{
   619  								Name: "job-name",
   620  								PlanSequence: []atc.Step{
   621  									{
   622  										Config: &atc.GetStep{
   623  											Name: "some-resource",
   624  										},
   625  									},
   626  								},
   627  							},
   628  						},
   629  
   630  						Resources: atc.ResourceConfigs{
   631  							{
   632  								Name: "some-resource",
   633  								Type: "some-type",
   634  								Source: atc.Source{
   635  									"some": "source",
   636  								},
   637  							},
   638  							{
   639  								Name: "unused-resource",
   640  							},
   641  						},
   642  					}, db.ConfigVersion(1), false)
   643  					Expect(err).ToNot(HaveOccurred())
   644  
   645  					var found bool
   646  					job1, found, err = pipeline1.Job("job-name")
   647  					Expect(err).ToNot(HaveOccurred())
   648  					Expect(found).To(BeTrue())
   649  
   650  					err = job1.RequestSchedule()
   651  					Expect(err).ToNot(HaveOccurred())
   652  				})
   653  
   654  				It("fetches that job and the used resource", func() {
   655  					jobs, err := jobFactory.JobsToSchedule()
   656  					Expect(err).ToNot(HaveOccurred())
   657  					Expect(len(jobs)).To(Equal(1))
   658  					Expect(jobs[0].Name()).To(Equal(job1.Name()))
   659  					Expect(jobs[0].Resources).To(HaveLen(1))
   660  					Expect(jobs[0].Resources).To(ConsistOf(
   661  						db.SchedulerResource{
   662  							Name:   "some-resource",
   663  							Type:   "some-type",
   664  							Source: atc.Source{"some": "source"},
   665  						},
   666  					))
   667  				})
   668  			})
   669  
   670  			Context("when multiple jobs needed to be schedule uses resources", func() {
   671  				BeforeEach(func() {
   672  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   673  						Jobs: atc.JobConfigs{
   674  							{
   675  								Name: "job-1",
   676  								PlanSequence: []atc.Step{
   677  									{
   678  										Config: &atc.GetStep{
   679  											Name: "some-resource",
   680  										},
   681  									},
   682  								},
   683  							},
   684  							{
   685  								Name: "job-2",
   686  								PlanSequence: []atc.Step{
   687  									{
   688  										Config: &atc.GetStep{
   689  											Name: "some-resource",
   690  										},
   691  									},
   692  									{
   693  										Config: &atc.GetStep{
   694  											Name: "other-resource",
   695  										},
   696  									},
   697  								},
   698  							},
   699  						},
   700  
   701  						Resources: atc.ResourceConfigs{
   702  							{
   703  								Name: "some-resource",
   704  								Type: "some-type",
   705  							},
   706  							{
   707  								Name: "other-resource",
   708  								Type: "some-type",
   709  							},
   710  							{
   711  								Name: "unused-resource",
   712  								Type: "some-type",
   713  							},
   714  						},
   715  					}, db.ConfigVersion(1), false)
   716  					Expect(err).ToNot(HaveOccurred())
   717  
   718  					pipeline2, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline-2"}, atc.Config{
   719  						Jobs: atc.JobConfigs{
   720  							{
   721  								Name: "job-3",
   722  								PlanSequence: []atc.Step{
   723  									{
   724  										Config: &atc.GetStep{
   725  											Name: "some-resource",
   726  										},
   727  									},
   728  									{
   729  										Config: &atc.GetStep{
   730  											Name: "some-resource-2",
   731  										},
   732  									},
   733  								},
   734  							},
   735  						},
   736  
   737  						Resources: atc.ResourceConfigs{
   738  							{
   739  								Name: "some-resource",
   740  								Type: "other-type",
   741  							},
   742  							{
   743  								Name: "some-resource-2",
   744  								Type: "other-type",
   745  							},
   746  						},
   747  					}, db.ConfigVersion(1), false)
   748  					Expect(err).ToNot(HaveOccurred())
   749  
   750  					var found bool
   751  					job1, found, err = pipeline1.Job("job-1")
   752  					Expect(err).ToNot(HaveOccurred())
   753  					Expect(found).To(BeTrue())
   754  
   755  					job2, found, err = pipeline1.Job("job-2")
   756  					Expect(err).ToNot(HaveOccurred())
   757  					Expect(found).To(BeTrue())
   758  
   759  					job3, found, err = pipeline2.Job("job-3")
   760  					Expect(err).ToNot(HaveOccurred())
   761  					Expect(found).To(BeTrue())
   762  
   763  					err = job1.RequestSchedule()
   764  					Expect(err).ToNot(HaveOccurred())
   765  
   766  					err = job2.RequestSchedule()
   767  					Expect(err).ToNot(HaveOccurred())
   768  
   769  					err = job3.RequestSchedule()
   770  					Expect(err).ToNot(HaveOccurred())
   771  				})
   772  
   773  				It("fetches that job and the used resource", func() {
   774  					jobs, err := jobFactory.JobsToSchedule()
   775  					Expect(err).ToNot(HaveOccurred())
   776  
   777  					jobResources := make(map[string]db.SchedulerResources)
   778  					for _, job := range jobs {
   779  						jobResources[job.Name()] = job.Resources
   780  					}
   781  
   782  					Expect(jobResources).To(MatchAllKeys(Keys{
   783  						job1.Name(): ConsistOf(
   784  							db.SchedulerResource{
   785  								Name: "some-resource",
   786  								Type: "some-type",
   787  							},
   788  						),
   789  						job2.Name(): ConsistOf(
   790  							db.SchedulerResource{
   791  								Name: "some-resource",
   792  								Type: "some-type",
   793  							},
   794  							db.SchedulerResource{
   795  								Name: "other-resource",
   796  								Type: "some-type",
   797  							}),
   798  						job3.Name(): ConsistOf(
   799  							db.SchedulerResource{
   800  								Name: "some-resource",
   801  								Type: "other-type",
   802  							},
   803  							db.SchedulerResource{
   804  								Name: "some-resource-2",
   805  								Type: "other-type",
   806  							}),
   807  					}))
   808  				})
   809  			})
   810  
   811  			Context("when the job needed to be schedule uses resources as puts", func() {
   812  				BeforeEach(func() {
   813  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   814  						Jobs: atc.JobConfigs{
   815  							{
   816  								Name: "job-name",
   817  								PlanSequence: []atc.Step{
   818  									{
   819  										Config: &atc.PutStep{
   820  											Name: "some-resource",
   821  										},
   822  									},
   823  								},
   824  							},
   825  						},
   826  
   827  						Resources: atc.ResourceConfigs{
   828  							{
   829  								Name: "some-resource",
   830  								Type: "some-type",
   831  								Source: atc.Source{
   832  									"some": "source",
   833  								},
   834  							},
   835  							{
   836  								Name: "unused-resource",
   837  							},
   838  						},
   839  					}, db.ConfigVersion(1), false)
   840  					Expect(err).ToNot(HaveOccurred())
   841  
   842  					var found bool
   843  					job1, found, err = pipeline1.Job("job-name")
   844  					Expect(err).ToNot(HaveOccurred())
   845  					Expect(found).To(BeTrue())
   846  
   847  					err = job1.RequestSchedule()
   848  					Expect(err).ToNot(HaveOccurred())
   849  				})
   850  
   851  				It("fetches that job and the used resource", func() {
   852  					jobs, err := jobFactory.JobsToSchedule()
   853  					Expect(err).ToNot(HaveOccurred())
   854  					Expect(len(jobs)).To(Equal(1))
   855  					Expect(jobs[0].Name()).To(Equal(job1.Name()))
   856  					Expect(jobs[0].Resources).To(ConsistOf(
   857  						db.SchedulerResource{
   858  							Name:   "some-resource",
   859  							Type:   "some-type",
   860  							Source: atc.Source{"some": "source"},
   861  						},
   862  					))
   863  				})
   864  			})
   865  
   866  			Context("when the job needed to be schedule uses the resource as a put and a get", func() {
   867  				BeforeEach(func() {
   868  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   869  						Jobs: atc.JobConfigs{
   870  							{
   871  								Name: "job-name",
   872  								PlanSequence: []atc.Step{
   873  									{
   874  										Config: &atc.GetStep{
   875  											Name: "some-resource",
   876  										},
   877  									},
   878  									{
   879  										Config: &atc.PutStep{
   880  											Name: "some-resource",
   881  										},
   882  									},
   883  								},
   884  							},
   885  						},
   886  
   887  						Resources: atc.ResourceConfigs{
   888  							{
   889  								Name: "some-resource",
   890  								Type: "some-type",
   891  								Source: atc.Source{
   892  									"some": "source",
   893  								},
   894  							},
   895  							{
   896  								Name: "unused-resource",
   897  							},
   898  						},
   899  					}, db.ConfigVersion(1), false)
   900  					Expect(err).ToNot(HaveOccurred())
   901  
   902  					var found bool
   903  					job1, found, err = pipeline1.Job("job-name")
   904  					Expect(err).ToNot(HaveOccurred())
   905  					Expect(found).To(BeTrue())
   906  
   907  					err = job1.RequestSchedule()
   908  					Expect(err).ToNot(HaveOccurred())
   909  				})
   910  
   911  				It("fetches that job and the used resource", func() {
   912  					jobs, err := jobFactory.JobsToSchedule()
   913  					Expect(err).ToNot(HaveOccurred())
   914  					Expect(len(jobs)).To(Equal(1))
   915  					Expect(jobs[0].Name()).To(Equal(job1.Name()))
   916  					Expect(jobs[0].Resources).To(ConsistOf(
   917  						db.SchedulerResource{
   918  							Name:   "some-resource",
   919  							Type:   "some-type",
   920  							Source: atc.Source{"some": "source"},
   921  						},
   922  					))
   923  				})
   924  			})
   925  		})
   926  
   927  		Describe("schedule jobs resource types", func() {
   928  			Context("when the pipeline for the job needed to be scheduled uses custom resource types", func() {
   929  				BeforeEach(func() {
   930  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   931  						Jobs: atc.JobConfigs{
   932  							{Name: "job-name"},
   933  						},
   934  						ResourceTypes: atc.ResourceTypes{
   935  							{
   936  								Name: "some-type",
   937  								Type: "other-type",
   938  							},
   939  						},
   940  					}, db.ConfigVersion(1), false)
   941  					Expect(err).ToNot(HaveOccurred())
   942  
   943  					var found bool
   944  					job1, found, err = pipeline1.Job("job-name")
   945  					Expect(err).ToNot(HaveOccurred())
   946  					Expect(found).To(BeTrue())
   947  
   948  					err = job1.RequestSchedule()
   949  					Expect(err).ToNot(HaveOccurred())
   950  				})
   951  
   952  				It("fetches that job and resource type", func() {
   953  					jobs, err := jobFactory.JobsToSchedule()
   954  					Expect(err).ToNot(HaveOccurred())
   955  					Expect(len(jobs)).To(Equal(1))
   956  					Expect(jobs[0].Name()).To(Equal(job1.Name()))
   957  					Expect(jobs[0].ResourceTypes).To(ConsistOf(
   958  						atc.VersionedResourceType{
   959  							ResourceType: atc.ResourceType{
   960  								Name: "some-type",
   961  								Type: "other-type",
   962  							},
   963  						},
   964  					))
   965  				})
   966  			})
   967  
   968  			Context("when multiple job from different pipelines uses custom resource types", func() {
   969  				BeforeEach(func() {
   970  					pipeline1, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, atc.Config{
   971  						Jobs: atc.JobConfigs{
   972  							{Name: "job-1"},
   973  							{Name: "job-2"},
   974  						},
   975  						ResourceTypes: atc.ResourceTypes{
   976  							{
   977  								Name: "some-type",
   978  								Type: "other-type",
   979  							},
   980  						},
   981  					}, db.ConfigVersion(1), false)
   982  					Expect(err).ToNot(HaveOccurred())
   983  
   984  					pipeline2, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "fake-pipeline-2"}, atc.Config{
   985  						Jobs: atc.JobConfigs{
   986  							{Name: "job-3"},
   987  						},
   988  						ResourceTypes: atc.ResourceTypes{
   989  							{
   990  								Name: "some-type-1",
   991  								Type: "other-type-1",
   992  							},
   993  							{
   994  								Name: "some-type-2",
   995  								Type: "other-type-2",
   996  							},
   997  						},
   998  					}, db.ConfigVersion(1), false)
   999  					Expect(err).ToNot(HaveOccurred())
  1000  
  1001  					var found bool
  1002  					job1, found, err = pipeline1.Job("job-1")
  1003  					Expect(err).ToNot(HaveOccurred())
  1004  					Expect(found).To(BeTrue())
  1005  
  1006  					err = job1.RequestSchedule()
  1007  					Expect(err).ToNot(HaveOccurred())
  1008  
  1009  					job2, found, err = pipeline1.Job("job-2")
  1010  					Expect(err).ToNot(HaveOccurred())
  1011  					Expect(found).To(BeTrue())
  1012  
  1013  					err = job2.RequestSchedule()
  1014  					Expect(err).ToNot(HaveOccurred())
  1015  
  1016  					job3, found, err = pipeline2.Job("job-3")
  1017  					Expect(err).ToNot(HaveOccurred())
  1018  					Expect(found).To(BeTrue())
  1019  
  1020  					err = job3.RequestSchedule()
  1021  					Expect(err).ToNot(HaveOccurred())
  1022  				})
  1023  
  1024  				It("fetches all jobs and resource types", func() {
  1025  					jobs, err := jobFactory.JobsToSchedule()
  1026  					Expect(err).ToNot(HaveOccurred())
  1027  
  1028  					jobResourceTypes := make(map[string]atc.VersionedResourceTypes)
  1029  					for _, job := range jobs {
  1030  						jobResourceTypes[job.Name()] = job.ResourceTypes
  1031  					}
  1032  
  1033  					Expect(jobResourceTypes).To(MatchAllKeys(Keys{
  1034  						job1.Name(): ConsistOf(
  1035  							atc.VersionedResourceType{
  1036  								ResourceType: atc.ResourceType{
  1037  									Name: "some-type",
  1038  									Type: "other-type",
  1039  								},
  1040  							},
  1041  						),
  1042  						job2.Name(): ConsistOf(
  1043  							atc.VersionedResourceType{
  1044  								ResourceType: atc.ResourceType{
  1045  									Name: "some-type",
  1046  									Type: "other-type",
  1047  								},
  1048  							},
  1049  						),
  1050  						job3.Name(): ConsistOf(
  1051  							atc.VersionedResourceType{
  1052  								ResourceType: atc.ResourceType{
  1053  									Name: "some-type-1",
  1054  									Type: "other-type-1",
  1055  								},
  1056  							},
  1057  							atc.VersionedResourceType{
  1058  								ResourceType: atc.ResourceType{
  1059  									Name: "some-type-2",
  1060  									Type: "other-type-2",
  1061  								},
  1062  							},
  1063  						),
  1064  					}))
  1065  				})
  1066  			})
  1067  		})
  1068  	})
  1069  })
  1070  
  1071  var _ = Context("SchedulerResource", func() {
  1072  	var resource db.SchedulerResource
  1073  
  1074  	BeforeEach(func() {
  1075  		resource = db.SchedulerResource{
  1076  			Name: "some-name",
  1077  			Type: "some-type",
  1078  			Source: atc.Source{
  1079  				"some-key": "some-value",
  1080  			},
  1081  		}
  1082  	})
  1083  
  1084  	Context("ApplySourceDefaults", func() {
  1085  		var resourceTypes atc.VersionedResourceTypes
  1086  
  1087  		BeforeEach(func() {
  1088  			resourceTypes = atc.VersionedResourceTypes{
  1089  				{
  1090  					ResourceType: atc.ResourceType{
  1091  						Name:     "some-type",
  1092  						Defaults: atc.Source{"default-key": "default-value"},
  1093  					},
  1094  				},
  1095  			}
  1096  		})
  1097  
  1098  		JustBeforeEach(func() {
  1099  			resource.ApplySourceDefaults(resourceTypes)
  1100  		})
  1101  
  1102  		It("should apply defaults", func() {
  1103  			Expect(resource).To(Equal(db.SchedulerResource{
  1104  				Name: "some-name",
  1105  				Type: "some-type",
  1106  				Source: atc.Source{
  1107  					"some-key":    "some-value",
  1108  					"default-key": "default-value",
  1109  				},
  1110  			}))
  1111  		})
  1112  
  1113  		Context("when the parent resource is not found", func() {
  1114  			BeforeEach(func() {
  1115  				resourceTypes = atc.VersionedResourceTypes{}
  1116  				atc.LoadBaseResourceTypeDefaults(map[string]atc.Source{
  1117  					"some-type": {"default-key": "default-value"},
  1118  				})
  1119  			})
  1120  
  1121  			AfterEach(func() {
  1122  				atc.LoadBaseResourceTypeDefaults(map[string]atc.Source{})
  1123  			})
  1124  
  1125  			It("should apply defaults using the base resource type", func() {
  1126  				Expect(resource).To(Equal(db.SchedulerResource{
  1127  					Name: "some-name",
  1128  					Type: "some-type",
  1129  					Source: atc.Source{
  1130  						"some-key":    "some-value",
  1131  						"default-key": "default-value",
  1132  					},
  1133  				}))
  1134  			})
  1135  		})
  1136  	})
  1137  })