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

chore(orchestrator): startup and remove containers based on dependencies #5509

Merged
merged 57 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
8305c0a
change exit codes of svc/env/job deploy
KollaAdithya Aug 10, 2023
ee2ee49
move errstruct to errors.go
KollaAdithya Aug 10, 2023
f00e15c
parse container deps from manifest
KollaAdithya Nov 14, 2023
a3a62af
change doc comment
KollaAdithya Nov 14, 2023
965b133
change doc comment
KollaAdithya Nov 14, 2023
9f4debc
Merge branch 'aws:mainline' into dependency/containers
KollaAdithya Nov 14, 2023
c4379c3
change test case name
KollaAdithya Nov 14, 2023
feb4412
Address fb from @ CaptainCarpensir
KollaAdithya Nov 14, 2023
4ac754d
fix static check
KollaAdithya Nov 14, 2023
18b2db1
add docker container methods
KollaAdithya Nov 16, 2023
87feceb
modify graph package
KollaAdithya Nov 19, 2023
8176525
implement dockerengine chnages and mocks
KollaAdithya Nov 19, 2023
e923d35
add run local changes
KollaAdithya Nov 19, 2023
c0ff69d
add WithStatus to graph package
KollaAdithya Nov 19, 2023
3b212ee
override container with dependsOn
KollaAdithya Nov 19, 2023
6365868
most of the chnages
KollaAdithya Nov 30, 2023
3cace54
use errorgroup
KollaAdithya Nov 30, 2023
1da538f
update mocks
KollaAdithya Nov 30, 2023
33fecbe
add remove of containers in stop
KollaAdithya Nov 30, 2023
4d5287d
resolve all merge conflicts
KollaAdithya Dec 6, 2023
8efb61a
add exitcode interface
KollaAdithya Dec 6, 2023
2376957
add status to buildGraph
KollaAdithya Dec 6, 2023
ad1afa8
add buffered channel and curTask
KollaAdithya Dec 6, 2023
06ac0b9
remove containers in reverse dependency order
KollaAdithya Dec 6, 2023
226448b
reolve conflicts
KollaAdithya Dec 6, 2023
83d1b07
Merge branch 'mainline' into implement/graph/dependencies
KollaAdithya Dec 6, 2023
70be81a
merge changes of doesContainerExist
KollaAdithya Dec 6, 2023
1d90997
add tests
KollaAdithya Dec 6, 2023
25e074c
add test for remove
KollaAdithya Dec 6, 2023
5739e60
add testcase for ess container exits
KollaAdithya Dec 6, 2023
f878217
Merge branch 'mainline' into implement/graph/dependencies
KollaAdithya Dec 6, 2023
41bd18f
Fix newline in pipeline.go
KollaAdithya Dec 6, 2023
5990309
increase test coverage
KollaAdithya Dec 6, 2023
5a4952f
address few nits and add tests
KollaAdithya Dec 8, 2023
fafc521
address one more nit
KollaAdithya Dec 8, 2023
c903b6d
remove DoesContainerExist logic :
KollaAdithya Dec 13, 2023
d1b159d
address fb: modify graph pkg API
KollaAdithya Dec 15, 2023
77c4e1a
use o.curTask at two places
KollaAdithya Dec 15, 2023
3bb15b6
fix doc comment
KollaAdithya Dec 15, 2023
831ca73
fix more doc comments
KollaAdithya Dec 15, 2023
6bc7968
remove mutex in graph traversal
KollaAdithya Dec 15, 2023
1a690f2
address @Lou1415926 fb
KollaAdithya Dec 15, 2023
075023c
address fb @ Lou1415926
KollaAdithya Dec 15, 2023
cd497f9
fix more nits
KollaAdithya Dec 15, 2023
08542d3
use custom error
KollaAdithya Dec 16, 2023
eeb1560
use prevTask
KollaAdithya Dec 16, 2023
a30c097
remove mix up of essential and dependsOn
KollaAdithya Dec 16, 2023
456c6b8
remove essential from err
KollaAdithya Dec 16, 2023
ac862a7
fix error msg
KollaAdithya Dec 16, 2023
f549658
add test case
KollaAdithya Dec 16, 2023
9aa5bb4
add non essential info
KollaAdithya Dec 18, 2023
a164eac
address ph fb
KollaAdithya Dec 19, 2023
c0b515b
use interface
KollaAdithya Dec 19, 2023
98377c3
Update internal/pkg/graph/graph.go
KollaAdithya Dec 19, 2023
369c30d
add check for visiting
KollaAdithya Dec 19, 2023
045db69
remove unnecessary waitForContainerToStart
KollaAdithya Dec 19, 2023
6d47259
Merge branch 'mainline' into implement/graph/dependencies
mergify[bot] Dec 19, 2023
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
5 changes: 3 additions & 2 deletions internal/pkg/cli/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,12 +706,13 @@ type templateDiffer interface {
type dockerEngineRunner interface {
CheckDockerEngineRunning() error
Run(context.Context, *dockerengine.RunOptions) error
DoesContainerExist(context.Context, string) (bool, error)
IsContainerRunning(context.Context, string) (bool, error)
Stop(context.Context, string) error
Rm(string) error
Build(context.Context, *dockerengine.BuildArguments, io.Writer) error
Exec(ctx context.Context, container string, out io.Writer, cmd string, args ...string) error
IsContainerCompleteOrSuccess(ctx context.Context, containerName string) (int, error)
IsContainerHealthy(ctx context.Context, containerName string) (bool, error)
Rm(context.Context, string) error
}

type workloadStackGenerator interface {
Expand Down
53 changes: 34 additions & 19 deletions internal/pkg/cli/mocks/mock_interfaces.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions internal/pkg/cli/run_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,8 +537,6 @@ func (o *runLocalOpts) prepareTask(ctx context.Context) (orchestrator.Task, erro
task.Containers[name] = ctr
}

// TODO (Adi): Use this dependency order in orchestrator to start and stop containers.
// replace container dependencies with the local dependencies from manifest.
containerDeps := manifest.ContainerDependencies(mft.Manifest())
for name, dep := range containerDeps {
ctr, ok := task.Containers[name]
Expand Down
30 changes: 18 additions & 12 deletions internal/pkg/docker/dockerengine/dockerengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -263,7 +264,6 @@ func (c DockerCmdClient) Push(ctx context.Context, uri string, w io.Writer, tags

func (in *RunOptions) generateRunArguments() []string {
args := []string{"run"}
args = append(args, "--rm")

if in.ContainerName != "" {
args = append(args, "--name", in.ContainerName)
Expand Down Expand Up @@ -303,6 +303,9 @@ func (in *RunOptions) generateRunArguments() []string {

// Run runs a Docker container with the sepcified options.
func (c DockerCmdClient) Run(ctx context.Context, options *RunOptions) error {
type exitCodeError interface {
ExitCode() int
}
KollaAdithya marked this conversation as resolved.
Show resolved Hide resolved
// set default options
if options.LogOptions.Color == nil {
options.LogOptions.Color = color.New()
Expand Down Expand Up @@ -343,6 +346,13 @@ func (c DockerCmdClient) Run(ctx context.Context, options *RunOptions) error {
exec.Stdout(stdout),
exec.Stderr(stderr),
exec.NewProcessGroup()); err != nil {
var ec exitCodeError
if errors.As(err, &ec) {
KollaAdithya marked this conversation as resolved.
Show resolved Hide resolved
return &ErrContainerExited{
name: options.ContainerName,
exitcode: ec.ExitCode(),
}
}
return fmt.Errorf("running container: %w", err)
}
return nil
Expand All @@ -351,15 +361,6 @@ func (c DockerCmdClient) Run(ctx context.Context, options *RunOptions) error {
return g.Wait()
}

// DoesContainerExist checks if a specific Docker container exists.
func (c DockerCmdClient) DoesContainerExist(ctx context.Context, name string) (bool, error) {
output, err := c.containerID(ctx, name)
if err != nil {
return false, err
}
return output != "", nil
}

// IsContainerRunning checks if a specific Docker container is running.
func (c DockerCmdClient) IsContainerRunning(ctx context.Context, name string) (bool, error) {
state, err := c.containerState(ctx, name)
Expand Down Expand Up @@ -459,6 +460,11 @@ type ErrContainerExited struct {
exitcode int
}

// ExitCode returns the OS exit code configured for this error.
func (e *ErrContainerExited) ExitCode() int {
return e.exitcode
}

// ErrContainerExited represents docker container exited with an exitcode.
func (e *ErrContainerExited) Error() string {
return fmt.Sprintf("container %q exited with code %d", e.name, e.exitcode)
Expand All @@ -474,9 +480,9 @@ func (c DockerCmdClient) Stop(ctx context.Context, containerID string) error {
}

// Rm calls `docker rm` to remove a stopped container.
func (c DockerCmdClient) Rm(containerID string) error {
func (c DockerCmdClient) Rm(ctx context.Context, containerID string) error {
buf := &bytes.Buffer{}
if err := c.runner.Run("docker", []string{"rm", containerID}, exec.Stdout(buf), exec.Stderr(buf)); err != nil {
if err := c.runner.RunWithContext(ctx, "docker", []string{"rm", containerID}, exec.Stdout(buf), exec.Stderr(buf)); err != nil {
return fmt.Errorf("%s: %w", strings.TrimSpace(buf.String()), err)
}
return nil
Expand Down
28 changes: 24 additions & 4 deletions internal/pkg/docker/dockerengine/dockerengine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
"os"
osexec "os/exec"
"path/filepath"
"strings"
Expand Down Expand Up @@ -680,13 +681,35 @@ func TestDockerCommand_Run(t *testing.T) {
setupMocks: func(controller *gomock.Controller) {
mockCmd = NewMockCmd(controller)
mockCmd.EXPECT().RunWithContext(gomock.Any(), "docker", []string{"run",
"--rm",
"--name", mockPauseContainer,
"mockImageUri",
"sleep", "infinity"}, gomock.Any(), gomock.Any(), gomock.Any()).Return(mockError)
},
wantedError: fmt.Errorf("running container: %w", mockError),
},

"should return error when container exits": {
containerName: mockPauseContainer,
command: mockCommand,
uri: mockImageURI,
setupMocks: func(controller *gomock.Controller) {
mockCmd = NewMockCmd(controller)

mockCmd.EXPECT().RunWithContext(gomock.Any(), "docker", []string{"run",
"--name", mockPauseContainer,
"mockImageUri",
"sleep", "infinity"}, gomock.Any(), gomock.Any(), gomock.Any()).
DoAndReturn(func(ctx context.Context, name string, args []string, opts ...exec.CmdOption) error {
// Simulate an zero exit code.
return &osexec.ExitError{ProcessState: &os.ProcessState{}}
})
},
wantedError: &ErrContainerExited{
name: mockPauseContainer,
exitcode: 0,
},
},

"success with run options for pause container": {
containerName: mockPauseContainer,
ports: mockContainerPorts,
Expand All @@ -695,7 +718,6 @@ func TestDockerCommand_Run(t *testing.T) {
setupMocks: func(controller *gomock.Controller) {
mockCmd = NewMockCmd(controller)
mockCmd.EXPECT().RunWithContext(gomock.Any(), "docker", gomock.InAnyOrder([]string{"run",
"--rm",
"--name", mockPauseContainer,
"--publish", "8080:8080",
"--publish", "8081:8081",
Expand All @@ -712,7 +734,6 @@ func TestDockerCommand_Run(t *testing.T) {
setupMocks: func(controller *gomock.Controller) {
mockCmd = NewMockCmd(controller)
mockCmd.EXPECT().RunWithContext(gomock.Any(), "docker", gomock.InAnyOrder([]string{"run",
"--rm",
"--name", mockContainerName,
"--network", "container:pauseContainer",
"--env", "DB_PASSWORD=mysecretPassword",
Expand All @@ -733,7 +754,6 @@ func TestDockerCommand_Run(t *testing.T) {
setupMocks: func(controller *gomock.Controller) {
mockCmd = NewMockCmd(controller)
mockCmd.EXPECT().RunWithContext(gomock.Any(), "docker", gomock.InAnyOrder([]string{"run",
"--rm",
"--name", mockContainerName,
"--network", "container:pauseContainer",
"--env", "DB_PASSWORD=mysecretPassword",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import (

// Double is a test double for dockerengine.DockerCmdClient
type Double struct {
StopFn func(context.Context, string) error
DoesContainerExistFn func(context.Context, string) (bool, error)
IsContainerRunningFn func(context.Context, string) (bool, error)
RunFn func(context.Context, *dockerengine.RunOptions) error
BuildFn func(context.Context, *dockerengine.BuildArguments, io.Writer) error
ExecFn func(context.Context, string, io.Writer, string, ...string) error
StopFn func(context.Context, string) error
IsContainerRunningFn func(context.Context, string) (bool, error)
RunFn func(context.Context, *dockerengine.RunOptions) error
BuildFn func(context.Context, *dockerengine.BuildArguments, io.Writer) error
ExecFn func(context.Context, string, io.Writer, string, ...string) error
IsContainerHealthyFn func(ctx context.Context, containerName string) (bool, error)
IsContainerCompleteOrSuccessFn func(ctx context.Context, containerName string) (int, error)
RmFn func(context.Context, string) error
}

// Stop calls the stubbed function.
Expand All @@ -28,14 +30,6 @@ func (d *Double) Stop(ctx context.Context, name string) error {
return d.StopFn(ctx, name)
}

// DoesContainerExist calls the stubbed function.
func (d *Double) DoesContainerExist(ctx context.Context, name string) (bool, error) {
if d.IsContainerRunningFn == nil {
return false, nil
}
return d.DoesContainerExistFn(ctx, name)
}

// IsContainerRunning calls the stubbed function.
func (d *Double) IsContainerRunning(ctx context.Context, name string) (bool, error) {
if d.IsContainerRunningFn == nil {
Expand Down Expand Up @@ -67,3 +61,27 @@ func (d *Double) Exec(ctx context.Context, container string, out io.Writer, cmd
}
return d.ExecFn(ctx, container, out, cmd, args...)
}

// Rm calls the stubbed function.
func (d *Double) Rm(ctx context.Context, name string) error {
if d.RmFn == nil {
return nil
}
return d.RmFn(ctx, name)
}

// IsContainerCompleteOrSuccess implements orchestrator.DockerEngine.
func (d *Double) IsContainerCompleteOrSuccess(ctx context.Context, containerName string) (int, error) {
if d.IsContainerCompleteOrSuccessFn == nil {
return -1, nil
}
return d.IsContainerCompleteOrSuccessFn(ctx, containerName)
}

// IsContainerHealthy implements orchestrator.DockerEngine.
func (d *Double) IsContainerHealthy(ctx context.Context, containerName string) (bool, error) {
if d.IsContainerHealthyFn == nil {
return false, nil
}
return d.IsContainerHealthyFn(ctx, containerName)
}
Loading
Loading