Skip to content

Commit

Permalink
liveupdate: display exec errors correctly (#5636)
Browse files Browse the repository at this point in the history
fixes #5635
  • Loading branch information
nicks committed Mar 28, 2022
1 parent 044acd5 commit 324cf90
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 2 deletions.
18 changes: 16 additions & 2 deletions internal/controllers/core/liveupdate/reconciler.go
Expand Up @@ -2,6 +2,7 @@ package liveupdate

import (
"context"
"errors"
"fmt"
"sync"
"time"
Expand Down Expand Up @@ -551,7 +552,14 @@ func (r *Reconciler) dispatchCompleteBuildAction(lu *v1alpha1.LiveUpdate, newSta
spanID := logstore.SpanID(lu.Annotations[v1alpha1.AnnotationSpanID])
var err error
if newStatus.Failed != nil {
err = fmt.Errorf("%s", newStatus.Failed.Message)
err = errors.New(newStatus.Failed.Message)
} else {
for _, c := range newStatus.Containers {
if c.LastExecError != "" {
err = errors.New(c.LastExecError)
break
}
}
}

resultSet := store.BuildResultSet{}
Expand Down Expand Up @@ -973,9 +981,15 @@ func (r *Reconciler) applyInternal(
} else {
// Something went wrong with this update and it's NOT the user's fault--
// likely a infrastructure error. Bail, and fall back to full build.
msg := ""
if cStatus.PodName != "" {
msg = fmt.Sprintf("Updating pod %s: %v", cStatus.PodName, err)
} else {
msg = fmt.Sprintf("Updating container %s: %v", cInfo.DisplayName(), err)
}
result.Failed = &v1alpha1.LiveUpdateStateFailed{
Reason: "UpdateFailed",
Message: fmt.Sprintf("Updating pod %s: %v", cStatus.PodName, err),
Message: msg,
}
return result
}
Expand Down
85 changes: 85 additions & 0 deletions internal/controllers/core/liveupdate/reconciler_test.go
Expand Up @@ -2,6 +2,8 @@ package liveupdate

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"testing"
Expand All @@ -13,6 +15,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"github.com/tilt-dev/tilt/internal/build"
"github.com/tilt-dev/tilt/internal/containerupdate"
"github.com/tilt-dev/tilt/internal/controllers/apis/configmap"
"github.com/tilt-dev/tilt/internal/controllers/apis/liveupdate"
Expand Down Expand Up @@ -720,6 +723,11 @@ func TestDockerComposeExecs(t *testing.T) {
assert.Equal(t, txtChangeTime, lu.Status.Containers[0].LastFileTimeSynced)
}

// Make sure there were no exec errors.
if assert.NotNil(t, f.st.lastCompletedAction) {
assert.Nil(t, f.st.lastCompletedAction.Error)
}

// Make sure two cmds were executed, and one was skipped.
if assert.Equal(t, 1, len(f.cu.Calls)) {
assert.Equal(t, []model.Cmd{
Expand All @@ -729,6 +737,83 @@ func TestDockerComposeExecs(t *testing.T) {
}
}

func TestDockerComposeExecInfraFailure(t *testing.T) {
f := newFixture(t)

p, _ := os.Getwd()
nowMicro := apis.NowMicro()
txtPath := filepath.Join(p, "a.txt")
txtChangeTime := metav1.MicroTime{Time: nowMicro.Add(time.Second)}

f.setupDockerComposeFrontend()

var lu v1alpha1.LiveUpdate
f.MustGet(types.NamespacedName{Name: "frontend-liveupdate"}, &lu)

execs := []v1alpha1.LiveUpdateExec{
{Args: model.ToUnixCmd("echo error && exit 1").Argv},
}
lu.Spec.Execs = execs
f.Upsert(&lu)

f.cu.SetUpdateErr(fmt.Errorf("cluster connection lost"))

// Trigger a file event, and make sure that the status reflects the sync.
f.addFileEvent("frontend-fw", txtPath, txtChangeTime)
f.MustReconcile(types.NamespacedName{Name: "frontend-liveupdate"})

f.MustGet(types.NamespacedName{Name: "frontend-liveupdate"}, &lu)
if assert.NotNil(t, lu.Status.Failed) {
assert.Equal(t, "UpdateFailed", lu.Status.Failed.Reason)
assert.Equal(t, "Updating container main-id: cluster connection lost",
lu.Status.Failed.Message)
}

// Make sure there were exec errors.
if assert.NotNil(t, f.st.lastCompletedAction) {
assert.Equal(t, "Updating container main-id: cluster connection lost",
f.st.lastCompletedAction.Error.Error())
}
}

func TestDockerComposeExecRunFailure(t *testing.T) {
f := newFixture(t)

p, _ := os.Getwd()
nowMicro := apis.NowMicro()
txtPath := filepath.Join(p, "a.txt")
txtChangeTime := metav1.MicroTime{Time: nowMicro.Add(time.Second)}

f.setupDockerComposeFrontend()

var lu v1alpha1.LiveUpdate
f.MustGet(types.NamespacedName{Name: "frontend-liveupdate"}, &lu)

execs := []v1alpha1.LiveUpdateExec{
{Args: model.ToUnixCmd("echo error && exit 1").Argv},
}
lu.Spec.Execs = execs
f.Upsert(&lu)

f.cu.SetUpdateErr(build.NewRunStepFailure(errors.New("compilation failed")))

// Trigger a file event, and make sure that the status reflects the sync.
f.addFileEvent("frontend-fw", txtPath, txtChangeTime)
f.MustReconcile(types.NamespacedName{Name: "frontend-liveupdate"})

f.MustGet(types.NamespacedName{Name: "frontend-liveupdate"}, &lu)
assert.Nil(t, lu.Status.Failed)
if assert.Equal(t, 1, len(lu.Status.Containers)) {
assert.Equal(t, "compilation failed", lu.Status.Containers[0].LastExecError)
}

// Make sure there were exec errors.
if assert.NotNil(t, f.st.lastCompletedAction) {
assert.Equal(t, "compilation failed",
f.st.lastCompletedAction.Error.Error())
}
}

type TestingStore struct {
*store.TestingStore
ctx context.Context
Expand Down

0 comments on commit 324cf90

Please sign in to comment.