Skip to content

Commit

Permalink
support dockerfiles
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmdm committed May 28, 2021
1 parent 1a2e033 commit 28b7983
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 4 deletions.
3 changes: 3 additions & 0 deletions examples/buildexample/.yeyrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build:
dockerfile: ./Dockerfile
context: .
3 changes: 3 additions & 0 deletions examples/buildexample/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM ubuntu:latest

CMD ["bash"]
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/silphid/yey

go 1.14
go 1.16

require (
github.com/AlecAivazis/survey/v2 v2.2.12
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
Expand Down
26 changes: 26 additions & 0 deletions src/cmd/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package run
import (
"context"
"fmt"
"os"

yey "github.com/silphid/yey/src/internal"
"github.com/silphid/yey/src/internal/docker"
"github.com/silphid/yey/src/internal/logging"

"github.com/silphid/yey/src/cmd"

Expand Down Expand Up @@ -65,6 +67,15 @@ func run(ctx context.Context, name string, options Options) error {
yeyContext.Remove = options.Remove
}

if yeyContext.Image == "" {
var err error
yeyContext.Image, err = readAndBuildDockerfile(ctx, yeyContext.Build)
if err != nil {
return fmt.Errorf("failed to build yey context image: %w", err)
}
logging.Log("built image: %s", yeyContext.Image)
}

containerName := yey.ContainerName(contexts.Path, yeyContext)

if options.Reset {
Expand All @@ -75,3 +86,18 @@ func run(ctx context.Context, name string, options Options) error {

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

func readAndBuildDockerfile(ctx context.Context, build yey.DockerBuild) (string, error) {
dockerBytes, err := os.ReadFile(build.Dockerfile)
if err != nil {
return "", fmt.Errorf("failed to read dockerfile: %w", err)
}

imageName := yey.ImageName(dockerBytes)

if err := docker.Build(ctx, build.Dockerfile, imageName, build.Args, build.Context); err != nil {
return "", fmt.Errorf("failed to build image: %w", err)
}

return imageName, nil
}
17 changes: 17 additions & 0 deletions src/internal/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ import (
"gopkg.in/yaml.v2"
)

type DockerBuild struct {
Dockerfile string
Args map[string]string
Context string
}

// Context represents execution configuration for some docker container
type Context struct {
Name string `yaml:",omitempty"`
Remove *bool
Image string
Build DockerBuild
Env map[string]string
Mounts map[string]string
Cmd []string
Expand All @@ -30,6 +37,10 @@ func (c Context) Clone() Context {
for key, value := range c.Mounts {
clone.Mounts[key] = value
}
clone.Build.Args = make(map[string]string)
for key, value := range c.Build.Args {
clone.Build.Args[key] = value
}
return clone
}

Expand All @@ -49,6 +60,12 @@ func (c Context) Merge(source Context) Context {
for key, value := range source.Mounts {
merged.Mounts[key] = value
}
if source.Build.Dockerfile != "" {
merged.Build.Dockerfile = source.Build.Dockerfile
}
for key, value := range source.Build.Args {
merged.Build.Args[key] = value
}
return merged
}

Expand Down
35 changes: 32 additions & 3 deletions src/internal/contextFile.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func readContextFileFromNetwork(url string) ([]byte, error) {
}

// parseContextFile unmarshals the contextFile data and resolves any parent contextfiles
func parseContextFile(data []byte) (Contexts, error) {
func parseContextFile(root string, data []byte) (Contexts, error) {
var ctxFile ContextFile
if err := yaml.Unmarshal(data, &ctxFile); err != nil {
return Contexts{}, fmt.Errorf("failed to decode context file: %w", err)
Expand All @@ -89,6 +89,13 @@ func parseContextFile(data []byte) (Contexts, error) {
Named: ctxFile.Named,
}

if root != "" {
contexts.Context = resolveContextPaths(root, contexts.Context)
for name, context := range contexts.Named {
contexts.Named[name] = resolveContextPaths(root, context)
}
}

if ctxFile.Parent != "" {
parent, err := readAndParseContextFileFromURI(ctxFile.Parent)
if err != nil {
Expand All @@ -105,18 +112,20 @@ func parseContextFile(data []byte) (Contexts, error) {
func readAndParseContextFileFromURI(path string) (Contexts, error) {
var bytes []byte
var err error
var root string

if strings.HasPrefix(path, "https:") || strings.HasPrefix(path, "http:") {
bytes, err = readContextFileFromNetwork(path)
} else {
root = filepath.Dir(path)
bytes, err = readContextFileFromFilePath(path)
}

if err != nil {
return Contexts{}, fmt.Errorf("failed to read context file: %w", err)
}

return parseContextFile(bytes)
return parseContextFile(root, bytes)
}

// LoadContexts reads the context file and returns the contexts. It starts by reading from current
Expand All @@ -127,11 +136,31 @@ func LoadContexts() (Contexts, error) {
return Contexts{}, fmt.Errorf("failed to read context file: %w", err)
}

contexts, err := parseContextFile(bytes)
contexts, err := parseContextFile(filepath.Dir(path), bytes)
if err != nil {
return Contexts{}, err
}
contexts.Path = path

return contexts, nil
}

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

func resolvePath(root, path string) string {
if path == "" {
return ""
}
if strings.HasPrefix(path, "/") {
return path
}
return filepath.Join(root, path)
}
14 changes: 14 additions & 0 deletions src/internal/docker/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"

Expand Down Expand Up @@ -45,6 +46,19 @@ func Remove(ctx context.Context, containerName string) error {
return attachStdPipes(exec.CommandContext(ctx, "docker", "rm", "-v", containerName)).Run()
}

func Build(ctx context.Context, dockerPath string, imageName string, buildArgs map[string]string, context string) error {
args := []string{"build", "-f", dockerPath, "-t", imageName}
for key, value := range buildArgs {
args = append(args, "--build-arg", fmt.Sprintf("%s=%q", key, value))
}
if context == "" {
context = filepath.Dir(dockerPath)
}
args = append(args, context)

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

var newlines = regexp.MustCompile(`\r?\n`)

func ListContainers(ctx context.Context) ([]string, error) {
Expand Down
4 changes: 4 additions & 0 deletions src/internal/yey.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ func ContainerPathPrefix(path string) string {
}
return fmt.Sprintf("yey-%s-%s", pathBase, hash(path))
}

func ImageName(dockerfile []byte) string {
return fmt.Sprintf("yey-%s", hash(string(dockerfile)))
}

0 comments on commit 28b7983

Please sign in to comment.