Skip to content

Commit ea9158f

Browse files
Scotttekton-robot
Scott
authored andcommitted
Run integration tests in "alpha" as part of pipelines' CI
Prior to this commit the integration tests run against PRs were only those for "stable" features. This PR adds additional integration test runs for "alpha" features as well. `test/e2e-scripts.sh` now patches the feature-flags ConfigMap before executing integration tests and examples tests, first with "enable-api-fields: stable" and then with "enable-api-fields: alpha". As part of switching on alpha tests two issues have also been fixed with alpha features: 1. Sidecar workspaces could collide with existing volumeMounts attached to the sidecar if the mountpath of the workspace matched an existing volumeMount. This has been fixed by preventing the additional workspace volumeMount if one already exists at that mountpath. 2. Tekton bundles integration tests needed to be updated to account for validation errors that are returned when a bundle is invalid.
1 parent f4b56b1 commit ea9158f

File tree

5 files changed

+185
-15
lines changed

5 files changed

+185
-15
lines changed

docs/workspaces.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,12 @@ spec:
186186
touch "$(workspaces.signals.path)/ready"
187187
```
188188

189-
**Note:** `Sidecars` _must_ explicitly opt-in to receiving the `Workspace` volume. Injected `Sidecars` from
190-
non-Tekton sources will not receive access to `Workspaces`.
189+
**Note:** Starting in Pipelines v0.24.0 `Sidecars` automatically get access to `Workspaces`.This is an
190+
alpha feature and requires Pipelines to have [the "alpha" feature gate enabled](./install.md#alpha-features).
191+
192+
If a Sidecar already has a `volumeMount` at the location expected for a `workspace` then that `workspace` is
193+
not bound to the Sidecar. This preserves backwards-compatibility with any existing uses of the `volumeMount`
194+
trick described above.
191195

192196
#### Isolating `Workspaces` to Specific `Steps` or `Sidecars`
193197

pkg/workspace/apply.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ func mountAsSharedWorkspace(ts v1beta1.TaskSpec, volumeMount corev1.VolumeMount)
158158
ts.StepTemplate.VolumeMounts = append(ts.StepTemplate.VolumeMounts, volumeMount)
159159

160160
for i := range ts.Sidecars {
161-
sidecar := &ts.Sidecars[i]
162-
sidecar.VolumeMounts = append(sidecar.VolumeMounts, volumeMount)
161+
AddSidecarVolumeMount(&ts.Sidecars[i], volumeMount)
163162
}
164163
}
165164

@@ -193,3 +192,14 @@ func mountAsIsolatedWorkspace(ts v1beta1.TaskSpec, workspaceName string, volumeM
193192
}
194193
}
195194
}
195+
196+
// AddSidecarVolumeMount is a helper to add a volumeMount to the sidecar unless its
197+
// MountPath would conflict with another of the sidecar's existing volume mounts.
198+
func AddSidecarVolumeMount(sidecar *v1beta1.Sidecar, volumeMount corev1.VolumeMount) {
199+
for j := range sidecar.VolumeMounts {
200+
if sidecar.VolumeMounts[j].MountPath == volumeMount.MountPath {
201+
return
202+
}
203+
}
204+
sidecar.VolumeMounts = append(sidecar.VolumeMounts, volumeMount)
205+
}

pkg/workspace/apply_test.go

+134
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,61 @@ func TestApply_IsolatedWorkspaces(t *testing.T) {
794794
Name: "source",
795795
}},
796796
},
797+
}, {
798+
name: "existing sidecar volumeMounts are not displaced by workspace binding",
799+
ts: v1beta1.TaskSpec{
800+
Workspaces: []v1beta1.WorkspaceDeclaration{{
801+
Name: "custom",
802+
MountPath: "/my/fancy/mount/path",
803+
ReadOnly: true,
804+
}},
805+
Sidecars: []v1beta1.Sidecar{{
806+
Container: corev1.Container{
807+
Name: "conflicting volume mount sidecar",
808+
VolumeMounts: []corev1.VolumeMount{{
809+
Name: "mount-path-conflicts",
810+
MountPath: "/my/fancy/mount/path",
811+
}},
812+
},
813+
}},
814+
},
815+
workspaces: []v1beta1.WorkspaceBinding{{
816+
Name: "custom",
817+
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
818+
ClaimName: "mypvc",
819+
},
820+
}},
821+
expectedTaskSpec: v1beta1.TaskSpec{
822+
StepTemplate: &corev1.Container{
823+
VolumeMounts: []corev1.VolumeMount{{
824+
Name: "ws-j2tds",
825+
MountPath: "/my/fancy/mount/path",
826+
ReadOnly: true,
827+
}},
828+
},
829+
Sidecars: []v1beta1.Sidecar{{
830+
Container: corev1.Container{
831+
Name: "conflicting volume mount sidecar",
832+
VolumeMounts: []corev1.VolumeMount{{
833+
Name: "mount-path-conflicts",
834+
MountPath: "/my/fancy/mount/path",
835+
}},
836+
},
837+
}},
838+
Volumes: []corev1.Volume{{
839+
Name: "ws-j2tds",
840+
VolumeSource: corev1.VolumeSource{
841+
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
842+
ClaimName: "mypvc",
843+
},
844+
},
845+
}},
846+
Workspaces: []v1beta1.WorkspaceDeclaration{{
847+
Name: "custom",
848+
MountPath: "/my/fancy/mount/path",
849+
ReadOnly: true,
850+
}},
851+
},
797852
}} {
798853
t.Run(tc.name, func(t *testing.T) {
799854
ctx := config.ToContext(context.Background(), &config.Config{
@@ -831,3 +886,82 @@ func TestApplyWithMissingWorkspaceDeclaration(t *testing.T) {
831886
t.Errorf("Expected error because workspace doesnt exist.")
832887
}
833888
}
889+
890+
// TestAddSidecarVolumeMount tests that sidecars dont receive a volume mount if
891+
// it has a mount that already shares the same MountPath.
892+
func TestAddSidecarVolumeMount(t *testing.T) {
893+
for _, tc := range []struct {
894+
sidecarMounts []corev1.VolumeMount
895+
volumeMount corev1.VolumeMount
896+
expectedSidecar v1beta1.Sidecar
897+
}{{
898+
sidecarMounts: nil,
899+
volumeMount: corev1.VolumeMount{
900+
Name: "foo",
901+
MountPath: "/workspace/foo",
902+
},
903+
expectedSidecar: v1beta1.Sidecar{
904+
Container: corev1.Container{
905+
VolumeMounts: []corev1.VolumeMount{{
906+
Name: "foo",
907+
MountPath: "/workspace/foo",
908+
}},
909+
},
910+
},
911+
}, {
912+
sidecarMounts: []corev1.VolumeMount{},
913+
volumeMount: corev1.VolumeMount{
914+
Name: "foo",
915+
MountPath: "/workspace/foo",
916+
},
917+
expectedSidecar: v1beta1.Sidecar{
918+
Container: corev1.Container{
919+
VolumeMounts: []corev1.VolumeMount{{
920+
Name: "foo",
921+
MountPath: "/workspace/foo",
922+
}},
923+
},
924+
},
925+
}, {
926+
sidecarMounts: []corev1.VolumeMount{{
927+
Name: "bar",
928+
MountPath: "/workspace/bar",
929+
}},
930+
volumeMount: corev1.VolumeMount{
931+
Name: "workspace1",
932+
MountPath: "/workspace/bar",
933+
},
934+
expectedSidecar: v1beta1.Sidecar{
935+
Container: corev1.Container{
936+
VolumeMounts: []corev1.VolumeMount{{
937+
Name: "bar",
938+
MountPath: "/workspace/bar",
939+
}},
940+
},
941+
},
942+
}, {
943+
sidecarMounts: []corev1.VolumeMount{{
944+
Name: "bar",
945+
MountPath: "/workspace/bar",
946+
}},
947+
volumeMount: corev1.VolumeMount{
948+
Name: "foo",
949+
MountPath: "/workspace/foo",
950+
},
951+
expectedSidecar: v1beta1.Sidecar{
952+
Container: corev1.Container{
953+
VolumeMounts: []corev1.VolumeMount{{
954+
Name: "bar",
955+
MountPath: "/workspace/bar",
956+
}, {
957+
Name: "foo",
958+
MountPath: "/workspace/foo",
959+
}},
960+
},
961+
},
962+
}} {
963+
sidecar := v1beta1.Sidecar{}
964+
sidecar.Container.VolumeMounts = tc.sidecarMounts
965+
workspace.AddSidecarVolumeMount(&v1beta1.Sidecar{}, corev1.VolumeMount{})
966+
}
967+
}

test/e2e-tests.sh

+28-8
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,34 @@ install_pipeline_crd
2929

3030
failed=0
3131

32-
# Run the integration tests
33-
header "Running Go e2e tests"
34-
go_test_e2e -timeout=20m ./test/... || failed=1
35-
36-
# Run these _after_ the integration tests b/c they don't quite work all the way
37-
# and they cause a lot of noise in the logs, making it harder to debug integration
38-
# test failures.
39-
go_test_e2e -tags=examples -timeout=20m ./test/ || failed=1
32+
function set_feature_gate() {
33+
local gate="$1"
34+
if [ "$gate" != "alpha" ] && [ "$gate" != "stable" ] && [ "$gate" != "beta" ] ; then
35+
printf "Invalid gate %s\n" ${gate}
36+
exit 255
37+
fi
38+
printf "Setting feature gate to %s\n", ${gate}
39+
jsonpatch=$(printf "{\"data\": {\"enable-api-fields\": \"%s\"}}" $1)
40+
echo "feature-flags ConfigMap patch: ${jsonpatch}"
41+
kubectl patch configmap feature-flags -n tekton-pipelines -p "$jsonpatch"
42+
}
43+
44+
function run_e2e() {
45+
# Run the integration tests
46+
header "Running Go e2e tests"
47+
go_test_e2e -timeout=20m ./test/... || failed=1
48+
49+
# Run these _after_ the integration tests b/c they don't quite work all the way
50+
# and they cause a lot of noise in the logs, making it harder to debug integration
51+
# test failures.
52+
go_test_e2e -tags=examples -timeout=20m ./test/ || failed=1
53+
}
54+
55+
set_feature_gate "stable"
56+
run_e2e
57+
58+
set_feature_gate "alpha"
59+
run_e2e
4060

4161
(( failed )) && fail_test
4262
success

test/tektonbundles_test.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/google/go-containerregistry/pkg/v1/tarball"
4040
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
4141
"github.com/tektoncd/pipeline/pkg/pod"
42+
"github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun"
4243
corev1 "k8s.io/api/core/v1"
4344
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4445
"knative.dev/pkg/apis"
@@ -269,7 +270,7 @@ func TestTektonBundlesUsingRegularImage(t *testing.T) {
269270
if err := WaitForPipelineRunState(ctx, c, pipelineRunName, timeout,
270271
Chain(
271272
FailedWithReason(pod.ReasonCouldntGetTask, pipelineRunName),
272-
FailedWithMessage("could not find object in image with kind: task and name: hello-world-dne", pipelineRunName),
273+
FailedWithMessage("does not contain a dev.tekton.image.apiVersion annotation", pipelineRunName),
273274
), "PipelineRunFailed"); err != nil {
274275
t.Fatalf("Error waiting for PipelineRun to finish with expected error: %s", err)
275276
}
@@ -345,6 +346,7 @@ func TestTektonBundlesUsingImproperFormat(t *testing.T) {
345346
img, err = mutate.Append(img, mutate.Addendum{
346347
Layer: taskLayer,
347348
Annotations: map[string]string{
349+
// intentionally invalid name annotation
348350
"org.opencontainers.image.title": taskName,
349351
"dev.tekton.image.kind": strings.ToLower(task.Kind),
350352
"dev.tekton.image.apiVersion": task.APIVersion,
@@ -380,8 +382,8 @@ func TestTektonBundlesUsingImproperFormat(t *testing.T) {
380382
t.Logf("Waiting for PipelineRun in namespace %s to finish", namespace)
381383
if err := WaitForPipelineRunState(ctx, c, pipelineRunName, timeout,
382384
Chain(
383-
FailedWithReason(pod.ReasonCouldntGetTask, pipelineRunName),
384-
FailedWithMessage("could not find object in image with kind: task and name: hello-world", pipelineRunName),
385+
FailedWithReason(pipelinerun.ReasonCouldntGetPipeline, pipelineRunName),
386+
FailedWithMessage("does not contain a dev.tekton.image.name annotation", pipelineRunName),
385387
), "PipelineRunFailed"); err != nil {
386388
t.Fatalf("Error waiting for PipelineRun to finish with expected error: %s", err)
387389
}

0 commit comments

Comments
 (0)