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

     1  package engine_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"time"
     7  
     8  	. "github.com/onsi/ginkgo"
     9  	. "github.com/onsi/gomega"
    10  
    11  	"code.cloudfoundry.org/clock/fakeclock"
    12  	"code.cloudfoundry.org/lager"
    13  	"github.com/pf-qiu/concourse/v6/atc"
    14  	"github.com/pf-qiu/concourse/v6/atc/db"
    15  	"github.com/pf-qiu/concourse/v6/atc/db/dbfakes"
    16  	"github.com/pf-qiu/concourse/v6/atc/db/lock"
    17  	"github.com/pf-qiu/concourse/v6/atc/db/lock/lockfakes"
    18  	"github.com/pf-qiu/concourse/v6/atc/engine"
    19  	"github.com/pf-qiu/concourse/v6/atc/engine/enginefakes"
    20  	"github.com/pf-qiu/concourse/v6/atc/exec"
    21  	"github.com/pf-qiu/concourse/v6/atc/policy/policyfakes"
    22  	"github.com/pf-qiu/concourse/v6/vars"
    23  )
    24  
    25  var _ = Describe("CheckDelegate", func() {
    26  	var (
    27  		fakeBuild         *dbfakes.FakeBuild
    28  		fakeClock         *fakeclock.FakeClock
    29  		fakeRateLimiter   *enginefakes.FakeRateLimiter
    30  		fakePolicyChecker *policyfakes.FakeChecker
    31  
    32  		state exec.RunState
    33  
    34  		now = time.Date(1991, 6, 3, 5, 30, 0, 0, time.UTC)
    35  
    36  		plan     atc.Plan
    37  		delegate exec.CheckDelegate
    38  
    39  		fakeResourceConfig      *dbfakes.FakeResourceConfig
    40  		fakeResourceConfigScope *dbfakes.FakeResourceConfigScope
    41  	)
    42  
    43  	BeforeEach(func() {
    44  		fakeBuild = new(dbfakes.FakeBuild)
    45  		fakeClock = fakeclock.NewFakeClock(now)
    46  		fakeRateLimiter = new(enginefakes.FakeRateLimiter)
    47  		credVars := vars.StaticVariables{
    48  			"source-param": "super-secret-source",
    49  			"git-key":      "{\n123\n456\n789\n}\n",
    50  		}
    51  		state = exec.NewRunState(noopStepper, credVars, true)
    52  
    53  		plan = atc.Plan{
    54  			ID:    "some-plan-id",
    55  			Check: &atc.CheckPlan{},
    56  		}
    57  
    58  		fakePolicyChecker = new(policyfakes.FakeChecker)
    59  
    60  		delegate = engine.NewCheckDelegate(fakeBuild, plan, state, fakeClock, fakeRateLimiter, fakePolicyChecker)
    61  
    62  		fakeResourceConfig = new(dbfakes.FakeResourceConfig)
    63  		fakeResourceConfigScope = new(dbfakes.FakeResourceConfigScope)
    64  		fakeResourceConfig.FindOrCreateScopeReturns(fakeResourceConfigScope, nil)
    65  	})
    66  
    67  	Describe("FindOrCreateScope", func() {
    68  		var saveErr error
    69  		var scope db.ResourceConfigScope
    70  
    71  		BeforeEach(func() {
    72  			saveErr = nil
    73  		})
    74  
    75  		JustBeforeEach(func() {
    76  			scope, saveErr = delegate.FindOrCreateScope(fakeResourceConfig)
    77  		})
    78  
    79  		Context("without a resource", func() {
    80  			BeforeEach(func() {
    81  				plan.Check.Resource = ""
    82  			})
    83  
    84  			It("succeeds", func() {
    85  				Expect(saveErr).ToNot(HaveOccurred())
    86  			})
    87  
    88  			It("finds or creates a global scope", func() {
    89  				Expect(fakeResourceConfig.FindOrCreateScopeCallCount()).To(Equal(1))
    90  				resource := fakeResourceConfig.FindOrCreateScopeArgsForCall(0)
    91  				Expect(resource).To(BeNil())
    92  			})
    93  
    94  			It("returns the scope", func() {
    95  				Expect(scope).To(Equal(fakeResourceConfigScope))
    96  			})
    97  		})
    98  
    99  		Context("with a resource", func() {
   100  			var (
   101  				fakePipeline *dbfakes.FakePipeline
   102  				fakeResource *dbfakes.FakeResource
   103  			)
   104  
   105  			BeforeEach(func() {
   106  				plan.Check.Resource = "some-resource"
   107  
   108  				fakePipeline = new(dbfakes.FakePipeline)
   109  				fakeBuild.PipelineReturns(fakePipeline, true, nil)
   110  
   111  				fakeResource = new(dbfakes.FakeResource)
   112  				fakePipeline.ResourceReturns(fakeResource, true, nil)
   113  			})
   114  
   115  			It("succeeds", func() {
   116  				Expect(saveErr).ToNot(HaveOccurred())
   117  			})
   118  
   119  			It("looks up the resource on the pipeline", func() {
   120  				Expect(fakePipeline.ResourceCallCount()).To(Equal(1))
   121  				resourceName := fakePipeline.ResourceArgsForCall(0)
   122  				Expect(resourceName).To(Equal("some-resource"))
   123  			})
   124  
   125  			It("finds or creates a scope for the resource", func() {
   126  				Expect(fakeResourceConfig.FindOrCreateScopeCallCount()).To(Equal(1))
   127  				resource := fakeResourceConfig.FindOrCreateScopeArgsForCall(0)
   128  				Expect(resource).To(Equal(fakeResource))
   129  			})
   130  
   131  			It("returns the scope", func() {
   132  				Expect(scope).To(Equal(fakeResourceConfigScope))
   133  			})
   134  
   135  			Context("when the pipeline is not found", func() {
   136  				BeforeEach(func() {
   137  					fakeBuild.PipelineReturns(nil, false, nil)
   138  				})
   139  
   140  				It("returns an error", func() {
   141  					Expect(saveErr).To(HaveOccurred())
   142  				})
   143  
   144  				It("does not create a scope", func() {
   145  					Expect(fakeResourceConfig.FindOrCreateScopeCallCount()).To(BeZero())
   146  				})
   147  			})
   148  
   149  			Context("when the resource is not found", func() {
   150  				BeforeEach(func() {
   151  					fakePipeline.ResourceReturns(nil, false, nil)
   152  				})
   153  
   154  				It("returns an error", func() {
   155  					Expect(saveErr).To(HaveOccurred())
   156  				})
   157  
   158  				It("does not create a scope", func() {
   159  					Expect(fakeResourceConfig.FindOrCreateScopeCallCount()).To(BeZero())
   160  				})
   161  			})
   162  		})
   163  	})
   164  
   165  	Describe("WaitToRun", func() {
   166  		var runLock lock.Lock
   167  		var run bool
   168  		var runErr error
   169  
   170  		BeforeEach(func() {
   171  			run = false
   172  		})
   173  
   174  		JustBeforeEach(func() {
   175  			runLock, run, runErr = delegate.WaitToRun(context.TODO(), fakeResourceConfigScope)
   176  		})
   177  
   178  		Context("when the build is manually triggered", func() {
   179  			BeforeEach(func() {
   180  				fakeBuild.IsManuallyTriggeredReturns(true)
   181  			})
   182  
   183  			It("returns true", func() {
   184  				Expect(run).To(BeTrue())
   185  			})
   186  		})
   187  
   188  		Context("with an interval configured", func() {
   189  			var interval time.Duration = time.Minute
   190  
   191  			BeforeEach(func() {
   192  				plan.Check.Interval = interval.String()
   193  			})
   194  
   195  			Context("when the interval has not elapsed since the last check", func() {
   196  				BeforeEach(func() {
   197  					fakeResourceConfigScope.LastCheckEndTimeReturns(now.Add(-(interval - 1)), nil)
   198  				})
   199  
   200  				It("returns false", func() {
   201  					Expect(run).To(BeFalse())
   202  				})
   203  			})
   204  
   205  			Context("when the interval has elapsed since the last check", func() {
   206  				BeforeEach(func() {
   207  					fakeResourceConfigScope.LastCheckEndTimeReturns(now.Add(-interval), nil)
   208  				})
   209  
   210  				It("returns true", func() {
   211  					Expect(run).To(BeTrue())
   212  				})
   213  			})
   214  		})
   215  
   216  		Context("when running for a resource", func() {
   217  			var fakeLock *lockfakes.FakeLock
   218  
   219  			BeforeEach(func() {
   220  				plan.Check.Resource = "some-resource"
   221  
   222  				fakeLock = new(lockfakes.FakeLock)
   223  				fakeResourceConfigScope.AcquireResourceCheckingLockReturns(fakeLock, true, nil)
   224  			})
   225  
   226  			It("returns a lock", func() {
   227  				Expect(runLock).To(Equal(fakeLock))
   228  			})
   229  
   230  			Context("before acquiring the lock", func() {
   231  				BeforeEach(func() {
   232  					fakeResourceConfigScope.AcquireResourceCheckingLockStub = func(lager.Logger) (lock.Lock, bool, error) {
   233  						Expect(fakeRateLimiter.WaitCallCount()).To(Equal(1))
   234  						return fakeLock, true, nil
   235  					}
   236  				})
   237  
   238  				It("rate limits", func() {
   239  					Expect(fakeRateLimiter.WaitCallCount()).To(Equal(1))
   240  				})
   241  			})
   242  
   243  			Context("when the build is manually triggered", func() {
   244  				BeforeEach(func() {
   245  					fakeBuild.IsManuallyTriggeredReturns(true)
   246  				})
   247  
   248  				It("does not rate limit", func() {
   249  					Expect(fakeRateLimiter.WaitCallCount()).To(Equal(0))
   250  				})
   251  			})
   252  
   253  			Context("when getting the last check end time errors", func() {
   254  				BeforeEach(func() {
   255  					fakeResourceConfigScope.LastCheckEndTimeReturns(time.Time{}, errors.New("oh no"))
   256  				})
   257  
   258  				It("returns an error", func() {
   259  					Expect(runErr).To(HaveOccurred())
   260  				})
   261  
   262  				It("releases the lock", func() {
   263  					Expect(fakeLock.ReleaseCallCount()).To(Equal(1))
   264  				})
   265  			})
   266  
   267  			Context("with an interval configured", func() {
   268  				var interval time.Duration = time.Minute
   269  
   270  				BeforeEach(func() {
   271  					plan.Check.Interval = interval.String()
   272  				})
   273  
   274  				Context("when the interval has not elapsed since the last check", func() {
   275  					BeforeEach(func() {
   276  						fakeResourceConfigScope.LastCheckEndTimeReturns(now.Add(-(interval - 1)), nil)
   277  					})
   278  
   279  					It("returns false", func() {
   280  						Expect(run).To(BeFalse())
   281  					})
   282  
   283  					It("releases the lock", func() {
   284  						Expect(fakeLock.ReleaseCallCount()).To(Equal(1))
   285  					})
   286  				})
   287  			})
   288  		})
   289  
   290  		Context("when not running for a resource", func() {
   291  			BeforeEach(func() {
   292  				plan.Check.Resource = ""
   293  			})
   294  
   295  			It("does not rate limit", func() {
   296  				Expect(fakeRateLimiter.WaitCallCount()).To(Equal(0))
   297  			})
   298  
   299  			It("does not acquire a lock", func() {
   300  				Expect(fakeResourceConfigScope.AcquireResourceCheckingLockCallCount()).To(Equal(0))
   301  			})
   302  
   303  			It("returns a no-op lock", func() {
   304  				Expect(runLock).To(Equal(lock.NoopLock{}))
   305  			})
   306  		})
   307  	})
   308  
   309  	Describe("PointToCheckedConfig", func() {
   310  		var pointErr error
   311  
   312  		BeforeEach(func() {
   313  			pointErr = nil
   314  		})
   315  
   316  		JustBeforeEach(func() {
   317  			pointErr = delegate.PointToCheckedConfig(fakeResourceConfigScope)
   318  		})
   319  
   320  		Context("when not checking for a resource or resource type", func() {
   321  			It("succeeds", func() {
   322  				Expect(pointErr).ToNot(HaveOccurred())
   323  			})
   324  		})
   325  
   326  		Context("when checking for a resource", func() {
   327  			var (
   328  				fakePipeline *dbfakes.FakePipeline
   329  				fakeResource *dbfakes.FakeResource
   330  			)
   331  
   332  			BeforeEach(func() {
   333  				plan.Check.Resource = "some-resource"
   334  
   335  				fakePipeline = new(dbfakes.FakePipeline)
   336  				fakeBuild.PipelineReturns(fakePipeline, true, nil)
   337  
   338  				fakeResource = new(dbfakes.FakeResource)
   339  				fakePipeline.ResourceReturns(fakeResource, true, nil)
   340  			})
   341  
   342  			It("succeeds", func() {
   343  				Expect(pointErr).ToNot(HaveOccurred())
   344  			})
   345  
   346  			It("looks up the resource on the pipeline", func() {
   347  				Expect(fakePipeline.ResourceCallCount()).To(Equal(1))
   348  				resourceName := fakePipeline.ResourceArgsForCall(0)
   349  				Expect(resourceName).To(Equal("some-resource"))
   350  			})
   351  
   352  			It("sets the resource config scope", func() {
   353  				Expect(fakeResource.SetResourceConfigScopeCallCount()).To(Equal(1))
   354  				scope := fakeResource.SetResourceConfigScopeArgsForCall(0)
   355  				Expect(scope).To(Equal(fakeResourceConfigScope))
   356  			})
   357  
   358  			Context("when the pipeline is not found", func() {
   359  				BeforeEach(func() {
   360  					fakeBuild.PipelineReturns(nil, false, nil)
   361  				})
   362  
   363  				It("returns an error", func() {
   364  					Expect(pointErr).To(HaveOccurred())
   365  				})
   366  			})
   367  
   368  			Context("when the resource is not found", func() {
   369  				BeforeEach(func() {
   370  					fakePipeline.ResourceReturns(nil, false, nil)
   371  				})
   372  
   373  				It("returns an error", func() {
   374  					Expect(pointErr).To(HaveOccurred())
   375  				})
   376  			})
   377  		})
   378  
   379  		Context("when checking for a resource type", func() {
   380  			var (
   381  				fakePipeline     *dbfakes.FakePipeline
   382  				fakeResourceType *dbfakes.FakeResourceType
   383  			)
   384  
   385  			BeforeEach(func() {
   386  				plan.Check.ResourceType = "some-resource-type"
   387  
   388  				fakePipeline = new(dbfakes.FakePipeline)
   389  				fakeBuild.PipelineReturns(fakePipeline, true, nil)
   390  
   391  				fakeResourceType = new(dbfakes.FakeResourceType)
   392  				fakePipeline.ResourceTypeReturns(fakeResourceType, true, nil)
   393  			})
   394  
   395  			It("succeeds", func() {
   396  				Expect(pointErr).ToNot(HaveOccurred())
   397  			})
   398  
   399  			It("looks up the resource type on the pipeline", func() {
   400  				Expect(fakePipeline.ResourceTypeCallCount()).To(Equal(1))
   401  				resourceName := fakePipeline.ResourceTypeArgsForCall(0)
   402  				Expect(resourceName).To(Equal("some-resource-type"))
   403  			})
   404  
   405  			It("assigns the scope to the resource type", func() {
   406  				Expect(fakeResourceType.SetResourceConfigScopeCallCount()).To(Equal(1))
   407  
   408  				scope := fakeResourceType.SetResourceConfigScopeArgsForCall(0)
   409  				Expect(scope).To(Equal(fakeResourceConfigScope))
   410  			})
   411  
   412  			Context("when the pipeline is not found", func() {
   413  				BeforeEach(func() {
   414  					fakeBuild.PipelineReturns(nil, false, nil)
   415  				})
   416  
   417  				It("returns an error", func() {
   418  					Expect(pointErr).To(HaveOccurred())
   419  				})
   420  			})
   421  
   422  			Context("when the resource is not found", func() {
   423  				BeforeEach(func() {
   424  					fakePipeline.ResourceTypeReturns(nil, false, nil)
   425  				})
   426  
   427  				It("returns an error", func() {
   428  					Expect(pointErr).To(HaveOccurred())
   429  				})
   430  			})
   431  		})
   432  	})
   433  })