Skip to content

Commit

Permalink
Merge pull request #7 from silphid/docker-cli
Browse files Browse the repository at this point in the history
First draft of CLI docker integration
  • Loading branch information
silphid authored May 27, 2021
2 parents b348fde + 21b6c11 commit 2653845
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 870 deletions.
5 changes: 0 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@ go 1.14

require (
github.com/AlecAivazis/survey/v2 v2.2.12
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/containerd/containerd v1.5.2 // indirect
github.com/docker/docker v20.10.6+incompatible
github.com/docker/go-connections v0.4.0 // indirect
github.com/go-test/deep v1.0.7
github.com/mitchellh/go-homedir v1.1.0
github.com/morikuni/aec v1.0.0 // indirect
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.7.0
gopkg.in/yaml.v2 v2.4.0
Expand Down
694 changes: 6 additions & 688 deletions go.sum

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions src/cmd/get/containers/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package containers
import (
"context"
"fmt"
"strings"

"github.com/spf13/cobra"

Expand All @@ -22,9 +23,10 @@ func New() *cobra.Command {
}

func run(ctx context.Context) error {
api, err := docker.NewAPI()
names, err := docker.ListContainers(ctx)
if err != nil {
return fmt.Errorf("failed to connect to docker client: %w", err)
return err
}
return api.ListContainers(ctx)
fmt.Println(strings.Join(names, "\n"))
return nil
}
7 changes: 1 addition & 6 deletions src/cmd/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,5 @@ func run(ctx context.Context, name string) error {

containerName := fmt.Sprintf("yey-%s-%s-%s", shortImageName, yeyContext.Name, yeyContext.Hash())

api, err := docker.NewAPI()
if err != nil {
return fmt.Errorf("failed to connect to docker client: %w", err)
}

return api.Start(ctx, yeyContext, containerName)
return docker.Start(ctx, yeyContext, containerName)
}
10 changes: 6 additions & 4 deletions src/internal/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (

// Context represents execution configuration for some docker container
type Context struct {
Name string `yaml:",omitempty"`
Image string
Env map[string]string
Mounts map[string]string
Name string `yaml:",omitempty"`
Image string
Env map[string]string
Mounts map[string]string
Cmd []string
EntryPoint []string
}

// Clone returns a deep-copy of this context
Expand Down
5 changes: 0 additions & 5 deletions src/internal/docker.go

This file was deleted.

138 changes: 0 additions & 138 deletions src/internal/docker/api.go

This file was deleted.

116 changes: 95 additions & 21 deletions src/internal/docker/cli.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,112 @@
package docker

import (
"context"
"fmt"
"os"
"os/exec"
"strings"

"github.com/mitchellh/go-homedir"
yey "github.com/silphid/yey/src/internal"
)

type CLI struct{}
func Start(ctx context.Context, yeyCtx yey.Context, containerName string) error {
// Determine whether we need to run or exec container
status, err := getContainerStatus(ctx, containerName)
if err != nil {
return err
}

func (c CLI) Start(ct yey.Context, imageTag, containerName string) error {
return fmt.Errorf("not implemented")
switch status {
case "":
return runContainer(ctx, yeyCtx, containerName)
case "exited":
return startContainer(ctx, containerName)
case "running":
return execContainer(ctx, containerName, yeyCtx.Cmd)
default:
return fmt.Errorf("container %q in unexpected state %q", containerName, status)
}
}

func ListContainers(ctx context.Context) ([]string, error) {
cmd := exec.Command("docker", "ps", "--all", "--filter", "name=yey-*", "--format", "{{.Names}}")
output, err := cmd.Output()
if err != nil {
return nil, err
}
return strings.Split(string(output), "\n"), nil
}

// Get running ID and state
// docker ps --all --filter "name=al" --format '{{.ID}}|{{.State}}'
// state="exited"|"running"
func getContainerStatus(ctx context.Context, name string) (string, error) {
cmd := exec.CommandContext(ctx, "docker", "inspect", name, "--format", "{{.State.Status}}")

// Run
// docker run -it --name al alpine
output, err := cmd.CombinedOutput()
if err != nil {
if strings.Contains(string(output), "No such object") {
return "", nil
}
return "", fmt.Errorf("failed to get container status: %s: %w", output, err)
}

// Exec
// run docker exec -it "${DOCKER_EXEC_ARGS[@]}" "${DOCKER_CONTAINER}" zsh
return strings.TrimSpace(string(output)), nil
}

// type containerState string
func runContainer(ctx context.Context, yeyCtx yey.Context, containerName string) error {
cwd, err := os.Getwd()
if err != nil {
return err
}

args := []string{
"run",
"--name", containerName,
"-it",
// "--env LS_COLORS",
// "--env TERM",
// "--env TERM_COLOR",
// "--env TERM_PROGRAM",
"--env", "YEY_WORK_DIR=" + cwd,
"--env", "YEY_CONTEXT=" + yeyCtx.Name,
}

// const (
// stateRunning containerState = "running"
// stateExited = "exited"
// )
// Context env vars
for name, value := range yeyCtx.Env {
args = append(args, "--env", fmt.Sprintf("%s=%s", name, value))
}

// type container struct {
// state containerState
// }
home, err := homedir.Dir()
if err != nil {
return fmt.Errorf("failed to detect user home directory: %w", err)
}

// func getContainer(name string) (container, error) {
// return container{}, nil
// }
for key, value := range yeyCtx.Mounts {
args = append(
args,
"--volume",
fmt.Sprintf("%s:%s", strings.ReplaceAll(key, "$HOME", home), value),
)
}

args = append(args, yeyCtx.Image)
args = append(args, yeyCtx.Cmd...)

return attachStdPipes(exec.CommandContext(ctx, "docker", args...)).Run()
}

func startContainer(ctx context.Context, containerName string) error {
return attachStdPipes(exec.CommandContext(ctx, "docker", "start", "-i", containerName)).Run()
}

func execContainer(ctx context.Context, containerName string, cmd []string) error {
args := append([]string{"exec", "-ti", containerName}, cmd...)
return attachStdPipes(exec.CommandContext(ctx, "docker", args...)).Run()
}

func attachStdPipes(cmd *exec.Cmd) *exec.Cmd {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
return cmd
}

0 comments on commit 2653845

Please sign in to comment.