Skip to content

Commit

Permalink
Implement Step and Sidecar Overrides for TaskRun
Browse files Browse the repository at this point in the history
This implements TEP-0094: Configuring Resources at Runtime.
StepOverrides and SidecarOverrides were added to the API in a previous commit.
This commit allows them to override resource requirements specified in the Task spec.
The same merging strategy that is currently used for stepTemplate is also used for
step and sidecar overrides, except that only the resources field of the container is overridden,
and unlike with templates, the overrides take precedence over the Task spec.
  • Loading branch information
lbernick committed Feb 18, 2022
1 parent 9605e3e commit ef13bea
Show file tree
Hide file tree
Showing 11 changed files with 794 additions and 6 deletions.
3 changes: 1 addition & 2 deletions docs/taskruns.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,9 @@ and reasons.
### Overriding Task Steps and Sidecars

**([alpha only](https://github.com/tektoncd/pipeline/blob/main/docs/install.md#alpha-features))**
**Warning: This feature is still under development and is not yet functional. Do not use it.**

A TaskRun can specify `StepOverrides` or `SidecarOverrides` to override Step or Sidecar
configuration specified in a Task.
configuration specified in a Task. Only named Steps and Sidecars may be overridden.

For example, given the following Task definition:

Expand Down
85 changes: 85 additions & 0 deletions pkg/apis/pipeline/v1beta1/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,88 @@ func MergeStepsWithStepTemplate(template *v1.Container, steps []Step) ([]Step, e
}
return steps, nil
}

// MergeStepsWithOverrides takes a possibly nil list of overrides and a
// list of steps, merging each of the steps with the overrides' resource requirements, if
// it's not nil, and returning the resulting list.
func MergeStepsWithOverrides(steps []Step, overrides []TaskRunStepOverride) ([]Step, error) {
stepNameToOverride := make(map[string]TaskRunStepOverride, len(overrides))
for _, o := range overrides {
stepNameToOverride[o.Name] = o
}
for i, s := range steps {
o, found := stepNameToOverride[s.Name]
if !found {
continue
}
mergedResources, err := mergeResourcesWithOverride(&s.Resources, &o.Resources)
if err != nil {
return nil, err
}
steps[i].Container.Resources = *mergedResources
}
return steps, nil
}

// MergeSidecarsWithOverrides takes a possibly nil list of overrides and a
// list of sidecars, merging each of the sidecars with the overrides' resource requirements, if
// it's not nil, and returning the resulting list.
func MergeSidecarsWithOverrides(sidecars []Sidecar, overrides []TaskRunSidecarOverride) ([]Sidecar, error) {
sidecarNameToOverride := make(map[string]TaskRunSidecarOverride, len(overrides))
for _, o := range overrides {
sidecarNameToOverride[o.Name] = o
}
for i, s := range sidecars {
o, found := sidecarNameToOverride[s.Name]
if !found {
continue
}
mergedResources, err := mergeResourcesWithOverride(&s.Resources, &o.Resources)
if err != nil {
return nil, err
}
sidecars[i].Container.Resources = *mergedResources
}
return sidecars, nil
}

func mergeResourcesWithOverride(resources, overrides *v1.ResourceRequirements) (*v1.ResourceRequirements, error) {
if overrides == nil {
return resources, nil
}
resourcesAsJSON, err := json.Marshal(resources)
if err != nil {
return nil, err
}
overridesAsJSON, err := json.Marshal(overrides)
if err != nil {
return nil, err
}
emptyJSON, err := json.Marshal(&v1.ResourceRequirements{})
if err != nil {
return nil, err
}
// Treat resources as "template", since we want overrides to override the value in the resources
patchSchema, err := strategicpatch.NewPatchMetaFromStruct(resources)
if err != nil {
return nil, err
}
patch, err := strategicpatch.CreateThreeWayMergePatch(emptyJSON, overridesAsJSON, resourcesAsJSON, patchSchema, true)
if err != nil {
return nil, err
}

// Actually apply the merge patch to the template JSON.
mergedAsJSON, err := strategicpatch.StrategicMergePatchUsingLookupPatchMeta(resourcesAsJSON, patch, patchSchema)
if err != nil {
return nil, err
}

// Unmarshal the merged JSON to a Container pointer, and return it.
merged := &v1.ResourceRequirements{}
err = json.Unmarshal(mergedAsJSON, merged)
if err != nil {
return nil, err
}
return merged, nil
}
Loading

0 comments on commit ef13bea

Please sign in to comment.