Skip to content
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
8 changes: 6 additions & 2 deletions cmd/agent/container/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/devsy-org/devsy/pkg/agent"
config2 "github.com/devsy-org/devsy/pkg/config"
agentd "github.com/devsy-org/devsy/pkg/daemon/agent"
"github.com/devsy-org/devsy/pkg/devcontainer/config"
"github.com/devsy-org/devsy/pkg/log"
"github.com/devsy-org/devsy/pkg/platform/client"
"github.com/devsy-org/devsy/pkg/ts"
Expand Down Expand Up @@ -46,7 +47,10 @@ func NewDaemonCmd() *cobra.Command {
daemonCmd.Flags().
StringVar(&cmd.Config.Timeout, "timeout", "", "The timeout to stop the container after")
daemonCmd.Flags().
StringVar(&cmd.Config.ShutdownAction, "shutdown-action", "", "The shutdown action (none or stopContainer)")
StringVar(
&cmd.Config.ShutdownAction, "shutdown-action", "",
"The shutdown action (none, stopContainer, or stopCompose)",
)
return daemonCmd
}

Expand Down Expand Up @@ -99,7 +103,7 @@ func (cmd *DaemonCmd) Run(c *cobra.Command, args []string) error {
}

// Start timeout monitor unless shutdownAction is "none".
if timeoutDuration > 0 && cmd.Config.ShutdownAction != "none" {
if timeoutDuration > 0 && cmd.Config.ShutdownAction != config.ShutdownActionNone {
tasksStarted = true
g.Go(func() error {
return runTimeoutMonitor(ctx, timeoutDuration)
Expand Down
8 changes: 6 additions & 2 deletions cmd/agent/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/devsy-org/devsy/cmd/flags"
"github.com/devsy-org/devsy/pkg/agent"
"github.com/devsy-org/devsy/pkg/client/clientimplementation"
"github.com/devsy-org/devsy/pkg/devcontainer/config"
"github.com/devsy-org/devsy/pkg/driver/custom"
"github.com/devsy-org/devsy/pkg/log"
provider2 "github.com/devsy-org/devsy/pkg/provider"
Expand Down Expand Up @@ -41,7 +42,10 @@ func NewDaemonCmd(flags *flags.GlobalFlags) *cobra.Command {
daemonCmd.Flags().
StringVar(&cmd.Interval, "interval", "", "The interval how to poll workspaces")
daemonCmd.Flags().
StringVar(&cmd.ShutdownAction, "shutdown-action", "", "The shutdown action (none or stopContainer)")
StringVar(
&cmd.ShutdownAction, "shutdown-action", "",
"The shutdown action (none, stopContainer, or stopCompose)",
)
return daemonCmd
}

Expand Down Expand Up @@ -129,7 +133,7 @@ func (cmd *DaemonCmd) checkAndShutdown(
latestActivity *time.Time,
workspace *provider2.AgentWorkspaceInfo,
) {
if cmd.ShutdownAction == "none" {
if cmd.ShutdownAction == config.ShutdownActionNone {
return
}

Expand Down
34 changes: 34 additions & 0 deletions e2e/tests/up-docker-compose/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,40 @@ func (tc *testContext) getAppContainer(
return ids, detail, err
}

func (tc *testContext) findAppAndSidecar(
ctx context.Context,
workspaceUID string,
) (appIDs, sidecarIDs []string) {
var err error
appIDs, err = findComposeContainer(
ctx, tc.dockerHelper, tc.composeHelper, workspaceUID, "app",
)
framework.ExpectNoError(err)
gomega.Expect(appIDs).To(gomega.HaveLen(1))

sidecarIDs, err = findComposeContainer(
ctx, tc.dockerHelper, tc.composeHelper, workspaceUID, "sidecar",
)
framework.ExpectNoError(err)
gomega.Expect(sidecarIDs).To(gomega.HaveLen(1))
return appIDs, sidecarIDs
}

func (tc *testContext) inspectRunningState(
ctx context.Context,
appIDs, sidecarIDs []string,
) (appRunning, sidecarRunning bool) {
var appDetails []container.InspectResponse
err := tc.dockerHelper.Inspect(ctx, appIDs, "container", &appDetails)
framework.ExpectNoError(err)

var sidecarDetails []container.InspectResponse
err = tc.dockerHelper.Inspect(ctx, sidecarIDs, "container", &sidecarDetails)
framework.ExpectNoError(err)

return appDetails[0].State.Running, sidecarDetails[0].State.Running
}

func (tc *testContext) verifyWorkspaceMount(
ctx context.Context,
workspace *provider2.Workspace,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "shutdown-action-container-test",
"dockerComposeFile": "../docker-compose.yaml",
"service": "app",
"workspaceFolder": "/workspaces",
"shutdownAction": "stopContainer"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
app:
image: ghcr.io/devsy-org/test-images/go:1
command: sleep infinity
volumes:
- .:/workspaces:cached
sidecar:
image: alpine:latest
command: sleep infinity
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "shutdown-action-test",
"dockerComposeFile": "../docker-compose.yaml",
"service": "app",
"workspaceFolder": "/workspaces",
"shutdownAction": "stopCompose"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
app:
image: ghcr.io/devsy-org/test-images/go:1
command: sleep infinity
volumes:
- .:/workspaces:cached
sidecar:
image: alpine:latest
command: sleep infinity
50 changes: 50 additions & 0 deletions e2e/tests/up-docker-compose/up_docker_compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,5 +557,55 @@ var _ = ginkgo.Describe(
gomega.Expect(strings.TrimSpace(buildArgs)).
To(gomega.Equal("ghcr.io/devsy-org/test-images/go:1"))
}, ginkgo.SpecTimeout(framework.TimeoutShort()))

ginkgo.It(
"shutdownAction stopCompose stops all services",
func(ctx context.Context) {
tempDir, workspace, err := tc.setupAndStartWorkspace(
ctx,
"tests/up-docker-compose/testdata/docker-compose-shutdown-action",
)
framework.ExpectNoError(err)

appIDs, sidecarIDs := tc.findAppAndSidecar(ctx, workspace.UID)

err = tc.f.DevsyStop(ctx, tempDir)
framework.ExpectNoError(err)

appRunning, sidecarRunning := tc.inspectRunningState(
ctx, appIDs, sidecarIDs,
)
gomega.Expect(appRunning).
To(gomega.BeFalse(), "app container should be stopped")
gomega.Expect(sidecarRunning).
To(gomega.BeFalse(), "sidecar container should be stopped")
},
ginkgo.SpecTimeout(framework.TimeoutShort()),
)

ginkgo.It(
"shutdownAction stopContainer only stops main service",
func(ctx context.Context) {
tempDir, workspace, err := tc.setupAndStartWorkspace(
ctx,
"tests/up-docker-compose/testdata/docker-compose-shutdown-action-container",
)
framework.ExpectNoError(err)

appIDs, sidecarIDs := tc.findAppAndSidecar(ctx, workspace.UID)

err = tc.f.DevsyStop(ctx, tempDir)
framework.ExpectNoError(err)

appRunning, sidecarRunning := tc.inspectRunningState(
ctx, appIDs, sidecarIDs,
)
gomega.Expect(appRunning).
To(gomega.BeFalse(), "app container should be stopped")
gomega.Expect(sidecarRunning).
To(gomega.BeTrue(), "sidecar container should still be running")
},
ginkgo.SpecTimeout(framework.TimeoutShort()),
)
},
)
2 changes: 1 addition & 1 deletion pkg/daemon/agent/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func BuildWorkspaceDaemonConfig(
// build info isn't required in the workspace and can be omitted
platformOptions.Build = nil

shutdownAction := "stopContainer"
shutdownAction := config.ShutdownActionStopContainer
if mergedConfig.ShutdownAction != "" {
shutdownAction = mergedConfig.ShutdownAction
}
Expand Down
15 changes: 10 additions & 5 deletions pkg/daemon/agent/daemon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,22 @@ func TestBuildWorkspaceDaemonConfig_ShutdownAction(t *testing.T) {
{
name: "defaults to stopContainer when empty",
shutdownAction: "",
want: "stopContainer",
want: config.ShutdownActionStopContainer,
},
{
name: "preserves none",
shutdownAction: "none",
want: "none",
shutdownAction: config.ShutdownActionNone,
want: config.ShutdownActionNone,
},
{
name: "preserves stopContainer",
shutdownAction: "stopContainer",
want: "stopContainer",
shutdownAction: config.ShutdownActionStopContainer,
want: config.ShutdownActionStopContainer,
},
{
name: "preserves stopCompose",
shutdownAction: config.ShutdownActionStopCompose,
want: config.ShutdownActionStopCompose,
},
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/devcontainer/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,12 @@ type PortAttribute struct {
Protocol string `json:"protocol,omitempty"`
}

const (
ShutdownActionNone = "none"
ShutdownActionStopContainer = "stopContainer"
ShutdownActionStopCompose = "stopCompose"
)

const (
AutoForwardIgnore = "ignore"
AutoForwardNotify = "notify"
Expand Down
42 changes: 28 additions & 14 deletions pkg/devcontainer/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,37 @@ func (r *runner) Stop(ctx context.Context) error {
return nil
}

if strings.ToLower(containerDetails.State.Status) == "running" {
if isDockerCompose, projectName := getDockerComposeProject(
containerDetails,
); isDockerCompose {
err = r.stopDockerCompose(ctx, projectName)
if err != nil {
return err
}
} else {
err = r.Driver.StopDevContainer(ctx, r.ID)
if err != nil {
return err
}
if strings.ToLower(containerDetails.State.Status) != "running" {
return nil
}

isCompose, projectName := getDockerComposeProject(containerDetails)
action := r.getShutdownAction(isCompose)

switch action {
case config.ShutdownActionNone:
return nil
case config.ShutdownActionStopCompose:
if isCompose {
return r.stopDockerCompose(ctx, projectName)
}
return r.Driver.StopDevContainer(ctx, r.ID)
default:
return r.Driver.StopDevContainer(ctx, r.ID)
}
}

return nil
func (r *runner) getShutdownAction(isCompose bool) string {
if r.WorkspaceConfig != nil &&
r.WorkspaceConfig.LastDevContainerConfig != nil &&
r.WorkspaceConfig.LastDevContainerConfig.Config != nil &&
r.WorkspaceConfig.LastDevContainerConfig.Config.ShutdownAction != "" {
return r.WorkspaceConfig.LastDevContainerConfig.Config.ShutdownAction
}
if isCompose {
return config.ShutdownActionStopCompose
}
return config.ShutdownActionStopContainer
}

func getDockerComposeProject(containerDetails *config.ContainerDetails) (bool, string) {
Expand Down
Loading