dockerfile: add syntax directive for introducing new features
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>docker-18.09
parent
fc888e6413
commit
460fb33da7
|
@ -116,6 +116,13 @@ func Build(ctx context.Context, c client.Client) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := c.Opts()["cmdline"]; !ok {
|
||||||
|
ref, cmdline, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile))
|
||||||
|
if ok {
|
||||||
|
return forwardGateway(ctx, c, ref, cmdline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
st, img, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, dockerfile2llb.ConvertOpt{
|
st, img, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, dockerfile2llb.ConvertOpt{
|
||||||
Target: opts[keyTarget],
|
Target: opts[keyTarget],
|
||||||
MetaResolver: c,
|
MetaResolver: c,
|
||||||
|
@ -158,6 +165,20 @@ func Build(ctx context.Context, c client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func forwardGateway(ctx context.Context, c client.Client, ref string, cmdline string) error {
|
||||||
|
opts := c.Opts()
|
||||||
|
if opts == nil {
|
||||||
|
opts = map[string]string{}
|
||||||
|
}
|
||||||
|
opts["cmdline"] = cmdline
|
||||||
|
opts["source"] = ref
|
||||||
|
_, err := c.Solve(ctx, client.SolveRequest{
|
||||||
|
Frontend: "gateway.v0",
|
||||||
|
FrontendOpt: opts,
|
||||||
|
}, nil, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func filter(opt map[string]string, key string) map[string]string {
|
func filter(opt map[string]string, key string) map[string]string {
|
||||||
m := map[string]string{}
|
m := map[string]string{}
|
||||||
for k, v := range opt {
|
for k, v := range opt {
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package dockerfile2llb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const keySyntax = "syntax"
|
||||||
|
|
||||||
|
var reDirective = regexp.MustCompile(`^#\s*([a-zA-Z][a-zA-Z0-9]*)\s*=\s*(.+?)\s*$`)
|
||||||
|
|
||||||
|
func DetectSyntax(r io.Reader) (string, string, bool) {
|
||||||
|
directives := ParseDirectives(r)
|
||||||
|
if len(directives) == 0 {
|
||||||
|
return "", "", false
|
||||||
|
}
|
||||||
|
v, ok := directives[keySyntax]
|
||||||
|
if !ok {
|
||||||
|
return "", "", false
|
||||||
|
}
|
||||||
|
p := strings.SplitN(v, " ", 2)
|
||||||
|
return p[0], v, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDirectives(r io.Reader) map[string]string {
|
||||||
|
m := map[string]string{}
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
for s.Scan() {
|
||||||
|
match := reDirective.FindStringSubmatch(s.Text())
|
||||||
|
if len(match) == 0 {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
m[strings.ToLower(match[1])] = match[2]
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package dockerfile2llb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDirectives(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
dt := `#escape=\
|
||||||
|
# key = FOO bar
|
||||||
|
|
||||||
|
# smth
|
||||||
|
`
|
||||||
|
|
||||||
|
d := ParseDirectives(bytes.NewBuffer([]byte(dt)))
|
||||||
|
require.Equal(t, len(d), 2, fmt.Sprintf("%+v", d))
|
||||||
|
|
||||||
|
v, ok := d["escape"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, v, "\\")
|
||||||
|
|
||||||
|
v, ok = d["key"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, v, "FOO bar")
|
||||||
|
|
||||||
|
// for some reason Moby implementation in case insensitive for escape
|
||||||
|
dt = `# EScape=\
|
||||||
|
# KEY = FOO bar
|
||||||
|
|
||||||
|
# smth
|
||||||
|
`
|
||||||
|
|
||||||
|
d = ParseDirectives(bytes.NewBuffer([]byte(dt)))
|
||||||
|
require.Equal(t, len(d), 2, fmt.Sprintf("%+v", d))
|
||||||
|
|
||||||
|
v, ok = d["escape"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, v, "\\")
|
||||||
|
|
||||||
|
v, ok = d["key"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, v, "FOO bar")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyntaxDirective(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
dt := `# syntax = dockerfile:experimental // opts
|
||||||
|
FROM busybox
|
||||||
|
`
|
||||||
|
|
||||||
|
ref, cmdline, ok := DetectSyntax(bytes.NewBuffer([]byte(dt)))
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, ref, "dockerfile:experimental")
|
||||||
|
require.Equal(t, cmdline, "dockerfile:experimental // opts")
|
||||||
|
|
||||||
|
dt = `FROM busybox
|
||||||
|
RUN ls
|
||||||
|
`
|
||||||
|
ref, cmdline, ok = DetectSyntax(bytes.NewBuffer([]byte(dt)))
|
||||||
|
require.False(t, ok)
|
||||||
|
require.Equal(t, ref, "")
|
||||||
|
require.Equal(t, cmdline, "")
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue