Skip to content

Commit 66735c6

Browse files
authored
Merge pull request #5952 from jsternberg/v0.21.1-picks
[v0.21] cherry-picks for v0.21.1
2 parents 52b004d + 73bda6d commit 66735c6

7 files changed

Lines changed: 235 additions & 39 deletions

File tree

cmd/buildctl/common/common.go

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,38 +30,25 @@ func ResolveClient(c *cli.Context) (*client.Client, error) {
3030
serverName = uri.Hostname()
3131
}
3232

33-
var caCert string
34-
var cert string
35-
var key string
33+
var (
34+
caCert string
35+
cert string
36+
key string
37+
err error
38+
)
3639

3740
tlsDir := c.GlobalString("tlsdir")
3841

3942
if tlsDir != "" {
40-
// Look for ca.pem or ca.crt and, if it exists, set caCert to that
41-
// Look for cert.pem or tls.crt and, if it exists, set cert to that
42-
// Look for key.pem or tls.key and, if it exists, set key to that
43-
for _, v := range [6]string{"ca.pem", "cert.pem", "key.pem", "ca.crt", "tls.crt", "tls.key"} {
44-
file := filepath.Join(tlsDir, v)
45-
if _, err := os.Stat(file); err == nil {
46-
switch v {
47-
case "ca.pem":
48-
case "ca.crt":
49-
caCert = file
50-
case "cert.pem":
51-
case "tls.crt":
52-
cert = file
53-
case "key.pem":
54-
case "tls.key":
55-
key = file
56-
}
57-
} else {
58-
return nil, err
59-
}
60-
}
61-
43+
// Fail straight away if TLS was specified both ways
6244
if c.GlobalString("tlscacert") != "" || c.GlobalString("tlscert") != "" || c.GlobalString("tlskey") != "" {
6345
return nil, errors.New("cannot specify tlsdir and tlscacert/tlscert/tlskey at the same time")
6446
}
47+
48+
caCert, cert, key, err = resolveTLSFilesFromDir(tlsDir)
49+
if err != nil {
50+
return nil, err
51+
}
6552
} else {
6653
caCert = c.GlobalString("tlscacert")
6754
cert = c.GlobalString("tlscert")
@@ -128,3 +115,29 @@ func ParseTemplate(format string) (*template.Template, error) {
128115
}
129116
return template.New("").Funcs(funcs).Parse(format)
130117
}
118+
119+
// resolveTLSFilesFromDir scans a TLS directory for known cert/key filenames.
120+
func resolveTLSFilesFromDir(tlsDir string) (caCert, cert, key string, err error) {
121+
oneOf := func(either, or string) (string, error) {
122+
for _, name := range []string{either, or} {
123+
fpath := filepath.Join(tlsDir, name)
124+
if _, err := os.Stat(fpath); err == nil {
125+
return fpath, nil
126+
} else if !os.IsNotExist(err) {
127+
return "", err
128+
}
129+
}
130+
return "", errors.Errorf("directory did not contain one of the needed files: %s or %s", either, or)
131+
}
132+
133+
if caCert, err = oneOf("ca.pem", "ca.crt"); err != nil {
134+
return "", "", "", err
135+
}
136+
if cert, err = oneOf("cert.pem", "tls.crt"); err != nil {
137+
return "", "", "", err
138+
}
139+
if key, err = oneOf("key.pem", "tls.key"); err != nil {
140+
return "", "", "", err
141+
}
142+
return caCert, cert, key, nil
143+
}

cmd/buildctl/common/common_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package common
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func writeTempFile(t *testing.T, dir, name, content string) string {
12+
t.Helper()
13+
path := filepath.Join(dir, name)
14+
require.NoError(t, os.WriteFile(path, []byte(content), 0644))
15+
return path
16+
}
17+
18+
func TestResolveTLSFilesFromDir(t *testing.T) {
19+
t.Run("all files present for cert-manager style", func(t *testing.T) {
20+
dir := t.TempDir()
21+
ca := writeTempFile(t, dir, "ca.crt", "ca")
22+
cert := writeTempFile(t, dir, "tls.crt", "cert")
23+
key := writeTempFile(t, dir, "tls.key", "key")
24+
25+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
26+
require.Equal(t, ca, caOut)
27+
require.Equal(t, cert, certOut)
28+
require.Equal(t, key, keyOut)
29+
require.NoError(t, err)
30+
})
31+
32+
t.Run("all files present for pem style", func(t *testing.T) {
33+
dir := t.TempDir()
34+
ca := writeTempFile(t, dir, "ca.pem", "ca")
35+
cert := writeTempFile(t, dir, "cert.pem", "cert")
36+
key := writeTempFile(t, dir, "key.pem", "key")
37+
38+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
39+
require.Equal(t, ca, caOut)
40+
require.Equal(t, cert, certOut)
41+
require.Equal(t, key, keyOut)
42+
require.NoError(t, err)
43+
})
44+
45+
t.Run("mixed set is present", func(t *testing.T) {
46+
dir := t.TempDir()
47+
ca := writeTempFile(t, dir, "ca.crt", "ca-cert-manager")
48+
cert := writeTempFile(t, dir, "cert.pem", "cert-pem")
49+
key := writeTempFile(t, dir, "key.pem", "key-pem")
50+
// ca for cert-manager, cert and key for pem
51+
52+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
53+
require.Equal(t, ca, caOut)
54+
require.Equal(t, cert, certOut)
55+
require.Equal(t, key, keyOut)
56+
require.NoError(t, err)
57+
})
58+
59+
t.Run("all files present for cert-manager and pem styles and pem is chosen", func(t *testing.T) {
60+
dir := t.TempDir()
61+
writeTempFile(t, dir, "ca.crt", "ca-cert-manager")
62+
writeTempFile(t, dir, "tls.crt", "cert-cert-manager")
63+
writeTempFile(t, dir, "tls.key", "key-cert-manager")
64+
ca := writeTempFile(t, dir, "ca.pem", "ca-pem")
65+
cert := writeTempFile(t, dir, "cert.pem", "cert-pem")
66+
key := writeTempFile(t, dir, "key.pem", "key-pem")
67+
68+
caOut, certOut, keyOut, err := resolveTLSFilesFromDir(dir)
69+
require.Equal(t, ca, caOut)
70+
require.Equal(t, cert, certOut)
71+
require.Equal(t, key, keyOut)
72+
require.NoError(t, err)
73+
})
74+
}

cmd/buildctl/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func main() {
8787
},
8888
cli.StringFlag{
8989
Name: "tlsdir",
90-
Usage: "directory containing CA certificate, client certificate, and client key",
90+
Usage: "directory containing CA certificate, client certificate, and client key. Supported file names are (ca.pem, cert.pem, key.pem) or (ca.crt, tls.crt, tls.key)",
9191
Value: "",
9292
},
9393
cli.IntFlag{

control/control.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
376376
atomic.AddInt64(&c.buildCount, 1)
377377
defer atomic.AddInt64(&c.buildCount, -1)
378378

379+
if req.Cache == nil {
380+
req.Cache = &controlapi.CacheOptions{} // make sure cache options are initialized
381+
}
379382
translateLegacySolveRequest(req)
380383

381384
defer func() {

docs/reference/buildctl.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ GLOBAL OPTIONS:
2929
--tlscacert value CA certificate for validation
3030
--tlscert value client certificate
3131
--tlskey value client key
32-
--tlsdir value directory containing CA certificate, client certificate, and client key
32+
--tlsdir value directory containing CA certificate, client certificate, and client key. Supported file names are (ca.pem, cert.pem, key.pem) or (ca.crt, tls.crt, tls.key)
3333
--timeout value timeout backend connection after value seconds (default: 5)
3434
--wait block RPCs until the connection becomes available
3535
--help, -h show help

frontend/dockerui/build.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,12 @@ func (bc *Client) Build(ctx context.Context, fn BuildFunc) (*ResultBuilder, erro
6161
} else {
6262
p = platforms.DefaultSpec()
6363
}
64-
65-
k := platforms.FormatAll(p)
66-
p = extendWindowsPlatform(p, img.Platform)
67-
p = platforms.Normalize(p)
68-
64+
expPlat := makeExportPlatform(p, img.Platform)
6965
if bc.MultiPlatformRequested {
70-
res.AddRef(k, ref)
71-
res.AddMeta(fmt.Sprintf("%s/%s", exptypes.ExporterImageConfigKey, k), config)
66+
res.AddRef(expPlat.ID, ref)
67+
res.AddMeta(fmt.Sprintf("%s/%s", exptypes.ExporterImageConfigKey, expPlat.ID), config)
7268
if len(baseConfig) > 0 {
73-
res.AddMeta(fmt.Sprintf("%s/%s", exptypes.ExporterImageBaseConfigKey, k), baseConfig)
69+
res.AddMeta(fmt.Sprintf("%s/%s", exptypes.ExporterImageBaseConfigKey, expPlat.ID), baseConfig)
7470
}
7571
} else {
7672
res.SetRef(ref)
@@ -79,10 +75,7 @@ func (bc *Client) Build(ctx context.Context, fn BuildFunc) (*ResultBuilder, erro
7975
res.AddMeta(exptypes.ExporterImageBaseConfigKey, baseConfig)
8076
}
8177
}
82-
expPlatforms.Platforms[i] = exptypes.Platform{
83-
ID: k,
84-
Platform: p,
85-
}
78+
expPlatforms.Platforms[i] = expPlat
8679
return nil
8780
})
8881
}
@@ -133,3 +126,16 @@ func extendWindowsPlatform(p, imgP ocispecs.Platform) ocispecs.Platform {
133126
}
134127
return p
135128
}
129+
130+
func makeExportPlatform(p, imgP ocispecs.Platform) exptypes.Platform {
131+
p = platforms.Normalize(p)
132+
exp := exptypes.Platform{
133+
ID: platforms.FormatAll(p),
134+
}
135+
if p.OS == "windows" {
136+
p = extendWindowsPlatform(p, imgP)
137+
p = platforms.Normalize(p)
138+
}
139+
exp.Platform = p
140+
return exp
141+
}

frontend/dockerui/build_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package dockerui
2+
3+
import (
4+
"testing"
5+
6+
"github.com/containerd/platforms"
7+
"github.com/moby/buildkit/exporter/containerimage/exptypes"
8+
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestNormalizePlatform(t *testing.T) {
13+
testCases := []struct {
14+
p, imgP ocispecs.Platform
15+
expected exptypes.Platform
16+
}{
17+
{
18+
p: ocispecs.Platform{
19+
Architecture: "arm64",
20+
OS: "linux",
21+
Variant: "v8",
22+
},
23+
imgP: ocispecs.Platform{
24+
Architecture: "arm64",
25+
OS: "linux",
26+
},
27+
expected: exptypes.Platform{
28+
ID: "linux/arm64", // Not "linux/arm64/v8" https://github.com/moby/buildkit/issues/5915
29+
Platform: ocispecs.Platform{
30+
Architecture: "arm64",
31+
OS: "linux",
32+
},
33+
},
34+
},
35+
{
36+
p: ocispecs.Platform{
37+
Architecture: "arm64",
38+
OS: "linux",
39+
Variant: "v8",
40+
},
41+
imgP: ocispecs.Platform{
42+
Architecture: "arm64",
43+
OS: "linux",
44+
Variant: "v8",
45+
},
46+
expected: exptypes.Platform{
47+
ID: "linux/arm64",
48+
Platform: ocispecs.Platform{
49+
Architecture: "arm64",
50+
OS: "linux",
51+
},
52+
},
53+
},
54+
{
55+
p: ocispecs.Platform{
56+
Architecture: "amd64",
57+
OS: "windows",
58+
},
59+
imgP: ocispecs.Platform{
60+
Architecture: "amd64",
61+
OS: "windows",
62+
OSVersion: "10.0.19041.0",
63+
},
64+
expected: exptypes.Platform{
65+
ID: "windows/amd64",
66+
Platform: ocispecs.Platform{
67+
Architecture: "amd64",
68+
OS: "windows",
69+
OSVersion: "10.0.19041.0",
70+
},
71+
},
72+
},
73+
{
74+
p: ocispecs.Platform{
75+
Architecture: "amd64",
76+
OS: "windows",
77+
OSVersion: "10.0.19041.0",
78+
},
79+
imgP: ocispecs.Platform{
80+
Architecture: "amd64",
81+
OS: "windows",
82+
OSVersion: "11.0.22000.0",
83+
},
84+
expected: exptypes.Platform{
85+
ID: "windows(10.0.19041.0)/amd64",
86+
Platform: ocispecs.Platform{
87+
Architecture: "amd64",
88+
OS: "windows",
89+
OSVersion: "10.0.19041.0",
90+
},
91+
},
92+
},
93+
}
94+
95+
for _, tc := range testCases {
96+
require.Equal(t, tc.expected, makeExportPlatform(tc.p, tc.imgP))
97+
// the ID needs to always be formatall(normalize(p))
98+
require.Equal(t, platforms.FormatAll(platforms.Normalize(tc.p)), tc.expected.ID)
99+
}
100+
}

0 commit comments

Comments
 (0)