Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly cleanup injected sidecars #5565

Merged
merged 1 commit into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions pkg/reconciler/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,6 @@ func (c *Reconciler) stopSidecars(ctx context.Context, tr *v1beta1.TaskRun) erro
return nil
}

// do not continue if the TaskSpec had no sidecars
if tr.Status.TaskSpec != nil && len(tr.Status.TaskSpec.Sidecars) == 0 && len(tr.Status.Sidecars) == 0 {
afrittoli marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

// do not continue if the TaskRun was canceled or timed out as this caused the pod to be deleted in failTaskRun
condition := tr.Status.GetCondition(apis.ConditionSucceeded)
if condition != nil {
Expand All @@ -267,11 +262,6 @@ func (c *Reconciler) stopSidecars(ctx context.Context, tr *v1beta1.TaskRun) erro
}
}

// do not continue if there are no Running sidecars.
if !podconvert.IsSidecarStatusRunning(tr) {
return nil
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test in https://github.com/tektoncd/pipeline/pull/5565/files#diff-6e67e9c647bbe2a08807ff5ccbdd7dc9036df373e56b9774d3996f92ab7ceabaL289 will mark a TaskRun failed if we fail to stop one of the injected sidecars.

I don't run an environment with istio, so I'm not sure what the best behaviour would be; I think failing the TaskRun because the injected sidecar could not be stopped seems a bit harsh, but at least it would be aligned with the behaviour we have to sidecars defined in the TaskRun.

I think it would be worth adding a note to the release notes about this.
You can do that even if the PR is merged once you read this comment, since the release notes will be picked up later by the release automation.

pod, err := podconvert.StopSidecars(ctx, c.Images.NopImage, c.KubeClientSet, tr.Namespace, tr.Status.PodName)
if err == nil {
// Check if any SidecarStatuses are still shown as Running after stopping
Expand Down
122 changes: 71 additions & 51 deletions pkg/reconciler/taskrun/taskrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4078,65 +4078,85 @@ status:
}
}

func TestStopSidecars_NoClientGetPodForTaskSpecWithoutRunningSidecars(t *testing.T) {
for _, tc := range []struct {
desc string
tr *v1beta1.TaskRun
}{{
desc: "no sidecars",
tr: parse.MustParseV1beta1TaskRun(t, `
metadata:
name: test-taskrun
namespace: foo
status:
conditions:
- status: "True"
type: Succeeded
podName: test-taskrun-pod
startTime: "2000-01-01T01:01:01Z"
`),
}, {
desc: "sidecars are terminated",
tr: parse.MustParseV1beta1TaskRun(t, `
func TestStopSidecars_WithInjectedSidecarsNoTaskSpecSidecars(t *testing.T) {
taskRun := parse.MustParseV1beta1TaskRun(t, `
metadata:
name: test-taskrun
name: test-taskrun-injected-sidecars
namespace: foo
spec:
taskRef:
name: test-task
status:
podName: test-taskrun-injected-sidecars-pod
conditions:
- status: "True"
- message: Build succeeded
reason: Build succeeded
status: "True"
type: Succeeded
podName: test-taskrun-pod
sidecars:
- terminated:
exitCode: 0
finishedAt: "2000-01-01T01:01:01Z"
startedAt: "2000-01-01T01:01:01Z"
startTime: "2000-01-01T01:01:01Z"
`),
}} {
t.Run(tc.desc, func(t *testing.T) {
d := test.Data{
TaskRuns: []*v1beta1.TaskRun{tc.tr},
}
`)

testAssets, cancel := getTaskRunController(t, d)
defer cancel()
c := testAssets.Controller
clients := testAssets.Clients
reconcileErr := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(tc.tr))
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "test-taskrun-injected-sidecars-pod",
Namespace: "foo",
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "step-do-something",
Image: "my-step-image",
},
{
Name: "injected-sidecar",
Image: "some-image",
},
},
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
ContainerStatuses: []corev1.ContainerStatus{
{
Name: "step-do-something",
State: v1.ContainerState{Terminated: &corev1.ContainerStateTerminated{}},
},
{
Name: "injected-sidecar",
State: v1.ContainerState{Running: &corev1.ContainerStateRunning{}},
},
},
},
}

// We do not expect an error
if reconcileErr != nil {
t.Errorf("Expected no error to be returned by reconciler: %v", reconcileErr)
}
d := test.Data{
Pods: []*corev1.Pod{pod},
TaskRuns: []*v1beta1.TaskRun{taskRun},
Tasks: []*v1beta1.Task{simpleTask},
}

// Verify that the pod was not retrieved
for _, action := range clients.Kube.Actions() {
if action.Matches("get", "pods") {
t.Errorf("expected the pod not to be retrieved because the TaskRun has no sidecars")
}
}
})
testAssets, cancel := getTaskRunController(t, d)
defer cancel()
c := testAssets.Controller
clients := testAssets.Clients

reconcileErr := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun))

// We do not expect an error
if reconcileErr != nil {
t.Errorf("Expected no error to be returned by reconciler: %v", reconcileErr)
}

retrievedPod, err := clients.Kube.CoreV1().Pods(pod.Namespace).Get(testAssets.Ctx, pod.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("error retrieving pod: %s", err)
}

if len(retrievedPod.Spec.Containers) != 2 {
t.Fatalf("expected pod with two containers")
}

// check that injected sidecar is replaced with nop image
if d := cmp.Diff(retrievedPod.Spec.Containers[1].Image, images.NopImage); d != "" {
t.Errorf("expected injected sidecar image to be replaced with nop image %s", diff.PrintWantGot(d))
}
}

Expand Down