func populatePlanLocations(planConfig *atc.PlanConfig, location *atc.Location) uint { var stepCount uint var parentID uint parentID = location.ID switch { case planConfig.Put != "": planConfig.Location = location // offset by one for the dependent get that will be added stepCount = stepCount + 1 case planConfig.Do != nil: children := *planConfig.Do parentID = location.ID + 1 for i := 0; i < len(children); i++ { child := children[i] childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: location.ParentID, ParallelGroup: 0, Hook: location.Hook, } stepCount = stepCount + populatePlanLocations(&child, childLocation) children[i] = child } case planConfig.Try != nil: childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: location.ParentID, ParallelGroup: 0, Hook: location.Hook, } stepCount = stepCount + populatePlanLocations(planConfig.Try, childLocation) case planConfig.Aggregate != nil: parallelGroup := location.ID + 1 stepCount += 1 if location.ParallelGroup != 0 { location.ParentID = location.ParallelGroup } children := *planConfig.Aggregate for i := 0; i < len(children); i++ { child := children[i] childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: location.ParentID, ParallelGroup: parallelGroup, } if child.Aggregate == nil { childLocation.Hook = location.Hook } stepCount = stepCount + populatePlanLocations(&child, childLocation) children[i] = child } parentID = parallelGroup default: planConfig.Location = location } if planConfig.Failure != nil { child := planConfig.Failure childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: parentID, ParallelGroup: 0, Hook: "failure", } stepCount = stepCount + populatePlanLocations(child, childLocation) } if planConfig.Success != nil { child := planConfig.Success childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: parentID, ParallelGroup: 0, Hook: "success", } stepCount = stepCount + populatePlanLocations(child, childLocation) } if planConfig.Ensure != nil { child := planConfig.Ensure childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: parentID, ParallelGroup: 0, Hook: "ensure", } stepCount = stepCount + populatePlanLocations(child, childLocation) } return stepCount + 1 }
func validatePlan(c atc.Config, identifier string, plan atc.PlanConfig) []string { foundTypes := foundTypes{ identifier: identifier, found: make(map[string]bool), } if plan.Get != "" { foundTypes.Find("get") } if plan.Put != "" { foundTypes.Find("put") } if plan.Task != "" { foundTypes.Find("task") } if plan.Do != nil { foundTypes.Find("do") } if plan.Aggregate != nil { foundTypes.Find("aggregate") } if plan.Try != nil { foundTypes.Find("try") } if valid, message := foundTypes.IsValid(); !valid { return []string{message} } errorMessages := []string{} switch { case plan.Do != nil: for i, plan := range *plan.Do { subIdentifier := fmt.Sprintf("%s[%d]", identifier, i) errorMessages = append(errorMessages, validatePlan(c, subIdentifier, plan)...) } case plan.Aggregate != nil: for i, plan := range *plan.Aggregate { subIdentifier := fmt.Sprintf("%s.aggregate[%d]", identifier, i) errorMessages = append(errorMessages, validatePlan(c, subIdentifier, plan)...) } case plan.Get != "": subIdentifier := fmt.Sprintf("%s.get.%s", identifier, plan.Get) errorMessages = append(errorMessages, validateInapplicableFields( []string{"privileged", "config", "file"}, plan, subIdentifier)..., ) if plan.Resource != "" { _, found := c.Resources.Lookup(plan.Resource) if !found { errorMessages = append( errorMessages, fmt.Sprintf( "%s refers to a resource that does not exist ('%s')", subIdentifier, plan.Resource, ), ) } } else { _, found := c.Resources.Lookup(plan.Get) if !found { errorMessages = append( errorMessages, fmt.Sprintf( "%s refers to a resource that does not exist", subIdentifier, ), ) } } for _, job := range plan.Passed { jobConfig, found := c.Jobs.Lookup(job) if !found { errorMessages = append( errorMessages, fmt.Sprintf( "%s.passed references an unknown job ('%s')", subIdentifier, job, ), ) } else { foundResource := false for _, jobInput := range JobInputs(jobConfig) { if jobInput.Resource == plan.ResourceName() { foundResource = true break } } for _, jobOutput := range JobOutputs(jobConfig) { if jobOutput.Resource == plan.ResourceName() { foundResource = true break } } if !foundResource { errorMessages = append( errorMessages, fmt.Sprintf( "%s.passed references a job ('%s') which doesn't interact with the resource ('%s')", subIdentifier, job, plan.Get, ), ) } } } case plan.Put != "": subIdentifier := fmt.Sprintf("%s.put.%s", identifier, plan.Put) errorMessages = append(errorMessages, validateInapplicableFields( []string{"passed", "trigger", "privileged", "config", "file"}, plan, subIdentifier)..., ) if plan.Resource != "" { _, found := c.Resources.Lookup(plan.Resource) if !found { errorMessages = append( errorMessages, fmt.Sprintf( "%s refers to a resource that does not exist ('%s')", subIdentifier, plan.Resource, ), ) } } else { _, found := c.Resources.Lookup(plan.Put) if !found { errorMessages = append( errorMessages, fmt.Sprintf( "%s refers to a resource that does not exist", subIdentifier, ), ) } } case plan.Task != "": subIdentifier := fmt.Sprintf("%s.task.%s", identifier, plan.Task) if plan.TaskConfig == nil && plan.TaskConfigPath == "" { errorMessages = append(errorMessages, subIdentifier+" does not specify any task configuration") } errorMessages = append(errorMessages, validateInapplicableFields( []string{"resource", "passed", "trigger"}, plan, subIdentifier)..., ) if plan.Params != nil { errorMessages = append(errorMessages, subIdentifier+" specifies params, which should be config.params") } case plan.Try != nil: subIdentifier := fmt.Sprintf("%s.try", identifier) errorMessages = append(errorMessages, validatePlan(c, subIdentifier, *plan.Try)...) } if plan.Ensure != nil { subIdentifier := fmt.Sprintf("%s.ensure", identifier) errorMessages = append(errorMessages, validatePlan(c, subIdentifier, *plan.Ensure)...) } if plan.Success != nil { subIdentifier := fmt.Sprintf("%s.success", identifier) errorMessages = append(errorMessages, validatePlan(c, subIdentifier, *plan.Success)...) } if plan.Failure != nil { subIdentifier := fmt.Sprintf("%s.failure", identifier) errorMessages = append(errorMessages, validatePlan(c, subIdentifier, *plan.Failure)...) } if plan.Timeout != "" { _, err := time.ParseDuration(plan.Timeout) if err != nil { subIdentifier := fmt.Sprintf("%s.timeout", identifier) errorMessages = append(errorMessages, subIdentifier+fmt.Sprintf(" refers to a duration that could not be parsed ('%s')", plan.Timeout)) } } return errorMessages }
func (l locationPopulator) populateLocations(planConfig *atc.PlanConfig, location *atc.Location) uint { var stepCount uint var parentID uint parentID = location.ID switch { case planConfig.Put != "": planConfig.Location = location // offset by one for the dependent get that will be added stepCount = stepCount + 1 case planConfig.Do != nil: // TODO: Do we actually need to increment these two here? See aggregate location. serialGroup := location.ID + 1 stepCount += 1 if location.SerialGroup != 0 { location.ParentID = location.SerialGroup } children := *planConfig.Do for i := 0; i < len(children); i++ { child := children[i] childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: location.ParentID, ParallelGroup: location.ParallelGroup, SerialGroup: serialGroup, } if child.Do == nil { childLocation.Hook = location.Hook } stepCount = stepCount + l.populateLocations(&child, childLocation) children[i] = child } parentID = serialGroup case planConfig.Try != nil: childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: location.ParentID, ParallelGroup: 0, Hook: location.Hook, } stepCount = stepCount + l.populateLocations(planConfig.Try, childLocation) case planConfig.Aggregate != nil: // TODO: Do we actually need to increment these two here? See do location. parallelGroup := location.ID + 1 stepCount += 1 if location.ParallelGroup != 0 { location.ParentID = location.ParallelGroup } children := *planConfig.Aggregate for i := 0; i < len(children); i++ { child := children[i] childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: location.ParentID, ParallelGroup: parallelGroup, SerialGroup: location.SerialGroup, } if child.Aggregate == nil && child.Do == nil { childLocation.Hook = location.Hook } stepCount = stepCount + l.populateLocations(&child, childLocation) children[i] = child } parentID = parallelGroup default: planConfig.Location = location } if planConfig.Failure != nil { child := planConfig.Failure childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: parentID, ParallelGroup: 0, Hook: "failure", } stepCount = stepCount + l.populateLocations(child, childLocation) } if planConfig.Success != nil { child := planConfig.Success childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: parentID, ParallelGroup: 0, Hook: "success", } stepCount = stepCount + l.populateLocations(child, childLocation) } if planConfig.Ensure != nil { child := planConfig.Ensure childLocation := &atc.Location{ ID: location.ID + stepCount + 1, ParentID: parentID, ParallelGroup: 0, Hook: "ensure", } stepCount = stepCount + l.populateLocations(child, childLocation) } return stepCount + 1 }