Support target-aware reference selectors
This commit is contained in:
@@ -50,15 +50,17 @@ type ResolveOptions struct {
|
||||
}
|
||||
|
||||
type ReferenceBinding struct {
|
||||
LaneID string `json:"lane_id,omitempty"`
|
||||
SlotName string `json:"slot_name"`
|
||||
Source string `json:"source"`
|
||||
BindingSource string `json:"binding_source,omitempty"`
|
||||
Stage ModuleStage `json:"stage,omitempty"`
|
||||
LaneID string `json:"lane_id,omitempty"`
|
||||
SlotName string `json:"slot_name"`
|
||||
Source string `json:"source"`
|
||||
BindingSource string `json:"binding_source,omitempty"`
|
||||
}
|
||||
|
||||
type ReferenceUnbind struct {
|
||||
LaneID string `json:"lane_id"`
|
||||
SlotName string `json:"slot_name"`
|
||||
Stage ModuleStage `json:"stage,omitempty"`
|
||||
LaneID string `json:"lane_id,omitempty"`
|
||||
SlotName string `json:"slot_name"`
|
||||
}
|
||||
|
||||
type ResolvedReferenceTarget struct {
|
||||
@@ -424,23 +426,12 @@ func resolveReferenceTargetBindings(target referenceResolutionTarget) ([]Referen
|
||||
}
|
||||
}
|
||||
|
||||
if target.Stage != StageExtract {
|
||||
for _, slot := range target.Slots {
|
||||
if slot.Required {
|
||||
if _, ok := bindings[slot.Name]; !ok {
|
||||
return nil, fmt.Errorf("%s required reference slot %q is not bound", referenceTargetErrorContext(target), slot.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sortedReferenceBindings(bindings), nil
|
||||
}
|
||||
|
||||
for _, override := range target.Options.ReferenceOverrides {
|
||||
optionLaneID := strings.TrimSpace(override.LaneID)
|
||||
if optionLaneID == "" {
|
||||
return nil, fmt.Errorf("pipeline %q reference override lane id must not be empty", target.PipelineID)
|
||||
match, err := referenceOverrideMatchesTarget(target, override)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if optionLaneID != target.LaneID {
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
source := override.BindingSource
|
||||
@@ -453,11 +444,11 @@ func resolveReferenceTargetBindings(target referenceResolutionTarget) ([]Referen
|
||||
}
|
||||
|
||||
for _, unbind := range target.Options.ReferenceUnbinds {
|
||||
optionLaneID := strings.TrimSpace(unbind.LaneID)
|
||||
if optionLaneID == "" {
|
||||
return nil, fmt.Errorf("pipeline %q reference unbind lane id must not be empty", target.PipelineID)
|
||||
match, err := referenceUnbindMatchesTarget(target, unbind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if optionLaneID != target.LaneID {
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
slotName := strings.TrimSpace(unbind.SlotName)
|
||||
@@ -481,6 +472,44 @@ func resolveReferenceTargetBindings(target referenceResolutionTarget) ([]Referen
|
||||
return sortedReferenceBindings(bindings), nil
|
||||
}
|
||||
|
||||
func referenceOverrideMatchesTarget(target referenceResolutionTarget, override ReferenceBinding) (bool, error) {
|
||||
stage, laneID, err := normalizeReferenceOptionTarget(target.PipelineID, "override", override.Stage, override.LaneID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return stage == target.Stage && laneID == target.LaneID, nil
|
||||
}
|
||||
|
||||
func referenceUnbindMatchesTarget(target referenceResolutionTarget, unbind ReferenceUnbind) (bool, error) {
|
||||
stage, laneID, err := normalizeReferenceOptionTarget(target.PipelineID, "unbind", unbind.Stage, unbind.LaneID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return stage == target.Stage && laneID == target.LaneID, nil
|
||||
}
|
||||
|
||||
func normalizeReferenceOptionTarget(pipelineID string, operation string, stage ModuleStage, laneID string) (ModuleStage, string, error) {
|
||||
stage = ModuleStage(strings.TrimSpace(string(stage)))
|
||||
if stage == "" {
|
||||
stage = StageExtract
|
||||
}
|
||||
laneID = strings.TrimSpace(laneID)
|
||||
|
||||
switch stage {
|
||||
case StageChunk:
|
||||
if laneID != "" {
|
||||
return "", "", fmt.Errorf("pipeline %q reference %s for chunk must not include a lane id", pipelineID, operation)
|
||||
}
|
||||
case StageExtract, StageNormalize:
|
||||
if laneID == "" {
|
||||
return "", "", fmt.Errorf("pipeline %q reference %s lane id must not be empty", pipelineID, operation)
|
||||
}
|
||||
default:
|
||||
return "", "", fmt.Errorf("pipeline %q reference %s stage %q is not supported", pipelineID, operation, stage)
|
||||
}
|
||||
return stage, laneID, nil
|
||||
}
|
||||
|
||||
func sortedReferenceBindings(bindings map[string]ReferenceBinding) []ReferenceBinding {
|
||||
keys := sortedReferenceBindingKeys(bindings)
|
||||
resolved := make([]ReferenceBinding, 0, len(keys))
|
||||
|
||||
Reference in New Issue
Block a user