diff --git a/pkg/driver/docker/docker.go b/pkg/driver/docker/docker.go index f614bff654..77e801fc24 100644 --- a/pkg/driver/docker/docker.go +++ b/pkg/driver/docker/docker.go @@ -402,24 +402,27 @@ func (d *dockerDriver) FindDevContainer( config.GetIDLabels(workspaceId, d.IDLabels), ) } - if err != nil { - return nil, err - } else if containerDetails == nil { - return nil, nil + if err != nil || containerDetails == nil { + return containerDetails, err } - if containerDetails.Config.User != "" { - if containerDetails.Config.Labels == nil { - containerDetails.Config.Labels = map[string]string{} - } - if containerDetails.Config.Labels[config.UserLabel] == "" { - containerDetails.Config.Labels[config.UserLabel] = containerDetails.Config.User - } - } + ensureUserLabel(containerDetails) return containerDetails, nil } +func ensureUserLabel(details *config.ContainerDetails) { + if details == nil || details.Config.User == "" { + return + } + if details.Config.Labels == nil { + details.Config.Labels = make(map[string]string) + } + if details.Config.Labels[config.UserLabel] == "" { + details.Config.Labels[config.UserLabel] = details.Config.User + } +} + func (d *dockerDriver) RequiresMountStreaming() bool { return false } func (d *dockerDriver) RecreateMode() driver.RecreateMode { return driver.RecreateDelete } diff --git a/pkg/driver/docker/docker_test.go b/pkg/driver/docker/docker_test.go index 5683273c60..92e2a2a346 100644 --- a/pkg/driver/docker/docker_test.go +++ b/pkg/driver/docker/docker_test.go @@ -1,8 +1,13 @@ package docker import ( + "context" + "os" + "path/filepath" "testing" + "github.com/devsy-org/devsy/pkg/devcontainer/config" + "github.com/devsy-org/devsy/pkg/docker" "github.com/stretchr/testify/suite" ) @@ -30,3 +35,165 @@ func TestDockerDriverSuite(t *testing.T) { func (s *DockerDriverTestSuite) SetupTest() { s.driver = &dockerDriver{} } + +func (s *DockerDriverTestSuite) TestEnsureUserLabel_NilDetails() { + s.NotPanics(func() { + ensureUserLabel(nil) + }) +} + +func (s *DockerDriverTestSuite) TestEnsureUserLabel_EmptyUser() { + details := &config.ContainerDetails{ + ID: "c1", + Config: config.ContainerDetailsConfig{ + User: "", + Labels: map[string]string{config.UserLabel: "existing"}, + }, + } + ensureUserLabel(details) + s.Equal("existing", details.Config.Labels[config.UserLabel]) + + detailsNilLabels := &config.ContainerDetails{ + ID: "c1", + Config: config.ContainerDetailsConfig{ + User: "", + Labels: nil, + }, + } + ensureUserLabel(detailsNilLabels) + s.Nil(detailsNilLabels.Config.Labels) +} + +func (s *DockerDriverTestSuite) TestEnsureUserLabel_InjectsWhenMissing() { + details := &config.ContainerDetails{ + ID: "c1", + Config: config.ContainerDetailsConfig{ + User: "1000", + Labels: nil, + }, + } + ensureUserLabel(details) + s.NotNil(details.Config.Labels) + s.Equal("1000", details.Config.Labels[config.UserLabel]) +} + +func (s *DockerDriverTestSuite) TestEnsureUserLabel_PreservesExistingLabel() { + details := &config.ContainerDetails{ + ID: "c1", + Config: config.ContainerDetailsConfig{ + User: "1000", + Labels: map[string]string{ + config.UserLabel: "custom-user", + }, + }, + } + ensureUserLabel(details) + s.Equal("custom-user", details.Config.Labels[config.UserLabel]) +} + +func (s *DockerDriverTestSuite) TestFindDevContainer_UsesContainerIDWhenPinned() { + script := `#!/bin/sh +case "$1" in + inspect) + echo '[{"ID":"pinned-123","Config":{"User":"node"}}]' + ;; + *) + exit 1 + ;; +esac +` + dir := s.T().TempDir() + bin := filepath.Join(dir, "docker-fake") + s.Require().NoError(os.WriteFile(bin, []byte(script), 0o755)) //nolint:gosec + + d := &dockerDriver{ + Docker: &docker.DockerHelper{ + DockerCommand: bin, + ContainerID: "pinned-123", + }, + } + + details, err := d.FindDevContainer(context.Background(), "my-workspace") + s.Require().NoError(err) + s.Require().NotNil(details) + s.Equal("pinned-123", details.ID) + s.Equal("node", details.Config.Labels[config.UserLabel]) +} + +func (s *DockerDriverTestSuite) TestFindDevContainer_FindByWorkspaceLabels() { + script := `#!/bin/sh +case "$1" in + ps) + echo "c-discovered" + ;; + inspect) + echo '[{"ID":"c-discovered","Config":{"User":"vscode","Labels":{"devsy.user":"override"}}}]' + ;; + *) + exit 1 + ;; +esac +` + dir := s.T().TempDir() + bin := filepath.Join(dir, "docker-fake") + s.Require().NoError(os.WriteFile(bin, []byte(script), 0o755)) //nolint:gosec + + d := &dockerDriver{ + Docker: &docker.DockerHelper{ + DockerCommand: bin, + }, + IDLabels: []string{"custom.label/workspace"}, + } + + details, err := d.FindDevContainer(context.Background(), "my-workspace") + s.Require().NoError(err) + s.Require().NotNil(details) + s.Equal("c-discovered", details.ID) + s.Equal("override", details.Config.Labels[config.UserLabel]) +} + +func (s *DockerDriverTestSuite) TestFindDevContainer_NotFoundReturnsNil() { + script := `#!/bin/sh +case "$1" in + ps) + # Return empty - no container found + ;; + *) + exit 1 + ;; +esac +` + dir := s.T().TempDir() + bin := filepath.Join(dir, "docker-fake") + s.Require().NoError(os.WriteFile(bin, []byte(script), 0o755)) //nolint:gosec + + d := &dockerDriver{ + Docker: &docker.DockerHelper{ + DockerCommand: bin, + }, + } + + details, err := d.FindDevContainer(context.Background(), "nonexistent") + s.Require().NoError(err) + s.Nil(details) +} + +func (s *DockerDriverTestSuite) TestFindDevContainer_ErrorPropagated() { + script := `#!/bin/sh +exit 1 +` + dir := s.T().TempDir() + bin := filepath.Join(dir, "docker-fake") + s.Require().NoError(os.WriteFile(bin, []byte(script), 0o755)) //nolint:gosec + + d := &dockerDriver{ + Docker: &docker.DockerHelper{ + DockerCommand: bin, + ContainerID: "failing-id", + }, + } + + details, err := d.FindDevContainer(context.Background(), "ws") + s.Require().Error(err) + s.Nil(details) +}