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

     1  package engine_test
     2  
     3  import (
     4  	"github.com/pf-qiu/concourse/v6/atc"
     5  	"github.com/pf-qiu/concourse/v6/atc/builds"
     6  	"github.com/pf-qiu/concourse/v6/atc/db"
     7  	"github.com/pf-qiu/concourse/v6/atc/db/dbfakes"
     8  	"github.com/pf-qiu/concourse/v6/atc/engine"
     9  	"github.com/pf-qiu/concourse/v6/atc/engine/enginefakes"
    10  	"github.com/pf-qiu/concourse/v6/atc/exec"
    11  	"github.com/pf-qiu/concourse/v6/atc/policy/policyfakes"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Builder", func() {
    17  
    18  	Describe("BuildStep", func() {
    19  
    20  		var (
    21  			err error
    22  
    23  			fakeCoreStepFactory *enginefakes.FakeCoreStepFactory
    24  			fakeRateLimiter     *enginefakes.FakeRateLimiter
    25  			fakePolicyChecker   *policyfakes.FakeChecker
    26  
    27  			planFactory    atc.PlanFactory
    28  			stepperFactory engine.StepperFactory
    29  		)
    30  
    31  		BeforeEach(func() {
    32  			fakeCoreStepFactory = new(enginefakes.FakeCoreStepFactory)
    33  			fakeRateLimiter = new(enginefakes.FakeRateLimiter)
    34  			fakePolicyChecker = new(policyfakes.FakeChecker)
    35  
    36  			stepperFactory = engine.NewStepperFactory(
    37  				fakeCoreStepFactory,
    38  				"http://example.com",
    39  				fakeRateLimiter,
    40  				fakePolicyChecker,
    41  			)
    42  
    43  			planFactory = atc.NewPlanFactory(123)
    44  		})
    45  
    46  		Context("with a build", func() {
    47  			var (
    48  				fakeBuild    *dbfakes.FakeBuild
    49  				fakePipeline *dbfakes.FakePipeline
    50  
    51  				expectedPlan     atc.Plan
    52  				expectedMetadata exec.StepMetadata
    53  			)
    54  
    55  			BeforeEach(func() {
    56  				fakePipeline = new(dbfakes.FakePipeline)
    57  				fakePipeline.IDReturns(2222)
    58  				fakePipeline.NameReturns("some-pipeline")
    59  				fakePipeline.InstanceVarsReturns(atc.InstanceVars{"branch": "master"})
    60  
    61  				fakeBuild = new(dbfakes.FakeBuild)
    62  				fakeBuild.IDReturns(4444)
    63  				fakeBuild.NameReturns("42")
    64  				fakeBuild.JobNameReturns("some-job")
    65  				fakeBuild.JobIDReturns(3333)
    66  				fakeBuild.PipelineIDReturns(fakePipeline.ID())
    67  				fakeBuild.PipelineNameReturns(fakePipeline.Name())
    68  				fakeBuild.PipelineInstanceVarsReturns(fakePipeline.InstanceVars())
    69  				fakeBuild.PipelineReturns(fakePipeline, true, nil)
    70  				fakeBuild.TeamNameReturns("some-team")
    71  				fakeBuild.TeamIDReturns(1111)
    72  
    73  				expectedMetadata = exec.StepMetadata{
    74  					BuildID:              4444,
    75  					BuildName:            "42",
    76  					TeamID:               1111,
    77  					TeamName:             "some-team",
    78  					JobID:                3333,
    79  					JobName:              "some-job",
    80  					PipelineID:           2222,
    81  					PipelineName:         "some-pipeline",
    82  					PipelineInstanceVars: atc.InstanceVars{"branch": "master"},
    83  					ExternalURL:          "http://example.com",
    84  				}
    85  			})
    86  
    87  			Context("when the build has the wrong schema", func() {
    88  				BeforeEach(func() {
    89  					fakeBuild.SchemaReturns("not-schema")
    90  				})
    91  
    92  				It("errors", func() {
    93  					_, err := stepperFactory.StepperForBuild(fakeBuild)
    94  					Expect(err).To(HaveOccurred())
    95  				})
    96  			})
    97  
    98  			Context("when the build has the right schema", func() {
    99  				BeforeEach(func() {
   100  					fakeBuild.SchemaReturns("exec.v2")
   101  				})
   102  
   103  				JustBeforeEach(func() {
   104  					fakeBuild.PrivatePlanReturns(expectedPlan)
   105  
   106  					stepper, err := stepperFactory.StepperForBuild(fakeBuild)
   107  					Expect(err).ToNot(HaveOccurred())
   108  
   109  					stepper(fakeBuild.PrivatePlan())
   110  				})
   111  
   112  				Context("with a putget in an aggregate", func() {
   113  					var (
   114  						putPlan               atc.Plan
   115  						dependentGetPlan      atc.Plan
   116  						otherPutPlan          atc.Plan
   117  						otherDependentGetPlan atc.Plan
   118  					)
   119  
   120  					BeforeEach(func() {
   121  						putPlan = planFactory.NewPlan(atc.PutPlan{
   122  							Name:     "some-put",
   123  							Resource: "some-output-resource",
   124  							Type:     "put",
   125  							Source:   atc.Source{"some": "source"},
   126  							Params:   atc.Params{"some": "params"},
   127  						})
   128  
   129  						otherPutPlan = planFactory.NewPlan(atc.PutPlan{
   130  							Name:     "some-put-2",
   131  							Resource: "some-output-resource-2",
   132  							Type:     "put",
   133  							Source:   atc.Source{"some": "source-2"},
   134  							Params:   atc.Params{"some": "params-2"},
   135  						})
   136  
   137  						expectedPlan = planFactory.NewPlan(atc.AggregatePlan{
   138  							planFactory.NewPlan(atc.OnSuccessPlan{
   139  								Step: putPlan,
   140  								Next: dependentGetPlan,
   141  							}),
   142  							planFactory.NewPlan(atc.OnSuccessPlan{
   143  								Step: otherPutPlan,
   144  								Next: otherDependentGetPlan,
   145  							}),
   146  						})
   147  					})
   148  
   149  					Context("constructing outputs", func() {
   150  						It("constructs the put correctly", func() {
   151  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.PutStepArgsForCall(0)
   152  							Expect(plan).To(Equal(putPlan))
   153  							Expect(stepMetadata).To(Equal(expectedMetadata))
   154  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   155  								Type:                 db.ContainerTypePut,
   156  								StepName:             "some-put",
   157  								PipelineID:           2222,
   158  								PipelineName:         "some-pipeline",
   159  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   160  								JobID:                3333,
   161  								JobName:              "some-job",
   162  								BuildID:              4444,
   163  								BuildName:            "42",
   164  							}))
   165  
   166  							plan, stepMetadata, containerMetadata, _ = fakeCoreStepFactory.PutStepArgsForCall(1)
   167  							Expect(plan).To(Equal(otherPutPlan))
   168  							Expect(stepMetadata).To(Equal(expectedMetadata))
   169  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   170  								Type:                 db.ContainerTypePut,
   171  								StepName:             "some-put-2",
   172  								PipelineID:           2222,
   173  								PipelineName:         "some-pipeline",
   174  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   175  								JobID:                3333,
   176  								JobName:              "some-job",
   177  								BuildID:              4444,
   178  								BuildName:            "42",
   179  							}))
   180  						})
   181  					})
   182  				})
   183  
   184  				Context("with a putget in a parallel", func() {
   185  					var (
   186  						putPlan               atc.Plan
   187  						dependentGetPlan      atc.Plan
   188  						otherPutPlan          atc.Plan
   189  						otherDependentGetPlan atc.Plan
   190  					)
   191  
   192  					BeforeEach(func() {
   193  						putPlan = planFactory.NewPlan(atc.PutPlan{
   194  							Name:     "some-put",
   195  							Resource: "some-output-resource",
   196  							Type:     "put",
   197  							Source:   atc.Source{"some": "source"},
   198  							Params:   atc.Params{"some": "params"},
   199  						})
   200  
   201  						otherPutPlan = planFactory.NewPlan(atc.PutPlan{
   202  							Name:     "some-put-2",
   203  							Resource: "some-output-resource-2",
   204  							Type:     "put",
   205  							Source:   atc.Source{"some": "source-2"},
   206  							Params:   atc.Params{"some": "params-2"},
   207  						})
   208  
   209  						expectedPlan = planFactory.NewPlan(atc.InParallelPlan{
   210  							Steps: []atc.Plan{
   211  								planFactory.NewPlan(atc.OnSuccessPlan{
   212  									Step: putPlan,
   213  									Next: dependentGetPlan,
   214  								}),
   215  								planFactory.NewPlan(atc.OnSuccessPlan{
   216  									Step: otherPutPlan,
   217  									Next: otherDependentGetPlan,
   218  								}),
   219  							},
   220  							Limit:    1,
   221  							FailFast: true,
   222  						})
   223  					})
   224  
   225  					Context("constructing outputs", func() {
   226  						It("constructs the put correctly", func() {
   227  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.PutStepArgsForCall(0)
   228  							Expect(plan).To(Equal(putPlan))
   229  							Expect(stepMetadata).To(Equal(expectedMetadata))
   230  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   231  								Type:                 db.ContainerTypePut,
   232  								StepName:             "some-put",
   233  								PipelineID:           2222,
   234  								PipelineName:         "some-pipeline",
   235  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   236  								JobID:                3333,
   237  								JobName:              "some-job",
   238  								BuildID:              4444,
   239  								BuildName:            "42",
   240  							}))
   241  
   242  							plan, stepMetadata, containerMetadata, _ = fakeCoreStepFactory.PutStepArgsForCall(1)
   243  							Expect(plan).To(Equal(otherPutPlan))
   244  							Expect(stepMetadata).To(Equal(expectedMetadata))
   245  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   246  								Type:                 db.ContainerTypePut,
   247  								StepName:             "some-put-2",
   248  								PipelineID:           2222,
   249  								PipelineName:         "some-pipeline",
   250  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   251  								JobID:                3333,
   252  								JobName:              "some-job",
   253  								BuildID:              4444,
   254  								BuildName:            "42",
   255  							}))
   256  						})
   257  					})
   258  				})
   259  
   260  				Context("with a retry plan", func() {
   261  					var (
   262  						getPlan       atc.Plan
   263  						taskPlan      atc.Plan
   264  						aggregatePlan atc.Plan
   265  						parallelPlan  atc.Plan
   266  						doPlan        atc.Plan
   267  						timeoutPlan   atc.Plan
   268  						retryPlanTwo  atc.Plan
   269  					)
   270  
   271  					BeforeEach(func() {
   272  						getPlan = planFactory.NewPlan(atc.GetPlan{
   273  							Name:     "some-get",
   274  							Resource: "some-input-resource",
   275  							Type:     "get",
   276  							Source:   atc.Source{"some": "source"},
   277  							Params:   atc.Params{"some": "params"},
   278  						})
   279  
   280  						taskPlan = planFactory.NewPlan(atc.TaskPlan{
   281  							Name:       "some-task",
   282  							Privileged: false,
   283  							Tags:       atc.Tags{"some", "task", "tags"},
   284  							ConfigPath: "some-config-path",
   285  						})
   286  
   287  						retryPlanTwo = planFactory.NewPlan(atc.RetryPlan{
   288  							taskPlan,
   289  							taskPlan,
   290  						})
   291  
   292  						aggregatePlan = planFactory.NewPlan(atc.AggregatePlan{retryPlanTwo})
   293  
   294  						parallelPlan = planFactory.NewPlan(atc.InParallelPlan{
   295  							Steps:    []atc.Plan{aggregatePlan},
   296  							Limit:    1,
   297  							FailFast: true,
   298  						})
   299  
   300  						doPlan = planFactory.NewPlan(atc.DoPlan{parallelPlan})
   301  
   302  						timeoutPlan = planFactory.NewPlan(atc.TimeoutPlan{
   303  							Step:     doPlan,
   304  							Duration: "1m",
   305  						})
   306  
   307  						expectedPlan = planFactory.NewPlan(atc.RetryPlan{
   308  							getPlan,
   309  							timeoutPlan,
   310  							getPlan,
   311  						})
   312  					})
   313  
   314  					It("constructs the retry correctly", func() {
   315  						Expect(*expectedPlan.Retry).To(HaveLen(3))
   316  					})
   317  
   318  					It("constructs the first get correctly", func() {
   319  						plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.GetStepArgsForCall(0)
   320  						expectedPlan := getPlan
   321  						expectedPlan.Attempts = []int{1}
   322  						Expect(plan).To(Equal(expectedPlan))
   323  						Expect(stepMetadata).To(Equal(expectedMetadata))
   324  						Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   325  							Type:                 db.ContainerTypeGet,
   326  							StepName:             "some-get",
   327  							PipelineID:           2222,
   328  							PipelineName:         "some-pipeline",
   329  							PipelineInstanceVars: "{\"branch\":\"master\"}",
   330  							JobID:                3333,
   331  							JobName:              "some-job",
   332  							BuildID:              4444,
   333  							BuildName:            "42",
   334  							Attempt:              "1",
   335  						}))
   336  					})
   337  
   338  					It("constructs the second get correctly", func() {
   339  						plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.GetStepArgsForCall(1)
   340  						expectedPlan := getPlan
   341  						expectedPlan.Attempts = []int{3}
   342  						Expect(plan).To(Equal(expectedPlan))
   343  						Expect(stepMetadata).To(Equal(expectedMetadata))
   344  						Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   345  							Type:                 db.ContainerTypeGet,
   346  							StepName:             "some-get",
   347  							PipelineID:           2222,
   348  							PipelineName:         "some-pipeline",
   349  							PipelineInstanceVars: "{\"branch\":\"master\"}",
   350  							JobID:                3333,
   351  							JobName:              "some-job",
   352  							BuildID:              4444,
   353  							BuildName:            "42",
   354  							Attempt:              "3",
   355  						}))
   356  					})
   357  
   358  					It("constructs nested retries correctly", func() {
   359  						Expect(*retryPlanTwo.Retry).To(HaveLen(2))
   360  					})
   361  
   362  					It("constructs nested steps correctly", func() {
   363  						plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(0)
   364  						expectedPlan := taskPlan
   365  						expectedPlan.Attempts = []int{2, 1}
   366  						Expect(plan).To(Equal(expectedPlan))
   367  						Expect(stepMetadata).To(Equal(expectedMetadata))
   368  						Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   369  							Type:                 db.ContainerTypeTask,
   370  							StepName:             "some-task",
   371  							PipelineID:           2222,
   372  							PipelineName:         "some-pipeline",
   373  							PipelineInstanceVars: "{\"branch\":\"master\"}",
   374  							JobID:                3333,
   375  							JobName:              "some-job",
   376  							BuildID:              4444,
   377  							BuildName:            "42",
   378  							Attempt:              "2.1",
   379  						}))
   380  
   381  						plan, stepMetadata, containerMetadata, _ = fakeCoreStepFactory.TaskStepArgsForCall(1)
   382  						expectedPlan = taskPlan
   383  						expectedPlan.Attempts = []int{2, 2}
   384  						Expect(plan).To(Equal(expectedPlan))
   385  						Expect(stepMetadata).To(Equal(expectedMetadata))
   386  						Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   387  							Type:                 db.ContainerTypeTask,
   388  							StepName:             "some-task",
   389  							PipelineID:           2222,
   390  							PipelineName:         "some-pipeline",
   391  							PipelineInstanceVars: "{\"branch\":\"master\"}",
   392  							JobID:                3333,
   393  							JobName:              "some-job",
   394  							BuildID:              4444,
   395  							BuildName:            "42",
   396  							Attempt:              "2.2",
   397  						}))
   398  					})
   399  				})
   400  
   401  				Context("with a plan where conditional steps are inside retries", func() {
   402  					var (
   403  						onAbortPlan   atc.Plan
   404  						onErrorPlan   atc.Plan
   405  						onSuccessPlan atc.Plan
   406  						onFailurePlan atc.Plan
   407  						ensurePlan    atc.Plan
   408  						leafPlan      atc.Plan
   409  					)
   410  
   411  					BeforeEach(func() {
   412  						leafPlan = planFactory.NewPlan(atc.TaskPlan{
   413  							Name:       "some-task",
   414  							Privileged: false,
   415  							Tags:       atc.Tags{"some", "task", "tags"},
   416  							ConfigPath: "some-config-path",
   417  						})
   418  
   419  						onAbortPlan = planFactory.NewPlan(atc.OnAbortPlan{
   420  							Step: leafPlan,
   421  							Next: leafPlan,
   422  						})
   423  
   424  						onErrorPlan = planFactory.NewPlan(atc.OnErrorPlan{
   425  							Step: onAbortPlan,
   426  							Next: leafPlan,
   427  						})
   428  
   429  						onSuccessPlan = planFactory.NewPlan(atc.OnSuccessPlan{
   430  							Step: onErrorPlan,
   431  							Next: leafPlan,
   432  						})
   433  
   434  						onFailurePlan = planFactory.NewPlan(atc.OnFailurePlan{
   435  							Step: onSuccessPlan,
   436  							Next: leafPlan,
   437  						})
   438  
   439  						ensurePlan = planFactory.NewPlan(atc.EnsurePlan{
   440  							Step: onFailurePlan,
   441  							Next: leafPlan,
   442  						})
   443  
   444  						expectedPlan = planFactory.NewPlan(atc.RetryPlan{
   445  							ensurePlan,
   446  						})
   447  					})
   448  
   449  					It("constructs nested steps correctly", func() {
   450  						Expect(fakeCoreStepFactory.TaskStepCallCount()).To(Equal(6))
   451  
   452  						_, _, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(0)
   453  						Expect(containerMetadata.Attempt).To(Equal("1"))
   454  						_, _, containerMetadata, _ = fakeCoreStepFactory.TaskStepArgsForCall(1)
   455  						Expect(containerMetadata.Attempt).To(Equal("1"))
   456  						_, _, containerMetadata, _ = fakeCoreStepFactory.TaskStepArgsForCall(2)
   457  						Expect(containerMetadata.Attempt).To(Equal("1"))
   458  						_, _, containerMetadata, _ = fakeCoreStepFactory.TaskStepArgsForCall(3)
   459  						Expect(containerMetadata.Attempt).To(Equal("1"))
   460  						_, _, containerMetadata, _ = fakeCoreStepFactory.TaskStepArgsForCall(4)
   461  						Expect(containerMetadata.Attempt).To(Equal("1"))
   462  					})
   463  				})
   464  
   465  				Context("with a basic plan", func() {
   466  
   467  					Context("that contains inputs", func() {
   468  						BeforeEach(func() {
   469  							expectedPlan = planFactory.NewPlan(atc.GetPlan{
   470  								Name:     "some-input",
   471  								Resource: "some-input-resource",
   472  								Type:     "get",
   473  								Tags:     []string{"some", "get", "tags"},
   474  								Version:  &atc.Version{"some": "version"},
   475  								Source:   atc.Source{"some": "source"},
   476  								Params:   atc.Params{"some": "params"},
   477  							})
   478  						})
   479  
   480  						It("constructs inputs correctly", func() {
   481  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.GetStepArgsForCall(0)
   482  							Expect(plan).To(Equal(expectedPlan))
   483  							Expect(stepMetadata).To(Equal(expectedMetadata))
   484  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   485  								Type:                 db.ContainerTypeGet,
   486  								StepName:             "some-input",
   487  								PipelineID:           2222,
   488  								PipelineName:         "some-pipeline",
   489  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   490  								JobID:                3333,
   491  								JobName:              "some-job",
   492  								BuildID:              4444,
   493  								BuildName:            "42",
   494  							}))
   495  						})
   496  					})
   497  
   498  					Context("that contains tasks", func() {
   499  						BeforeEach(func() {
   500  							expectedPlan = planFactory.NewPlan(atc.TaskPlan{
   501  								Name:          "some-task",
   502  								ConfigPath:    "some-input/build.yml",
   503  								InputMapping:  map[string]string{"foo": "bar"},
   504  								OutputMapping: map[string]string{"baz": "qux"},
   505  							})
   506  						})
   507  
   508  						It("constructs tasks correctly", func() {
   509  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(0)
   510  							Expect(plan).To(Equal(expectedPlan))
   511  							Expect(stepMetadata).To(Equal(expectedMetadata))
   512  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   513  								Type:                 db.ContainerTypeTask,
   514  								StepName:             "some-task",
   515  								PipelineID:           2222,
   516  								PipelineName:         "some-pipeline",
   517  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   518  								JobID:                3333,
   519  								JobName:              "some-job",
   520  								BuildID:              4444,
   521  								BuildName:            "42",
   522  							}))
   523  						})
   524  					})
   525  
   526  					Context("that contains a set_pipeline step", func() {
   527  						BeforeEach(func() {
   528  							expectedPlan = planFactory.NewPlan(atc.SetPipelinePlan{
   529  								Name:     "some-pipeline",
   530  								File:     "some-input/pipeline.yml",
   531  								VarFiles: []string{"foo", "bar"},
   532  								Vars:     map[string]interface{}{"baz": "qux"},
   533  							})
   534  						})
   535  
   536  						It("constructs set_pipeline correctly", func() {
   537  							plan, stepMetadata, _ := fakeCoreStepFactory.SetPipelineStepArgsForCall(0)
   538  							Expect(plan).To(Equal(expectedPlan))
   539  							Expect(stepMetadata).To(Equal(expectedMetadata))
   540  						})
   541  					})
   542  
   543  					Context("that contains a load_var step", func() {
   544  						BeforeEach(func() {
   545  							expectedPlan = planFactory.NewPlan(atc.LoadVarPlan{
   546  								Name: "some-var",
   547  								File: "some-input/data.yml",
   548  							})
   549  						})
   550  
   551  						It("constructs load_var correctly", func() {
   552  							plan, stepMetadata, _ := fakeCoreStepFactory.LoadVarStepArgsForCall(0)
   553  							Expect(plan).To(Equal(expectedPlan))
   554  							Expect(stepMetadata).To(Equal(expectedMetadata))
   555  						})
   556  					})
   557  
   558  					Context("that contains a check step", func() {
   559  						BeforeEach(func() {
   560  							expectedPlan = planFactory.NewPlan(atc.CheckPlan{
   561  								Name: "some-check",
   562  							})
   563  						})
   564  
   565  						It("constructs the step correctly", func() {
   566  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.CheckStepArgsForCall(0)
   567  							Expect(plan).To(Equal(expectedPlan))
   568  							Expect(stepMetadata).To(Equal(expectedMetadata))
   569  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   570  								Type:                 db.ContainerTypeCheck,
   571  								StepName:             "some-check",
   572  								PipelineID:           2222,
   573  								PipelineName:         "some-pipeline",
   574  								PipelineInstanceVars: `{"branch":"master"}`,
   575  								JobID:                3333,
   576  								JobName:              "some-job",
   577  								BuildID:              4444,
   578  								BuildName:            "42",
   579  							}))
   580  						})
   581  					})
   582  
   583  					Context("that contains outputs", func() {
   584  						var (
   585  							putPlan          atc.Plan
   586  							dependentGetPlan atc.Plan
   587  						)
   588  
   589  						BeforeEach(func() {
   590  							putPlan = planFactory.NewPlan(atc.PutPlan{
   591  								Name:     "some-put",
   592  								Resource: "some-output-resource",
   593  								Tags:     []string{"some", "putget", "tags"},
   594  								Type:     "put",
   595  								Source:   atc.Source{"some": "source"},
   596  								Params:   atc.Params{"some": "params"},
   597  							})
   598  
   599  							dependentGetPlan = planFactory.NewPlan(atc.GetPlan{
   600  								Name:        "some-get",
   601  								Resource:    "some-input-resource",
   602  								Tags:        []string{"some", "putget", "tags"},
   603  								Type:        "get",
   604  								VersionFrom: &putPlan.ID,
   605  								Source:      atc.Source{"some": "source"},
   606  								Params:      atc.Params{"another": "params"},
   607  							})
   608  
   609  							expectedPlan = planFactory.NewPlan(atc.OnSuccessPlan{
   610  								Step: putPlan,
   611  								Next: dependentGetPlan,
   612  							})
   613  						})
   614  
   615  						It("constructs the put correctly", func() {
   616  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.PutStepArgsForCall(0)
   617  							Expect(plan).To(Equal(putPlan))
   618  							Expect(stepMetadata).To(Equal(expectedMetadata))
   619  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   620  								Type:                 db.ContainerTypePut,
   621  								StepName:             "some-put",
   622  								PipelineID:           2222,
   623  								PipelineName:         "some-pipeline",
   624  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   625  								JobID:                3333,
   626  								JobName:              "some-job",
   627  								BuildID:              4444,
   628  								BuildName:            "42",
   629  							}))
   630  						})
   631  
   632  						It("constructs the dependent get correctly", func() {
   633  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.GetStepArgsForCall(0)
   634  							Expect(plan).To(Equal(dependentGetPlan))
   635  							Expect(stepMetadata).To(Equal(expectedMetadata))
   636  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   637  								Type:                 db.ContainerTypeGet,
   638  								StepName:             "some-get",
   639  								PipelineID:           2222,
   640  								PipelineName:         "some-pipeline",
   641  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   642  								JobID:                3333,
   643  								JobName:              "some-job",
   644  								BuildID:              4444,
   645  								BuildName:            "42",
   646  							}))
   647  						})
   648  					})
   649  				})
   650  
   651  				Context("running hooked composes", func() {
   652  					Context("with all the hooks", func() {
   653  						var (
   654  							inputPlan          atc.Plan
   655  							failureTaskPlan    atc.Plan
   656  							successTaskPlan    atc.Plan
   657  							completionTaskPlan atc.Plan
   658  							nextTaskPlan       atc.Plan
   659  						)
   660  
   661  						BeforeEach(func() {
   662  							inputPlan = planFactory.NewPlan(atc.GetPlan{
   663  								Name: "some-input",
   664  							})
   665  							failureTaskPlan = planFactory.NewPlan(atc.TaskPlan{
   666  								Name:   "some-failure-task",
   667  								Config: &atc.TaskConfig{},
   668  							})
   669  							successTaskPlan = planFactory.NewPlan(atc.TaskPlan{
   670  								Name:   "some-success-task",
   671  								Config: &atc.TaskConfig{},
   672  							})
   673  							completionTaskPlan = planFactory.NewPlan(atc.TaskPlan{
   674  								Name:   "some-completion-task",
   675  								Config: &atc.TaskConfig{},
   676  							})
   677  							nextTaskPlan = planFactory.NewPlan(atc.TaskPlan{
   678  								Name:   "some-next-task",
   679  								Config: &atc.TaskConfig{},
   680  							})
   681  
   682  							expectedPlan = planFactory.NewPlan(atc.OnSuccessPlan{
   683  								Step: planFactory.NewPlan(atc.EnsurePlan{
   684  									Step: planFactory.NewPlan(atc.OnSuccessPlan{
   685  										Step: planFactory.NewPlan(atc.OnFailurePlan{
   686  											Step: inputPlan,
   687  											Next: failureTaskPlan,
   688  										}),
   689  										Next: successTaskPlan,
   690  									}),
   691  									Next: completionTaskPlan,
   692  								}),
   693  								Next: nextTaskPlan,
   694  							})
   695  						})
   696  
   697  						It("constructs the step correctly", func() {
   698  							Expect(fakeCoreStepFactory.GetStepCallCount()).To(Equal(1))
   699  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.GetStepArgsForCall(0)
   700  							Expect(plan).To(Equal(inputPlan))
   701  							Expect(stepMetadata).To(Equal(expectedMetadata))
   702  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   703  								PipelineID:           2222,
   704  								PipelineName:         "some-pipeline",
   705  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   706  								JobID:                3333,
   707  								JobName:              "some-job",
   708  								BuildID:              4444,
   709  								BuildName:            "42",
   710  								StepName:             "some-input",
   711  								Type:                 db.ContainerTypeGet,
   712  							}))
   713  						})
   714  
   715  						It("constructs the completion hook correctly", func() {
   716  							Expect(fakeCoreStepFactory.TaskStepCallCount()).To(Equal(4))
   717  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(2)
   718  							Expect(plan).To(Equal(completionTaskPlan))
   719  							Expect(stepMetadata).To(Equal(expectedMetadata))
   720  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   721  								PipelineID:           2222,
   722  								PipelineName:         "some-pipeline",
   723  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   724  								JobID:                3333,
   725  								JobName:              "some-job",
   726  								BuildID:              4444,
   727  								BuildName:            "42",
   728  								StepName:             "some-completion-task",
   729  								Type:                 db.ContainerTypeTask,
   730  							}))
   731  						})
   732  
   733  						It("constructs the failure hook correctly", func() {
   734  							Expect(fakeCoreStepFactory.TaskStepCallCount()).To(Equal(4))
   735  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(0)
   736  							Expect(plan).To(Equal(failureTaskPlan))
   737  							Expect(stepMetadata).To(Equal(expectedMetadata))
   738  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   739  								PipelineID:           2222,
   740  								PipelineName:         "some-pipeline",
   741  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   742  								JobID:                3333,
   743  								JobName:              "some-job",
   744  								BuildID:              4444,
   745  								BuildName:            "42",
   746  								StepName:             "some-failure-task",
   747  								Type:                 db.ContainerTypeTask,
   748  							}))
   749  						})
   750  
   751  						It("constructs the success hook correctly", func() {
   752  							Expect(fakeCoreStepFactory.TaskStepCallCount()).To(Equal(4))
   753  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(1)
   754  							Expect(plan).To(Equal(successTaskPlan))
   755  							Expect(stepMetadata).To(Equal(expectedMetadata))
   756  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   757  								PipelineID:           2222,
   758  								PipelineName:         "some-pipeline",
   759  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   760  								JobID:                3333,
   761  								JobName:              "some-job",
   762  								BuildID:              4444,
   763  								BuildName:            "42",
   764  								StepName:             "some-success-task",
   765  								Type:                 db.ContainerTypeTask,
   766  							}))
   767  						})
   768  
   769  						It("constructs the next step correctly", func() {
   770  							Expect(fakeCoreStepFactory.TaskStepCallCount()).To(Equal(4))
   771  							plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(3)
   772  							Expect(plan).To(Equal(nextTaskPlan))
   773  							Expect(stepMetadata).To(Equal(expectedMetadata))
   774  							Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   775  								PipelineID:           2222,
   776  								PipelineName:         "some-pipeline",
   777  								PipelineInstanceVars: "{\"branch\":\"master\"}",
   778  								JobID:                3333,
   779  								JobName:              "some-job",
   780  								BuildID:              4444,
   781  								BuildName:            "42",
   782  								StepName:             "some-next-task",
   783  								Type:                 db.ContainerTypeTask,
   784  							}))
   785  						})
   786  					})
   787  				})
   788  
   789  				Context("running try steps", func() {
   790  					var inputPlan atc.Plan
   791  
   792  					BeforeEach(func() {
   793  						inputPlan = planFactory.NewPlan(atc.GetPlan{
   794  							Name: "some-input",
   795  						})
   796  
   797  						expectedPlan = planFactory.NewPlan(atc.TryPlan{
   798  							Step: inputPlan,
   799  						})
   800  					})
   801  
   802  					It("constructs the step correctly", func() {
   803  						Expect(fakeCoreStepFactory.GetStepCallCount()).To(Equal(1))
   804  						plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.GetStepArgsForCall(0)
   805  						Expect(plan).To(Equal(inputPlan))
   806  						Expect(stepMetadata).To(Equal(expectedMetadata))
   807  						Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   808  							Type:                 db.ContainerTypeGet,
   809  							StepName:             "some-input",
   810  							PipelineID:           2222,
   811  							PipelineName:         "some-pipeline",
   812  							PipelineInstanceVars: "{\"branch\":\"master\"}",
   813  							JobID:                3333,
   814  							JobName:              "some-job",
   815  							BuildID:              4444,
   816  							BuildName:            "42",
   817  						}))
   818  					})
   819  				})
   820  
   821  				Context("running across steps", func() {
   822  					BeforeEach(func() {
   823  						planner := builds.NewPlanner(planFactory)
   824  
   825  						step := &atc.AcrossStep{
   826  							Step: &atc.TaskStep{Name: "some-task"},
   827  							Vars: []atc.AcrossVarConfig{
   828  								{
   829  									Var:    "var1",
   830  									Values: []interface{}{"a1", "a2"},
   831  								},
   832  								{
   833  									Var:    "var2",
   834  									Values: []interface{}{"b1", "b2"},
   835  								},
   836  								{
   837  									Var:    "var3",
   838  									Values: []interface{}{"c1"},
   839  								},
   840  							},
   841  						}
   842  
   843  						expectedPlan, err = planner.Create(step, nil, nil, nil)
   844  						Expect(err).ToNot(HaveOccurred())
   845  					})
   846  
   847  					It("constructs the steps correctly", func() {
   848  						Expect(fakeCoreStepFactory.TaskStepCallCount()).To(Equal(4))
   849  						plan, stepMetadata, containerMetadata, _ := fakeCoreStepFactory.TaskStepArgsForCall(0)
   850  						Expect(*plan.Task).To(Equal(atc.TaskPlan{Name: "some-task"}))
   851  						Expect(stepMetadata).To(Equal(expectedMetadata))
   852  						Expect(containerMetadata).To(Equal(db.ContainerMetadata{
   853  							Type:                 db.ContainerTypeTask,
   854  							StepName:             "some-task",
   855  							PipelineID:           2222,
   856  							PipelineName:         "some-pipeline",
   857  							PipelineInstanceVars: "{\"branch\":\"master\"}",
   858  							JobID:                3333,
   859  							JobName:              "some-job",
   860  							BuildID:              4444,
   861  							BuildName:            "42",
   862  						}))
   863  					})
   864  				})
   865  			})
   866  		})
   867  	})
   868  })