Skip to content

Commit

Permalink
dockerfile from stdin
Browse files Browse the repository at this point in the history
Signed-off-by: fahed dorgaa <fahed.dorgaa@gmail.com>

fixes

Signed-off-by: fahed dorgaa <fahed.dorgaa@gmail.com>
  • Loading branch information
fahedouch committed Oct 19, 2021
1 parent 447f1c0 commit 8ac9454
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 20 deletions.
61 changes: 41 additions & 20 deletions cmd/nerdctl/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,14 @@ func buildAction(cmd *cobra.Command, args []string) error {
return err
}

buildctlBinary, buildctlArgs, needsLoading, err := generateBuildctlArgs(cmd, args)
buildctlBinary, buildctlArgs, needsLoading, cleanup, err := generateBuildctlArgs(cmd, args)
if err != nil {
return err
}
if cleanup != nil {
defer cleanup()
}

quiet, err := cmd.Flags().GetBool("quiet")
if err != nil {
return err
Expand Down Expand Up @@ -118,50 +122,50 @@ func buildAction(cmd *cobra.Command, args []string) error {
return nil
}

func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string, bool, error) {
func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string, bool, func(), error) {
var needsLoading bool
if len(args) < 1 {
return "", nil, false, errors.New("context needs to be specified")
return "", nil, false, nil, errors.New("context needs to be specified")
}
buildContext := args[0]
if buildContext == "-" || strings.Contains(buildContext, "://") {
return "", nil, false, errors.Errorf("unsupported build context: %q", buildContext)
return "", nil, false, nil, errors.Errorf("unsupported build context: %q", buildContext)
}

buildctlBinary, err := buildkitutil.BuildctlBinary()
if err != nil {
return "", nil, false, err
return "", nil, false, nil, err
}

output, err := cmd.Flags().GetString("output")
if err != nil {
return "", nil, false, err
return "", nil, false, nil, err
}
if output == "" {
output = "type=docker"
needsLoading = true
}
tagValue, err := cmd.Flags().GetStringSlice("tag")
if err != nil {
return "", nil, false, err
return "", nil, false, nil, err
}
if tagSlice := strutil.DedupeStrSlice(tagValue); len(tagSlice) > 0 {
if len(tagSlice) > 1 {
return "", nil, false, errors.Errorf("specifying multiple -t is not supported yet")
return "", nil, false, nil, errors.Errorf("specifying multiple -t is not supported yet")
}
output += ",name=" + tagSlice[0]
}

buildkitHost, err := cmd.Flags().GetString("buildkit-host")
if err != nil {
return "", nil, false, err
return "", nil, false, nil, err
}

buildctlArgs := buildkitutil.BuildctlBaseArgs(buildkitHost)

progressValue, err := cmd.Flags().GetString("progress")
if err != nil {
return "", nil, false, err
return "", nil, false, nil, err
}

buildctlArgs = append(buildctlArgs, []string{
Expand All @@ -175,10 +179,27 @@ func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string,

filename, err := cmd.Flags().GetString("file")
if err != nil {
return "", nil, false, err
return "", nil, false, nil, err
}

var dir, file string
var cleanup func()

if filename != "" {
dir, file := filepath.Split(filename)
if filename == "-" {
var err error
dir, err = buildkitutil.WriteTempDockerfile(cmd.InOrStdin())
if err != nil {
return "", nil, false, nil, err
}
file = buildkitutil.DefaultDockerfileName
cleanup = func() {
os.RemoveAll(dir)
}
} else {
dir, file = filepath.Split(filename)
}

if dir != "" {
buildctlArgs = append(buildctlArgs, "--local=dockerfile="+dir)
}
Expand All @@ -187,15 +208,15 @@ func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string,

target, err := cmd.Flags().GetString("target")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
if target != "" {
buildctlArgs = append(buildctlArgs, "--opt=target="+target)
}

buildArgsValue, err := cmd.Flags().GetStringSlice("build-arg")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
for _, ba := range strutil.DedupeStrSlice(buildArgsValue) {
buildctlArgs = append(buildctlArgs, "--opt=build-arg:"+ba)
Expand All @@ -217,31 +238,31 @@ func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string,

noCache, err := cmd.Flags().GetBool("no-cache")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
if noCache {
buildctlArgs = append(buildctlArgs, "--no-cache")
}

secretValue, err := cmd.Flags().GetStringSlice("secret")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
for _, s := range strutil.DedupeStrSlice(secretValue) {
buildctlArgs = append(buildctlArgs, "--secret="+s)
}

sshValue, err := cmd.Flags().GetStringSlice("ssh")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
for _, s := range strutil.DedupeStrSlice(sshValue) {
buildctlArgs = append(buildctlArgs, "--ssh="+s)
}

cacheFrom, err := cmd.Flags().GetStringSlice("cache-from")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
for _, s := range strutil.DedupeStrSlice(cacheFrom) {
if !strings.Contains(s, "type=") {
Expand All @@ -252,7 +273,7 @@ func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string,

cacheTo, err := cmd.Flags().GetStringSlice("cache-to")
if err != nil {
return "", nil, false, err
return "", nil, false, cleanup, err
}
for _, s := range strutil.DedupeStrSlice(cacheTo) {
if !strings.Contains(s, "type=") {
Expand All @@ -261,5 +282,5 @@ func generateBuildctlArgs(cmd *cobra.Command, args []string) (string, []string,
buildctlArgs = append(buildctlArgs, "--export-cache="+s)
}

return buildctlBinary, buildctlArgs, needsLoading, nil
return buildctlBinary, buildctlArgs, needsLoading, cleanup, nil
}
14 changes: 14 additions & 0 deletions cmd/nerdctl/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"

"github.com/containerd/nerdctl/pkg/testutil"
Expand All @@ -47,6 +48,19 @@ CMD ["echo", "nerdctl-build-test-string"]
base.Cmd("run", "--rm", imageName).AssertOutContains("nerdctl-build-test-string")
}

func TestBuildFromStdin(t *testing.T) {
testutil.RequiresBuild(t)
base := testutil.NewBase(t)
const imageName = "nerdctl-build-stdin-test"
defer base.Cmd("rmi", imageName).Run()

dockerfile := fmt.Sprintf(`FROM %s
CMD ["echo", "nerdctl-build-test-stdin"]
`, testutil.AlpineImage)

base.Cmd("build", "-t", imageName, "-f", "-", ".").CmdOption(testutil.WithStdin(strings.NewReader(dockerfile))).AssertOutContains("nerdctl-build-stdin-test")
}

func TestBuildLocal(t *testing.T) {
testutil.DockerIncompatible(t)
testutil.RequiresBuild(t)
Expand Down
34 changes: 34 additions & 0 deletions pkg/buildkitutil/buildkitutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,24 @@
package buildkitutil

import (
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"

"github.com/containerd/nerdctl/pkg/rootlessutil"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)

const (
// DefaultDockerfileName is the Default filename, read by nerdctl build
DefaultDockerfileName string = "Dockerfile"

TempDockerfileName string = "docker-build-tempdockerfile-"
)

func BuildctlBinary() (string, error) {
return exec.LookPath("buildctl")
}
Expand Down Expand Up @@ -52,3 +62,27 @@ func PingBKDaemon(buildkitHost string) error {
}
return nil
}

// WriteTempDockerfile is from https://github.com/docker/cli/blob/master/cli/command/image/build/context.go#L118
func WriteTempDockerfile(rc io.Reader) (dockerfileDir string, err error) {
// err is a named return value, due to the defer call below.
dockerfileDir, err = ioutil.TempDir("", TempDockerfileName)
if err != nil {
return "", errors.Errorf("unable to create temporary context directory: %v", err)
}
defer func() {
if err != nil {
os.RemoveAll(dockerfileDir)
}
}()

f, err := os.Create(filepath.Join(dockerfileDir, DefaultDockerfileName))
if err != nil {
return "", err
}
defer f.Close()
if _, err := io.Copy(f, rc); err != nil {
return "", err
}
return dockerfileDir, nil
}
15 changes: 15 additions & 0 deletions pkg/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"os/exec"
"strings"
Expand All @@ -45,6 +46,13 @@ type Base struct {
Env []string
}

// WithStdin sets the standard input of Cmd to the specified reader
func WithStdin(r io.Reader) func(*Cmd) {
return func(i *Cmd) {
i.Cmd.Stdin = r
}
}

func (b *Base) Cmd(args ...string) *Cmd {
icmdCmd := icmd.Command(b.Binary, append(b.Args, args...)...)
icmdCmd.Env = b.Env
Expand Down Expand Up @@ -219,6 +227,13 @@ func (c *Cmd) Run() *icmd.Result {
return icmd.RunCmd(c.Cmd)
}

func (c *Cmd) CmdOption(cmdOptions ...func(*Cmd)) *Cmd {
for _, opt := range cmdOptions {
opt(c)
}
return c
}

func (c *Cmd) Assert(expected icmd.Expected) {
c.Base.T.Helper()
c.Run().Assert(c.Base.T, expected)
Expand Down

0 comments on commit 8ac9454

Please sign in to comment.