mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
fix(agent/agentcontainers): reset error at start of rebuild (#18686)
Reset the error associated with a devcontainer when a rebuild is requested.
This commit is contained in:
@ -946,6 +946,7 @@ func (api *API) handleDevcontainerRecreate(w http.ResponseWriter, r *http.Reques
|
|||||||
// devcontainer multiple times in parallel.
|
// devcontainer multiple times in parallel.
|
||||||
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusStarting
|
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusStarting
|
||||||
dc.Container = nil
|
dc.Container = nil
|
||||||
|
dc.Error = ""
|
||||||
api.knownDevcontainers[dc.WorkspaceFolder] = dc
|
api.knownDevcontainers[dc.WorkspaceFolder] = dc
|
||||||
go func() {
|
go func() {
|
||||||
_ = api.CreateDevcontainer(dc.WorkspaceFolder, dc.ConfigPath, WithRemoveExistingContainer())
|
_ = api.CreateDevcontainer(dc.WorkspaceFolder, dc.ConfigPath, WithRemoveExistingContainer())
|
||||||
|
@ -69,7 +69,7 @@ func (f *fakeContainerCLI) ExecAs(ctx context.Context, name, user string, args .
|
|||||||
type fakeDevcontainerCLI struct {
|
type fakeDevcontainerCLI struct {
|
||||||
upID string
|
upID string
|
||||||
upErr error
|
upErr error
|
||||||
upErrC chan error // If set, send to return err, close to return upErr.
|
upErrC chan func() error // If set, send to return err, close to return upErr.
|
||||||
execErr error
|
execErr error
|
||||||
execErrC chan func(cmd string, args ...string) error // If set, send fn to return err, nil or close to return execErr.
|
execErrC chan func(cmd string, args ...string) error // If set, send fn to return err, nil or close to return execErr.
|
||||||
readConfig agentcontainers.DevcontainerConfig
|
readConfig agentcontainers.DevcontainerConfig
|
||||||
@ -82,9 +82,9 @@ func (f *fakeDevcontainerCLI) Up(ctx context.Context, _, _ string, _ ...agentcon
|
|||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return "", ctx.Err()
|
return "", ctx.Err()
|
||||||
case err, ok := <-f.upErrC:
|
case fn, ok := <-f.upErrC:
|
||||||
if ok {
|
if ok {
|
||||||
return f.upID, err
|
return f.upID, fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -613,7 +613,7 @@ func TestAPI(t *testing.T) {
|
|||||||
nowRecreateErrorTrap := mClock.Trap().Now("recreate", "errorTimes")
|
nowRecreateErrorTrap := mClock.Trap().Now("recreate", "errorTimes")
|
||||||
nowRecreateSuccessTrap := mClock.Trap().Now("recreate", "successTimes")
|
nowRecreateSuccessTrap := mClock.Trap().Now("recreate", "successTimes")
|
||||||
|
|
||||||
tt.devcontainerCLI.upErrC = make(chan error)
|
tt.devcontainerCLI.upErrC = make(chan func() error)
|
||||||
|
|
||||||
// Setup router with the handler under test.
|
// Setup router with the handler under test.
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
@ -1665,7 +1665,7 @@ func TestAPI(t *testing.T) {
|
|||||||
mClock = quartz.NewMock(t)
|
mClock = quartz.NewMock(t)
|
||||||
fCCLI = &fakeContainerCLI{arch: "<none>"}
|
fCCLI = &fakeContainerCLI{arch: "<none>"}
|
||||||
fDCCLI = &fakeDevcontainerCLI{
|
fDCCLI = &fakeDevcontainerCLI{
|
||||||
upErrC: make(chan error, 1),
|
upErrC: make(chan func() error, 1),
|
||||||
}
|
}
|
||||||
fSAC = &fakeSubAgentClient{
|
fSAC = &fakeSubAgentClient{
|
||||||
logger: logger.Named("fakeSubAgentClient"),
|
logger: logger.Named("fakeSubAgentClient"),
|
||||||
@ -1717,7 +1717,7 @@ func TestAPI(t *testing.T) {
|
|||||||
|
|
||||||
// Given: We simulate an error running `devcontainer up`
|
// Given: We simulate an error running `devcontainer up`
|
||||||
simulatedError := xerrors.New("simulated error")
|
simulatedError := xerrors.New("simulated error")
|
||||||
testutil.RequireSend(ctx, t, fDCCLI.upErrC, simulatedError)
|
testutil.RequireSend(ctx, t, fDCCLI.upErrC, func() error { return simulatedError })
|
||||||
|
|
||||||
nowRecreateErrorTrap.MustWait(ctx).MustRelease(ctx)
|
nowRecreateErrorTrap.MustWait(ctx).MustRelease(ctx)
|
||||||
nowRecreateErrorTrap.Close()
|
nowRecreateErrorTrap.Close()
|
||||||
@ -1742,7 +1742,22 @@ func TestAPI(t *testing.T) {
|
|||||||
require.Equal(t, http.StatusAccepted, rec.Code)
|
require.Equal(t, http.StatusAccepted, rec.Code)
|
||||||
|
|
||||||
// Given: We allow `devcontainer up` to succeed.
|
// Given: We allow `devcontainer up` to succeed.
|
||||||
testutil.RequireSend(ctx, t, fDCCLI.upErrC, nil)
|
testutil.RequireSend(ctx, t, fDCCLI.upErrC, func() error {
|
||||||
|
req = httptest.NewRequest(http.MethodGet, "/", nil)
|
||||||
|
rec = httptest.NewRecorder()
|
||||||
|
r.ServeHTTP(rec, req)
|
||||||
|
require.Equal(t, http.StatusOK, rec.Code)
|
||||||
|
|
||||||
|
response = codersdk.WorkspaceAgentListContainersResponse{}
|
||||||
|
err = json.NewDecoder(rec.Body).Decode(&response)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Then: We make sure that the error has been cleared before running up.
|
||||||
|
require.Len(t, response.Devcontainers, 1)
|
||||||
|
require.Equal(t, "", response.Devcontainers[0].Error)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
nowRecreateSuccessTrap.MustWait(ctx).MustRelease(ctx)
|
nowRecreateSuccessTrap.MustWait(ctx).MustRelease(ctx)
|
||||||
nowRecreateSuccessTrap.Close()
|
nowRecreateSuccessTrap.Close()
|
||||||
@ -1756,7 +1771,7 @@ func TestAPI(t *testing.T) {
|
|||||||
err = json.NewDecoder(rec.Body).Decode(&response)
|
err = json.NewDecoder(rec.Body).Decode(&response)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Then: We expect that there will be no error associated with the devcontainer.
|
// Then: We also expect no error after running up..
|
||||||
require.Len(t, response.Devcontainers, 1)
|
require.Len(t, response.Devcontainers, 1)
|
||||||
require.Equal(t, "", response.Devcontainers[0].Error)
|
require.Equal(t, "", response.Devcontainers[0].Error)
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user