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

     1  package db_test
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/pf-qiu/concourse/v6/atc"
     8  	"github.com/pf-qiu/concourse/v6/atc/db"
     9  	"github.com/pf-qiu/concourse/v6/atc/db/dbfakes"
    10  	. "github.com/onsi/ginkgo"
    11  	. "github.com/onsi/gomega"
    12  )
    13  
    14  var _ = Describe("CheckFactory", func() {
    15  	var (
    16  		err error
    17  	)
    18  
    19  	Describe("TryCreateCheck", func() {
    20  		var (
    21  			created bool
    22  			build   db.Build
    23  
    24  			fakeResource      *dbfakes.FakeResource
    25  			fakeResourceType  *dbfakes.FakeResourceType
    26  			fakeResourceTypes db.ResourceTypes
    27  			fromVersion       atc.Version
    28  			manuallyTriggered bool
    29  
    30  			checkPlan atc.CheckPlan
    31  			fakeBuild *dbfakes.FakeBuild
    32  		)
    33  
    34  		BeforeEach(func() {
    35  			fromVersion = atc.Version{"from": "version"}
    36  
    37  			checkPlan = atc.CheckPlan{
    38  				Type:   "doesnt-matter",
    39  				Source: atc.Source{"doesnt": "matter"},
    40  			}
    41  
    42  			fakeResource = new(dbfakes.FakeResource)
    43  			fakeResource.NameReturns("some-name")
    44  			fakeResource.TagsReturns([]string{"tag-a", "tag-b"})
    45  			fakeResource.SourceReturns(atc.Source{"some": "source"})
    46  			fakeResource.PipelineIDReturns(defaultPipeline.ID())
    47  			fakeResource.PipelineNameReturns(defaultPipeline.Name())
    48  			fakeResource.PipelineInstanceVarsReturns(defaultPipeline.InstanceVars())
    49  			fakeResource.PipelineReturns(defaultPipeline, true, nil)
    50  			fakeResource.CheckPlanReturns(checkPlan)
    51  
    52  			fakeBuild = new(dbfakes.FakeBuild)
    53  			fakeResource.CreateBuildReturns(fakeBuild, true, nil)
    54  
    55  			fakeResourceType = new(dbfakes.FakeResourceType)
    56  			fakeResourceType.NameReturns("some-type")
    57  			fakeResourceType.TypeReturns("some-base-type")
    58  			fakeResourceType.TagsReturns([]string{"some-tag"})
    59  			fakeResourceType.SourceReturns(atc.Source{"some": "type-source"})
    60  			fakeResourceType.DefaultsReturns(atc.Source{"some-default": "some-default-value"})
    61  			fakeResourceType.PipelineIDReturns(defaultPipeline.ID())
    62  			fakeResourceType.PipelineNameReturns(defaultPipeline.Name())
    63  			fakeResourceType.PipelineInstanceVarsReturns(defaultPipeline.InstanceVars())
    64  			fakeResourceType.PipelineReturns(defaultPipeline, true, nil)
    65  
    66  			fakeResourceTypes = db.ResourceTypes{fakeResourceType}
    67  			manuallyTriggered = false
    68  		})
    69  
    70  		JustBeforeEach(func() {
    71  			build, created, err = checkFactory.TryCreateCheck(context.TODO(), fakeResource, fakeResourceTypes, fromVersion, manuallyTriggered)
    72  		})
    73  
    74  		Context("when the resource parent type is not a custom type", func() {
    75  			BeforeEach(func() {
    76  				fakeResource.TypeReturns("base-type")
    77  			})
    78  
    79  			It("returns the build", func() {
    80  				Expect(err).NotTo(HaveOccurred())
    81  				Expect(created).To(BeTrue())
    82  				Expect(build).To(Equal(fakeBuild))
    83  			})
    84  
    85  			It("starts the build with the check plan", func() {
    86  				Expect(fakeResource.CreateBuildCallCount()).To(Equal(1))
    87  				_, manuallyTriggered, plan := fakeResource.CreateBuildArgsForCall(0)
    88  				Expect(manuallyTriggered).To(BeFalse())
    89  				Expect(plan.ID).ToNot(BeEmpty())
    90  				Expect(plan.Check).To(Equal(&checkPlan))
    91  			})
    92  
    93  			Context("when the interval has not elapsed", func() {
    94  				BeforeEach(func() {
    95  					fakeResource.LastCheckEndTimeReturns(time.Now().Add(defaultCheckInterval))
    96  				})
    97  
    98  				It("does not create a build for the resource", func() {
    99  					Expect(fakeResource.CheckPlanCallCount()).To(Equal(0))
   100  					Expect(fakeResource.CreateBuildCallCount()).To(Equal(0))
   101  				})
   102  
   103  				Context("but the check is manually triggered", func() {
   104  					BeforeEach(func() {
   105  						manuallyTriggered = true
   106  					})
   107  
   108  					It("creates the build anyway", func() {
   109  						Expect(fakeResource.CheckPlanCallCount()).To(Equal(1))
   110  						Expect(fakeResource.CreateBuildCallCount()).To(Equal(1))
   111  					})
   112  				})
   113  			})
   114  
   115  			Context("when a build is not created", func() {
   116  				BeforeEach(func() {
   117  					fakeResource.CreateBuildReturns(nil, false, nil)
   118  				})
   119  
   120  				It("returns false", func() {
   121  					Expect(err).NotTo(HaveOccurred())
   122  					Expect(created).To(BeFalse())
   123  					Expect(build).To(BeNil())
   124  				})
   125  			})
   126  		})
   127  
   128  		Context("when the resource has a webhook configured", func() {
   129  			BeforeEach(func() {
   130  				fakeResource.HasWebhookReturns(true)
   131  			})
   132  
   133  			It("creates a check plan with the default webhook interval", func() {
   134  				Expect(fakeResource.CheckPlanCallCount()).To(Equal(1))
   135  				version, interval, types, defaults := fakeResource.CheckPlanArgsForCall(0)
   136  				Expect(version).To(Equal(atc.Version{"from": "version"}))
   137  				Expect(interval).To(Equal(defaultWebhookCheckInterval))
   138  				Expect(types).To(BeNil())
   139  				Expect(defaults).To(BeEmpty())
   140  			})
   141  
   142  			Context("when the default webhook interval has not elapsed", func() {
   143  				BeforeEach(func() {
   144  					fakeResource.LastCheckEndTimeReturns(time.Now().Add(-(defaultWebhookCheckInterval / 2)))
   145  				})
   146  
   147  				It("does not create a build for the resource", func() {
   148  					Expect(fakeResource.CheckPlanCallCount()).To(Equal(0))
   149  					Expect(fakeResource.CreateBuildCallCount()).To(Equal(0))
   150  				})
   151  			})
   152  		})
   153  
   154  		Context("when an interval is specified", func() {
   155  			BeforeEach(func() {
   156  				fakeResource.CheckEveryReturns("42s")
   157  			})
   158  
   159  			It("sets it in the check plan", func() {
   160  				Expect(fakeResource.CheckPlanCallCount()).To(Equal(1))
   161  				version, interval, types, defaults := fakeResource.CheckPlanArgsForCall(0)
   162  				Expect(version).To(Equal(atc.Version{"from": "version"}))
   163  				Expect(interval).To(Equal(42 * time.Second))
   164  				Expect(types).To(BeNil())
   165  				Expect(defaults).To(BeEmpty())
   166  			})
   167  		})
   168  
   169  		Context("when the interval is not parseable", func() {
   170  			BeforeEach(func() {
   171  				fakeResource.CheckEveryReturns("not-a-duration")
   172  			})
   173  
   174  			It("errors", func() {
   175  				Expect(err).To(HaveOccurred())
   176  			})
   177  		})
   178  
   179  		Context("when the resource has a parent type", func() {
   180  			BeforeEach(func() {
   181  				fakeResource.TypeReturns("custom-type")
   182  				fakeResource.PipelineIDReturns(1)
   183  				fakeResourceType.NameReturns("custom-type")
   184  				fakeResourceType.PipelineIDReturns(1)
   185  				fakeResourceType.DefaultsReturns(atc.Source{"sdk": "sdk"})
   186  			})
   187  
   188  			Context("when the parent type has no version", func() {
   189  				BeforeEach(func() {
   190  					fakeResourceType.VersionReturns(nil)
   191  				})
   192  
   193  				It("errors", func() {
   194  					Expect(err).To(HaveOccurred())
   195  				})
   196  			})
   197  
   198  			Context("when the parent type has a version", func() {
   199  				BeforeEach(func() {
   200  					fakeResourceType.VersionReturns(atc.Version{"some": "version"})
   201  				})
   202  
   203  				Context("when the parent type's interval has not elapsed", func() {
   204  					BeforeEach(func() {
   205  						fakeResourceType.LastCheckEndTimeReturns(time.Now().Add(defaultCheckInterval))
   206  					})
   207  
   208  					It("does not create a build for the parent type", func() {
   209  						Expect(fakeResourceType.CheckPlanCallCount()).To(Equal(0))
   210  						Expect(fakeResourceType.CreateBuildCallCount()).To(Equal(0))
   211  					})
   212  				})
   213  
   214  				Context("when the parent type's interval has elapsed", func() {
   215  					BeforeEach(func() {
   216  						fakeResourceType.LastCheckEndTimeReturns(time.Now().Add(-defaultCheckInterval))
   217  						fakeResource.LastCheckEndTimeReturns(time.Now().Add(-defaultCheckInterval))
   218  					})
   219  
   220  					It("creates a check plan", func() {
   221  						Expect(fakeResource.CheckPlanCallCount()).To(Equal(1))
   222  						version, interval, types, defaults := fakeResource.CheckPlanArgsForCall(0)
   223  						Expect(version).To(Equal(atc.Version{"from": "version"}))
   224  						Expect(interval).To(Equal(defaultCheckInterval))
   225  						Expect(types).To(Equal(fakeResourceTypes))
   226  						Expect(defaults).To(Equal(atc.Source{"sdk": "sdk"}))
   227  					})
   228  
   229  					It("returns the build", func() {
   230  						Expect(err).NotTo(HaveOccurred())
   231  						Expect(created).To(BeTrue())
   232  						Expect(build).To(Equal(fakeBuild))
   233  					})
   234  
   235  					It("starts the build with the check plan", func() {
   236  						Expect(fakeResource.CreateBuildCallCount()).To(Equal(1))
   237  						_, manuallyTriggered, plan := fakeResource.CreateBuildArgsForCall(0)
   238  						Expect(manuallyTriggered).To(BeFalse())
   239  						Expect(plan.ID).ToNot(BeEmpty())
   240  						Expect(plan.Check).To(Equal(&checkPlan))
   241  					})
   242  				})
   243  			})
   244  		})
   245  	})
   246  
   247  	Describe("Resources", func() {
   248  		var (
   249  			resources []db.Resource
   250  		)
   251  
   252  		BeforeEach(func() {
   253  			defaultPipelineConfig = atc.Config{
   254  				Jobs: atc.JobConfigs{
   255  					{
   256  						Name: "some-job",
   257  						PlanSequence: []atc.Step{
   258  							{
   259  								Config: &atc.GetStep{
   260  									Name: "some-resource",
   261  								},
   262  							},
   263  							{
   264  								Config: &atc.PutStep{
   265  									Name: "some-put-only-resource",
   266  								},
   267  							},
   268  						},
   269  					},
   270  				},
   271  				Resources: atc.ResourceConfigs{
   272  					{
   273  						Name: "some-resource",
   274  						Type: "some-base-resource-type",
   275  						Source: atc.Source{
   276  							"some": "source",
   277  						},
   278  					},
   279  					{
   280  						Name: "some-put-only-resource",
   281  						Type: "some-base-resource-type",
   282  						Source: atc.Source{
   283  							"some": "source",
   284  						},
   285  					},
   286  				},
   287  				ResourceTypes: atc.ResourceTypes{
   288  					{
   289  						Name: "some-type",
   290  						Type: "some-base-resource-type",
   291  						Source: atc.Source{
   292  							"some-type": "source",
   293  						},
   294  					},
   295  				},
   296  			}
   297  
   298  			defaultPipelineRef = atc.PipelineRef{Name: "default-pipeline", InstanceVars: atc.InstanceVars{"branch": "master"}}
   299  			defaultPipeline, _, err = defaultTeam.SavePipeline(defaultPipelineRef, defaultPipelineConfig, db.ConfigVersion(1), false)
   300  			Expect(err).NotTo(HaveOccurred())
   301  
   302  			_, found, err := defaultPipeline.Resource("some-put-only-resource")
   303  			Expect(err).ToNot(HaveOccurred())
   304  			Expect(found).To(BeTrue())
   305  		})
   306  
   307  		JustBeforeEach(func() {
   308  			resources, err = checkFactory.Resources()
   309  			Expect(err).NotTo(HaveOccurred())
   310  		})
   311  
   312  		It("include only resources-in-use in return", func() {
   313  			Expect(resources).To(HaveLen(1))
   314  			Expect(resources[0].Name()).To(Equal("some-resource"))
   315  		})
   316  
   317  		Context("when the resource is not active", func() {
   318  			BeforeEach(func() {
   319  				_, err = dbConn.Exec(`UPDATE resources SET active = false`)
   320  				Expect(err).NotTo(HaveOccurred())
   321  			})
   322  
   323  			It("does not return the resource", func() {
   324  				Expect(resources).To(HaveLen(0))
   325  			})
   326  		})
   327  
   328  		Context("when the resource pipeline is paused", func() {
   329  			BeforeEach(func() {
   330  				_, err = dbConn.Exec(`UPDATE pipelines SET paused = true`)
   331  				Expect(err).NotTo(HaveOccurred())
   332  			})
   333  
   334  			It("does not return the resource", func() {
   335  				Expect(resources).To(HaveLen(0))
   336  			})
   337  		})
   338  	})
   339  
   340  	Describe("ResourceTypes", func() {
   341  		var (
   342  			resourceTypes db.ResourceTypes
   343  		)
   344  
   345  		JustBeforeEach(func() {
   346  			resourceTypes, err = checkFactory.ResourceTypes()
   347  			Expect(err).NotTo(HaveOccurred())
   348  		})
   349  
   350  		It("include resource types in return", func() {
   351  			Expect(resourceTypes).To(HaveLen(1))
   352  			Expect(resourceTypes[0].Name()).To(Equal("some-type"))
   353  		})
   354  
   355  		Context("when the resource type is not active", func() {
   356  			BeforeEach(func() {
   357  				_, err = dbConn.Exec(`UPDATE resource_types SET active = false`)
   358  				Expect(err).NotTo(HaveOccurred())
   359  			})
   360  
   361  			It("does not return the resource type", func() {
   362  				Expect(resourceTypes).To(HaveLen(0))
   363  			})
   364  		})
   365  	})
   366  })