github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/builds/planner.go (about) 1 package builds 2 3 import ( 4 "github.com/pf-qiu/concourse/v6/atc" 5 "github.com/pf-qiu/concourse/v6/atc/db" 6 ) 7 8 type Planner struct { 9 planFactory atc.PlanFactory 10 } 11 12 func NewPlanner(planFactory atc.PlanFactory) Planner { 13 return Planner{ 14 planFactory: planFactory, 15 } 16 } 17 18 func (planner Planner) Create( 19 planConfig atc.StepConfig, 20 resources db.SchedulerResources, 21 resourceTypes atc.VersionedResourceTypes, 22 inputs []db.BuildInput, 23 ) (atc.Plan, error) { 24 visitor := &planVisitor{ 25 planFactory: planner.planFactory, 26 27 resources: resources, 28 resourceTypes: resourceTypes, 29 inputs: inputs, 30 } 31 32 err := planConfig.Visit(visitor) 33 if err != nil { 34 return atc.Plan{}, err 35 } 36 37 return visitor.plan, nil 38 } 39 40 type planVisitor struct { 41 planFactory atc.PlanFactory 42 43 resources db.SchedulerResources 44 resourceTypes atc.VersionedResourceTypes 45 inputs []db.BuildInput 46 47 plan atc.Plan 48 } 49 50 func (visitor *planVisitor) VisitTask(step *atc.TaskStep) error { 51 visitor.plan = visitor.planFactory.NewPlan(atc.TaskPlan{ 52 Name: step.Name, 53 Privileged: step.Privileged, 54 Config: step.Config, 55 ConfigPath: step.ConfigPath, 56 Vars: step.Vars, 57 Tags: step.Tags, 58 Params: step.Params, 59 InputMapping: step.InputMapping, 60 OutputMapping: step.OutputMapping, 61 ImageArtifactName: step.ImageArtifactName, 62 63 VersionedResourceTypes: visitor.resourceTypes, 64 }) 65 66 return nil 67 } 68 69 func (visitor *planVisitor) VisitGet(step *atc.GetStep) error { 70 resourceName := step.Resource 71 if resourceName == "" { 72 resourceName = step.Name 73 } 74 75 resource, found := visitor.resources.Lookup(resourceName) 76 if !found { 77 return UnknownResourceError{resourceName} 78 } 79 80 var version atc.Version 81 for _, input := range visitor.inputs { 82 if input.Name == step.Name { 83 version = atc.Version(input.Version) 84 break 85 } 86 } 87 88 if version == nil { 89 return VersionNotProvidedError{step.Name} 90 } 91 92 resource.ApplySourceDefaults(visitor.resourceTypes) 93 94 visitor.plan = visitor.planFactory.NewPlan(atc.GetPlan{ 95 Name: step.Name, 96 97 Type: resource.Type, 98 Resource: resourceName, 99 Source: resource.Source, 100 Params: step.Params, 101 Version: &version, 102 Tags: step.Tags, 103 104 VersionedResourceTypes: visitor.resourceTypes, 105 }) 106 107 return nil 108 } 109 110 func (visitor *planVisitor) VisitPut(step *atc.PutStep) error { 111 logicalName := step.Name 112 113 resourceName := step.Resource 114 if resourceName == "" { 115 resourceName = logicalName 116 } 117 118 resource, found := visitor.resources.Lookup(resourceName) 119 if !found { 120 return UnknownResourceError{resourceName} 121 } 122 123 resource.ApplySourceDefaults(visitor.resourceTypes) 124 125 atcPutPlan := atc.PutPlan{ 126 Type: resource.Type, 127 Name: logicalName, 128 Resource: resourceName, 129 Source: resource.Source, 130 Params: step.Params, 131 Tags: step.Tags, 132 Inputs: step.Inputs, 133 134 VersionedResourceTypes: visitor.resourceTypes, 135 } 136 137 putPlan := visitor.planFactory.NewPlan(atcPutPlan) 138 139 dependentGetPlan := visitor.planFactory.NewPlan(atc.GetPlan{ 140 Type: resource.Type, 141 Name: logicalName, 142 Resource: resourceName, 143 VersionFrom: &putPlan.ID, 144 145 Params: step.GetParams, 146 Tags: step.Tags, 147 Source: resource.Source, 148 149 VersionedResourceTypes: visitor.resourceTypes, 150 }) 151 152 visitor.plan = visitor.planFactory.NewPlan(atc.OnSuccessPlan{ 153 Step: putPlan, 154 Next: dependentGetPlan, 155 }) 156 157 return nil 158 } 159 160 func (visitor *planVisitor) VisitDo(step *atc.DoStep) error { 161 do := atc.DoPlan{} 162 163 for _, step := range step.Steps { 164 err := step.Config.Visit(visitor) 165 if err != nil { 166 return err 167 } 168 169 do = append(do, visitor.plan) 170 } 171 172 visitor.plan = visitor.planFactory.NewPlan(do) 173 174 return nil 175 } 176 177 func (visitor *planVisitor) VisitAggregate(step *atc.AggregateStep) error { 178 do := atc.AggregatePlan{} 179 180 for _, sub := range step.Steps { 181 err := sub.Config.Visit(visitor) 182 if err != nil { 183 return err 184 } 185 186 do = append(do, visitor.plan) 187 } 188 189 visitor.plan = visitor.planFactory.NewPlan(do) 190 191 return nil 192 } 193 194 func (visitor *planVisitor) VisitInParallel(step *atc.InParallelStep) error { 195 var steps []atc.Plan 196 197 for _, sub := range step.Config.Steps { 198 err := sub.Config.Visit(visitor) 199 if err != nil { 200 return err 201 } 202 203 steps = append(steps, visitor.plan) 204 } 205 206 visitor.plan = visitor.planFactory.NewPlan(atc.InParallelPlan{ 207 Steps: steps, 208 Limit: step.Config.Limit, 209 FailFast: step.Config.FailFast, 210 }) 211 212 return nil 213 } 214 215 func (visitor *planVisitor) VisitAcross(step *atc.AcrossStep) error { 216 vars := make([]atc.AcrossVar, len(step.Vars)) 217 for i, v := range step.Vars { 218 vars[i] = atc.AcrossVar{ 219 Var: v.Var, 220 Values: v.Values, 221 MaxInFlight: v.MaxInFlight, 222 } 223 } 224 225 acrossPlan := atc.AcrossPlan{ 226 Vars: vars, 227 Steps: []atc.VarScopedPlan{}, 228 FailFast: step.FailFast, 229 } 230 for _, vals := range cartesianProduct(step.Vars) { 231 err := step.Step.Visit(visitor) 232 if err != nil { 233 return err 234 } 235 acrossPlan.Steps = append(acrossPlan.Steps, atc.VarScopedPlan{ 236 Step: visitor.plan, 237 Values: vals, 238 }) 239 } 240 241 visitor.plan = visitor.planFactory.NewPlan(acrossPlan) 242 243 return nil 244 } 245 246 func cartesianProduct(vars []atc.AcrossVarConfig) [][]interface{} { 247 if len(vars) == 0 { 248 return make([][]interface{}, 1) 249 } 250 var product [][]interface{} 251 subProduct := cartesianProduct(vars[:len(vars)-1]) 252 for _, vec := range subProduct { 253 for _, val := range vars[len(vars)-1].Values { 254 product = append(product, append(vec, val)) 255 } 256 } 257 return product 258 } 259 260 func (visitor *planVisitor) VisitSetPipeline(step *atc.SetPipelineStep) error { 261 visitor.plan = visitor.planFactory.NewPlan(atc.SetPipelinePlan{ 262 Name: step.Name, 263 File: step.File, 264 Team: step.Team, 265 Vars: step.Vars, 266 VarFiles: step.VarFiles, 267 InstanceVars: step.InstanceVars, 268 }) 269 270 return nil 271 } 272 273 func (visitor *planVisitor) VisitLoadVar(step *atc.LoadVarStep) error { 274 visitor.plan = visitor.planFactory.NewPlan(atc.LoadVarPlan{ 275 Name: step.Name, 276 File: step.File, 277 Format: step.Format, 278 Reveal: step.Reveal, 279 }) 280 281 return nil 282 } 283 284 func (visitor *planVisitor) VisitTry(step *atc.TryStep) error { 285 err := step.Step.Config.Visit(visitor) 286 if err != nil { 287 return err 288 } 289 290 visitor.plan = visitor.planFactory.NewPlan(atc.TryPlan{ 291 Step: visitor.plan, 292 }) 293 294 return nil 295 } 296 297 func (visitor *planVisitor) VisitTimeout(step *atc.TimeoutStep) error { 298 err := step.Step.Visit(visitor) 299 if err != nil { 300 return err 301 } 302 303 visitor.plan = visitor.planFactory.NewPlan(atc.TimeoutPlan{ 304 Duration: step.Duration, 305 Step: visitor.plan, 306 }) 307 308 return nil 309 } 310 311 func (visitor *planVisitor) VisitRetry(step *atc.RetryStep) error { 312 retryStep := make(atc.RetryPlan, step.Attempts) 313 314 for i := 0; i < step.Attempts; i++ { 315 err := step.Step.Visit(visitor) 316 if err != nil { 317 return err 318 } 319 320 retryStep[i] = visitor.plan 321 } 322 323 visitor.plan = visitor.planFactory.NewPlan(retryStep) 324 325 return nil 326 } 327 328 func (visitor *planVisitor) VisitOnSuccess(step *atc.OnSuccessStep) error { 329 plan := atc.OnSuccessPlan{} 330 331 err := step.Step.Visit(visitor) 332 if err != nil { 333 return err 334 } 335 336 plan.Step = visitor.plan 337 338 err = step.Hook.Config.Visit(visitor) 339 if err != nil { 340 return err 341 } 342 343 plan.Next = visitor.plan 344 345 visitor.plan = visitor.planFactory.NewPlan(plan) 346 347 return nil 348 } 349 350 func (visitor *planVisitor) VisitOnFailure(step *atc.OnFailureStep) error { 351 plan := atc.OnFailurePlan{} 352 353 err := step.Step.Visit(visitor) 354 if err != nil { 355 return err 356 } 357 358 plan.Step = visitor.plan 359 360 err = step.Hook.Config.Visit(visitor) 361 if err != nil { 362 return err 363 } 364 365 plan.Next = visitor.plan 366 367 visitor.plan = visitor.planFactory.NewPlan(plan) 368 369 return nil 370 } 371 372 func (visitor *planVisitor) VisitOnAbort(step *atc.OnAbortStep) error { 373 plan := atc.OnAbortPlan{} 374 375 err := step.Step.Visit(visitor) 376 if err != nil { 377 return err 378 } 379 380 plan.Step = visitor.plan 381 382 err = step.Hook.Config.Visit(visitor) 383 if err != nil { 384 return err 385 } 386 387 plan.Next = visitor.plan 388 389 visitor.plan = visitor.planFactory.NewPlan(plan) 390 391 return nil 392 } 393 394 func (visitor *planVisitor) VisitOnError(step *atc.OnErrorStep) error { 395 plan := atc.OnErrorPlan{} 396 397 err := step.Step.Visit(visitor) 398 if err != nil { 399 return err 400 } 401 402 plan.Step = visitor.plan 403 404 err = step.Hook.Config.Visit(visitor) 405 if err != nil { 406 return err 407 } 408 409 plan.Next = visitor.plan 410 411 visitor.plan = visitor.planFactory.NewPlan(plan) 412 413 return nil 414 } 415 func (visitor *planVisitor) VisitEnsure(step *atc.EnsureStep) error { 416 plan := atc.EnsurePlan{} 417 418 err := step.Step.Visit(visitor) 419 if err != nil { 420 return err 421 } 422 423 plan.Step = visitor.plan 424 425 err = step.Hook.Config.Visit(visitor) 426 if err != nil { 427 return err 428 } 429 430 plan.Next = visitor.plan 431 432 visitor.plan = visitor.planFactory.NewPlan(plan) 433 434 return nil 435 }