Skip to content

Commit

Permalink
Merge pull request #17 from silphid/work-dir
Browse files Browse the repository at this point in the history
Synchronize run work dir with external work dir
  • Loading branch information
silphid authored Jun 1, 2021
2 parents f9b31c4 + 193eff1 commit c5f9dc8
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 28 deletions.
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// Utilisez IntelliSense pour en savoir plus sur les attributs possibles.
// Pointez pour afficher la description des attributs existants.
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug yey run",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/src",
"args": ["run"],
"cwd": "${workspaceFolder}"
}
]
}
2 changes: 1 addition & 1 deletion dev/build
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
go build -ldflags "-X main.version=dev-$(date +%F-%T)" -o /usr/local/bin/yeydev ./src
go build -ldflags "-X main.version=dev-$(date +%F-%T)" -o /usr/local/bin/yey ./src
36 changes: 35 additions & 1 deletion src/cmd/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

yey "github.com/silphid/yey/src/internal"
"github.com/silphid/yey/src/internal/docker"
Expand Down Expand Up @@ -84,7 +86,39 @@ func run(ctx context.Context, name string, options Options) error {
}
}

return docker.Start(ctx, yeyContext, containerName)
workDir, err := getContainerWorkDir(yeyContext)
if err != nil {
return err
}

var runOptions []docker.RunOption
if workDir != "" {
runOptions = append(runOptions, docker.WithWorkDir(workDir))
}

return docker.Start(ctx, yeyContext, containerName, runOptions...)
}

func getContainerWorkDir(yeyContext yey.Context) (string, error) {
workDir, err := os.Getwd()
if err != nil {
return "", err
}

for key, value := range yeyContext.Mounts {
// Where is work dir relatively to mount dir?
subDir, err := filepath.Rel(key, workDir)
if err != nil {
return "", err
}

// Is work dir within mount dir?
if !strings.HasPrefix(subDir, fmt.Sprintf("..%c", filepath.Separator)) {
return filepath.Join(value, subDir), nil
}
}

return "", nil
}

func readAndBuildDockerfile(ctx context.Context, build yey.DockerBuild) (string, error) {
Expand Down
72 changes: 59 additions & 13 deletions src/internal/contextFile.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ func parseContextFile(dir string, data []byte) (Contexts, error) {
}

if dir != "" {
contexts.Context = resolveContextPaths(dir, contexts.Context)
for name, context := range contexts.Named {
contexts.Named[name] = resolveContextPaths(dir, context)
var err error
contexts, err = resolveContextsPaths(dir, contexts)
if err != nil {
return Contexts{}, err
}
}

Expand Down Expand Up @@ -145,24 +146,69 @@ func LoadContexts() (Contexts, error) {
return contexts, nil
}

func resolveContextPaths(dir string, context Context) Context {
func resolveContextsPaths(dir string, contexts Contexts) (Contexts, error) {
var err error
contexts.Context, err = resolveContextPaths(dir, contexts.Context)
if err != nil {
return Contexts{}, err
}
for name, context := range contexts.Named {
contexts.Named[name], err = resolveContextPaths(dir, context)
if err != nil {
return Contexts{}, err
}
}
return contexts, nil
}

func resolveContextPaths(dir string, context Context) (Context, error) {
clone := context.Clone()
clone.Build.Dockerfile = resolvePath(dir, context.Build.Dockerfile)
clone.Build.Context = resolvePath(dir, clone.Build.Context)
for key, value := range clone.Mounts {
clone.Mounts[resolvePath(dir, key)] = value

// Resolve dockerfile path
var err error
clone.Build.Dockerfile, err = resolvePath(dir, context.Build.Dockerfile)
if err != nil {
return Context{}, err
}
return clone

// Resolve build context dir
clone.Build.Context, err = resolvePath(dir, clone.Build.Context)
if err != nil {
return Context{}, err
}

// Resolve mount dirs
clone.Mounts = make(map[string]string, len(context.Mounts))
for key, value := range context.Mounts {
key, err = resolvePath(dir, key)
if err != nil {
return Context{}, err
}
clone.Mounts[key] = value
}

return clone, nil
}

func resolvePath(dir, path string) string {
func resolvePath(dir, path string) (string, error) {
if path == "" {
return ""
return "", nil
}

// Resolve home dir
var err error
if path == "~" {
path, err = homedir.Dir()
} else {
path, err = homedir.Expand(path)
}
if err != nil {
return "", err
}

if filepath.IsAbs(path) {
return path
return path, nil
}

return filepath.Join(dir, path)
return filepath.Join(dir, path), nil
}
47 changes: 34 additions & 13 deletions src/internal/docker/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,28 @@ import (
"regexp"
"strings"

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

func Start(ctx context.Context, yeyCtx yey.Context, containerName string) error {
type runOptions struct {
workDir string
}

type RunOption func(*runOptions)

func WithWorkDir(wd string) RunOption {
return func(ro *runOptions) {
ro.workDir = wd
}
}

func Start(ctx context.Context, yeyCtx yey.Context, containerName string, opts ...RunOption) error {
var options runOptions
for _, opt := range opts {
opt(&options)
}

// Determine whether we need to run or exec container
status, err := getContainerStatus(ctx, containerName)
if err != nil {
Expand All @@ -24,11 +40,11 @@ func Start(ctx context.Context, yeyCtx yey.Context, containerName string) error

switch status {
case "":
return runContainer(ctx, yeyCtx, containerName)
return runContainer(ctx, yeyCtx, containerName, options)
case "exited":
return startContainer(ctx, containerName)
case "running":
return execContainer(ctx, containerName, yeyCtx.Cmd)
return execContainer(ctx, containerName, yeyCtx.Cmd, options)
default:
return fmt.Errorf("container %q in unexpected state %q", containerName, status)
}
Expand Down Expand Up @@ -106,7 +122,7 @@ func getContainerStatus(ctx context.Context, name string) (string, error) {
return strings.TrimSpace(string(output)), nil
}

func runContainer(ctx context.Context, yeyCtx yey.Context, containerName string) error {
func runContainer(ctx context.Context, yeyCtx yey.Context, containerName string, options runOptions) error {
cwd, err := os.Getwd()
if err != nil {
return err
Expand All @@ -129,23 +145,23 @@ func runContainer(ctx context.Context, yeyCtx yey.Context, containerName string)
args = append(args, "--env", fmt.Sprintf("%s=%s", name, value))
}

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

// Mount binds
for key, value := range yeyCtx.Mounts {
args = append(
args,
"--volume",
fmt.Sprintf("%s:%s", strings.ReplaceAll(key, "$HOME", home), value),
fmt.Sprintf("%s:%s", key, value),
)
}

if yeyCtx.Remove != nil && *yeyCtx.Remove {
args = append(args, "--rm")
}

if options.workDir != "" {
args = append(args, "--workdir", options.workDir)
}

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

Expand All @@ -156,8 +172,13 @@ 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...)
func execContainer(ctx context.Context, containerName string, cmd []string, options runOptions) error {
args := []string{"exec", "-ti"}
if options.workDir != "" {
args = append(args, "--workdir", options.workDir)
}
args = append(args, containerName)
args = append(args, cmd...)
return attachStdPipes(exec.CommandContext(ctx, "docker", args...)).Run()
}

Expand Down

0 comments on commit c5f9dc8

Please sign in to comment.