forked from tektoncd/pipeline
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add validtion when applying task modifiers 🧐
Task modifiers for PipelineResources add pre and post steps and sometimes Volumes to a pod spec. Adding a step or a volume that already exists will create a pod that cannot run so this commit adds validation: - If a modifier tries to add a step that already exists (i.e. the name is the same) that's an error - If a modifier tries to add a volume that already exists but the volume it references is the same, we assume that two resources need the same volume, so it's not an error, but we only add it wonce - If a modifier tries to add a volume that already exists but the volume it references is different, that means two resources need different volumes but we cant add both since the names are the same, so that's an error I encountered a problem with this while working on tektoncd#1417 (which we decided not to merge) where I tried to use two VolumeResources and there was a bug where they both had the same name, so the pod was not schedulable. I had to work backwards from the error that the pod was invalid and thought it would be much more handy to get the error earlier, so I added this.
- Loading branch information
1 parent
1271c3f
commit 78cb0cf
Showing
4 changed files
with
193 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* | ||
Copyright 2019 The Tekton Authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package v1alpha1_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" | ||
corev1 "k8s.io/api/core/v1" | ||
) | ||
|
||
var ( | ||
prependStep = corev1.Container{ | ||
Name: "prepend-step", | ||
Image: "dummy", | ||
Command: []string{"doit"}, | ||
Args: []string{"stuff", "things"}, | ||
} | ||
appendStep = corev1.Container{ | ||
Name: "append-step", | ||
Image: "dummy", | ||
Command: []string{"doit"}, | ||
Args: []string{"other stuff", "other things"}, | ||
} | ||
volume = corev1.Volume{ | ||
Name: "magic-volume", | ||
VolumeSource: corev1.VolumeSource{ | ||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: "some-claim"}, | ||
}, | ||
} | ||
) | ||
|
||
type TestTaskModifier struct{} | ||
|
||
func (tm *TestTaskModifier) GetStepsToPrepend() []v1alpha1.Step { | ||
return []v1alpha1.Step{{ | ||
Container: prependStep, | ||
}} | ||
} | ||
|
||
func (tm *TestTaskModifier) GetStepsToAppend() []v1alpha1.Step { | ||
return []v1alpha1.Step{{ | ||
Container: appendStep, | ||
}} | ||
} | ||
|
||
func (tm *TestTaskModifier) GetVolumes() []corev1.Volume { | ||
return []corev1.Volume{volume} | ||
} | ||
|
||
func TestApplyTaskModifier(t *testing.T) { | ||
testcases := []struct { | ||
name string | ||
ts v1alpha1.TaskSpec | ||
}{{ | ||
name: "success", | ||
ts: v1alpha1.TaskSpec{}, | ||
}, { | ||
name: "identical volume already added", | ||
ts: v1alpha1.TaskSpec{ | ||
// Trying to add the same Volume that has already been added shouldn't be an error | ||
// and it should not be added twice | ||
Volumes: []corev1.Volume{volume}, | ||
}, | ||
}} | ||
for _, tc := range testcases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
if err := v1alpha1.ApplyTaskModifier(&tc.ts, &TestTaskModifier{}); err != nil { | ||
t.Fatalf("Did not expect error modifying TaskSpec but got %v", err) | ||
} | ||
|
||
expectedTaskSpec := v1alpha1.TaskSpec{ | ||
Steps: []v1alpha1.Step{{ | ||
Container: prependStep, | ||
}, { | ||
Container: appendStep, | ||
}}, | ||
Volumes: []corev1.Volume{ | ||
volume, | ||
}, | ||
} | ||
|
||
if d := cmp.Diff(expectedTaskSpec, tc.ts); d != "" { | ||
t.Errorf("TaskSpec was not modified as expected (-want, +got): %s", d) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestApplyTaskModifier_AlreadyAdded(t *testing.T) { | ||
testcases := []struct { | ||
name string | ||
ts v1alpha1.TaskSpec | ||
}{{ | ||
name: "prepend already added", | ||
ts: v1alpha1.TaskSpec{ | ||
Steps: []v1alpha1.Step{{Container: prependStep}}, | ||
}, | ||
}, { | ||
name: "append already added", | ||
ts: v1alpha1.TaskSpec{ | ||
Steps: []v1alpha1.Step{{Container: appendStep}}, | ||
}, | ||
}, { | ||
name: "both steps already added", | ||
ts: v1alpha1.TaskSpec{ | ||
Steps: []v1alpha1.Step{{Container: prependStep}, {Container: appendStep}}, | ||
}, | ||
}, { | ||
name: "both steps already added reverse order", | ||
ts: v1alpha1.TaskSpec{ | ||
Steps: []v1alpha1.Step{{Container: appendStep}, {Container: prependStep}}, | ||
}, | ||
}, { | ||
name: "volume with same name but diff content already added", | ||
ts: v1alpha1.TaskSpec{ | ||
Volumes: []corev1.Volume{{ | ||
Name: "magic-volume", | ||
VolumeSource: corev1.VolumeSource{ | ||
EmptyDir: &corev1.EmptyDirVolumeSource{}, | ||
}, | ||
}}, | ||
}, | ||
}} | ||
for _, tc := range testcases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
if err := v1alpha1.ApplyTaskModifier(&tc.ts, &TestTaskModifier{}); err == nil { | ||
t.Errorf("Expected error when applying values already added but got none") | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters