434 lines
8.6 KiB
Go
434 lines
8.6 KiB
Go
package builds
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/concourse/concourse/atc"
|
|
"github.com/concourse/concourse/atc/db"
|
|
)
|
|
|
|
type Planner struct {
|
|
planFactory atc.PlanFactory
|
|
}
|
|
|
|
func NewPlanner(planFactory atc.PlanFactory) Planner {
|
|
return Planner{
|
|
planFactory: planFactory,
|
|
}
|
|
}
|
|
|
|
func (planner Planner) Create(
|
|
planConfig atc.StepConfig,
|
|
resources db.SchedulerResources,
|
|
resourceTypes atc.VersionedResourceTypes,
|
|
prototypes atc.Prototypes,
|
|
inputs []db.BuildInput,
|
|
) (atc.Plan, error) {
|
|
visitor := &planVisitor{
|
|
planFactory: planner.planFactory,
|
|
|
|
resources: resources,
|
|
resourceTypes: resourceTypes,
|
|
prototypes: prototypes,
|
|
inputs: inputs,
|
|
}
|
|
|
|
err := planConfig.Visit(visitor)
|
|
if err != nil {
|
|
return atc.Plan{}, err
|
|
}
|
|
|
|
return visitor.plan, nil
|
|
}
|
|
|
|
type planVisitor struct {
|
|
planFactory atc.PlanFactory
|
|
|
|
resources db.SchedulerResources
|
|
resourceTypes atc.VersionedResourceTypes
|
|
prototypes atc.Prototypes
|
|
inputs []db.BuildInput
|
|
|
|
plan atc.Plan
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitTask(step *atc.TaskStep) error {
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.TaskPlan{
|
|
Name: step.Name,
|
|
Privileged: step.Privileged,
|
|
Config: step.Config,
|
|
Limits: step.Limits,
|
|
ConfigPath: step.ConfigPath,
|
|
Vars: step.Vars,
|
|
Tags: step.Tags,
|
|
Params: step.Params,
|
|
InputMapping: step.InputMapping,
|
|
OutputMapping: step.OutputMapping,
|
|
ImageArtifactName: step.ImageArtifactName,
|
|
Timeout: step.Timeout,
|
|
|
|
VersionedResourceTypes: visitor.resourceTypes,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitRun(step *atc.RunStep) error {
|
|
prototype, found := visitor.prototypes.Lookup(step.Type)
|
|
if !found {
|
|
return UnknownPrototypeError{step.Type}
|
|
}
|
|
|
|
object := prototype.Defaults.Merge(atc.Source(step.Params))
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.RunPlan{
|
|
Message: step.Message,
|
|
Type: step.Type,
|
|
Object: atc.Params(object),
|
|
Privileged: step.Privileged,
|
|
Tags: step.Tags,
|
|
Limits: step.Limits,
|
|
Timeout: step.Timeout,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitGet(step *atc.GetStep) error {
|
|
resourceName := step.Resource
|
|
if resourceName == "" {
|
|
resourceName = step.Name
|
|
}
|
|
|
|
resource, found := visitor.resources.Lookup(resourceName)
|
|
if !found {
|
|
return UnknownResourceError{resourceName}
|
|
}
|
|
|
|
var version atc.Version
|
|
for _, input := range visitor.inputs {
|
|
if input.Name == step.Name {
|
|
version = atc.Version(input.Version)
|
|
break
|
|
}
|
|
}
|
|
|
|
if version == nil {
|
|
return VersionNotProvidedError{step.Name}
|
|
}
|
|
|
|
resource.ApplySourceDefaults(visitor.resourceTypes)
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.GetPlan{
|
|
Name: step.Name,
|
|
|
|
Type: resource.Type,
|
|
Resource: resourceName,
|
|
Source: resource.Source,
|
|
Params: step.Params,
|
|
Version: &version,
|
|
Tags: step.Tags,
|
|
Timeout: step.Timeout,
|
|
|
|
VersionedResourceTypes: visitor.resourceTypes,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitPut(step *atc.PutStep) error {
|
|
logicalName := step.Name
|
|
|
|
resourceName := step.Resource
|
|
if resourceName == "" {
|
|
resourceName = logicalName
|
|
}
|
|
|
|
resource, found := visitor.resources.Lookup(resourceName)
|
|
if !found {
|
|
return UnknownResourceError{resourceName}
|
|
}
|
|
|
|
resource.ApplySourceDefaults(visitor.resourceTypes)
|
|
|
|
atcPutPlan := atc.PutPlan{
|
|
Name: logicalName,
|
|
Resource: resourceName,
|
|
Type: resource.Type,
|
|
Source: resource.Source,
|
|
Params: step.Params,
|
|
ExposeBuildCreatedBy: resource.ExposeBuildCreatedBy,
|
|
|
|
Inputs: step.Inputs,
|
|
|
|
Tags: step.Tags,
|
|
Timeout: step.Timeout,
|
|
|
|
VersionedResourceTypes: visitor.resourceTypes,
|
|
}
|
|
|
|
putPlan := visitor.planFactory.NewPlan(atcPutPlan)
|
|
|
|
dependentGetPlan := visitor.planFactory.NewPlan(atc.GetPlan{
|
|
Name: logicalName,
|
|
Resource: resourceName,
|
|
Type: resource.Type,
|
|
Source: resource.Source,
|
|
Params: step.GetParams,
|
|
VersionFrom: &putPlan.ID,
|
|
|
|
Tags: step.Tags,
|
|
Timeout: step.Timeout,
|
|
|
|
VersionedResourceTypes: visitor.resourceTypes,
|
|
})
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.OnSuccessPlan{
|
|
Step: putPlan,
|
|
Next: dependentGetPlan,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitDo(step *atc.DoStep) error {
|
|
do := atc.DoPlan{}
|
|
|
|
for _, step := range step.Steps {
|
|
err := step.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
do = append(do, visitor.plan)
|
|
}
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(do)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitInParallel(step *atc.InParallelStep) error {
|
|
var steps []atc.Plan
|
|
|
|
for _, sub := range step.Config.Steps {
|
|
err := sub.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
steps = append(steps, visitor.plan)
|
|
}
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.InParallelPlan{
|
|
Steps: steps,
|
|
Limit: step.Config.Limit,
|
|
FailFast: step.Config.FailFast,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitAcross(step *atc.AcrossStep) error {
|
|
vars := make([]atc.AcrossVar, len(step.Vars))
|
|
for i, v := range step.Vars {
|
|
vars[i] = atc.AcrossVar(v)
|
|
}
|
|
|
|
if err := step.Step.Visit(visitor); err != nil {
|
|
return err
|
|
}
|
|
|
|
template, err := json.Marshal(visitor.plan)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
acrossPlan := atc.AcrossPlan{
|
|
Vars: vars,
|
|
SubStepTemplate: string(template),
|
|
FailFast: step.FailFast,
|
|
}
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(acrossPlan)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitSetPipeline(step *atc.SetPipelineStep) error {
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.SetPipelinePlan{
|
|
Name: step.Name,
|
|
File: step.File,
|
|
Team: step.Team,
|
|
Vars: step.Vars,
|
|
VarFiles: step.VarFiles,
|
|
InstanceVars: step.InstanceVars,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitLoadVar(step *atc.LoadVarStep) error {
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.LoadVarPlan{
|
|
Name: step.Name,
|
|
File: step.File,
|
|
Format: step.Format,
|
|
Reveal: step.Reveal,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitTry(step *atc.TryStep) error {
|
|
err := step.Step.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.TryPlan{
|
|
Step: visitor.plan,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitTimeout(step *atc.TimeoutStep) error {
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(atc.TimeoutPlan{
|
|
Duration: step.Duration,
|
|
Step: visitor.plan,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitRetry(step *atc.RetryStep) error {
|
|
retryStep := make(atc.RetryPlan, step.Attempts)
|
|
|
|
for i := 0; i < step.Attempts; i++ {
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
retryStep[i] = visitor.plan
|
|
}
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(retryStep)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitOnSuccess(step *atc.OnSuccessStep) error {
|
|
plan := atc.OnSuccessPlan{}
|
|
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Step = visitor.plan
|
|
|
|
err = step.Hook.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Next = visitor.plan
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(plan)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitOnFailure(step *atc.OnFailureStep) error {
|
|
plan := atc.OnFailurePlan{}
|
|
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Step = visitor.plan
|
|
|
|
err = step.Hook.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Next = visitor.plan
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(plan)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitOnAbort(step *atc.OnAbortStep) error {
|
|
plan := atc.OnAbortPlan{}
|
|
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Step = visitor.plan
|
|
|
|
err = step.Hook.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Next = visitor.plan
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(plan)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (visitor *planVisitor) VisitOnError(step *atc.OnErrorStep) error {
|
|
plan := atc.OnErrorPlan{}
|
|
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Step = visitor.plan
|
|
|
|
err = step.Hook.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Next = visitor.plan
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(plan)
|
|
|
|
return nil
|
|
}
|
|
func (visitor *planVisitor) VisitEnsure(step *atc.EnsureStep) error {
|
|
plan := atc.EnsurePlan{}
|
|
|
|
err := step.Step.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Step = visitor.plan
|
|
|
|
err = step.Hook.Config.Visit(visitor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
plan.Next = visitor.plan
|
|
|
|
visitor.plan = visitor.planFactory.NewPlan(plan)
|
|
|
|
return nil
|
|
}
|