Skip to content

Commit 1e8e66e

Browse files
get-deps: fill REL_HASH_* from linuxkit
otherwise get-deps cannot detect dependencies Signed-off-by: Christoph Ostarek <[email protected]>
1 parent b693fda commit 1e8e66e

File tree

2 files changed

+169
-30
lines changed

2 files changed

+169
-30
lines changed

tools/get-deps/lktargs.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"io"
7+
"os"
8+
"path/filepath"
9+
10+
"github.com/linuxkit/linuxkit/src/cmd/linuxkit/pkglib"
11+
"github.com/linuxkit/linuxkit/src/cmd/linuxkit/spec"
12+
buildkitClient "github.com/moby/buildkit/client"
13+
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
14+
)
15+
16+
const (
17+
defaultPkgBuildYML = "build.yml"
18+
defaultPkgCommit = "HEAD"
19+
defaultPkgTag = "{{.Hash}}"
20+
defaultBuilderImage = "moby/buildkit:v0.12.3"
21+
)
22+
23+
// heavily inspired by src/cmd/linuxkit/pkglib/dockerdryrun.go
24+
type buildArgsDockerRunner struct {
25+
buildArgs map[string]string
26+
}
27+
28+
func (dr *buildArgsDockerRunner) Builder(
29+
ctx context.Context,
30+
dockerContext, builderImage, builderConfigPath, platform string,
31+
restart bool,
32+
) (*buildkitClient.Client, error) {
33+
return nil, nil
34+
}
35+
36+
func (dr *buildArgsDockerRunner) Pull(img string) (bool, error) {
37+
return false, errors.New("not implemented")
38+
}
39+
40+
func (dr *buildArgsDockerRunner) Tag(ref, tag string) error {
41+
return errors.New("not implemented")
42+
}
43+
44+
func (dr *buildArgsDockerRunner) Build(
45+
ctx context.Context,
46+
tag, pkg, dockerContext, builderImage, builderConfigPath, platform string,
47+
restart, preCacheImages bool,
48+
c spec.CacheProvider,
49+
r io.Reader,
50+
stdout io.Writer,
51+
sbomScan bool,
52+
sbomScannerImage, platformType string,
53+
imageBuildOpts spec.ImageBuildOptions,
54+
) error {
55+
for k, v := range imageBuildOpts.BuildArgs {
56+
dr.buildArgs[k] = *v
57+
}
58+
59+
return nil
60+
}
61+
62+
func (dr *buildArgsDockerRunner) Save(tgt string, refs ...string) error {
63+
return errors.New("not implemented")
64+
}
65+
66+
func (dr *buildArgsDockerRunner) Load(src io.Reader) error {
67+
return errors.New("not implemented")
68+
}
69+
70+
func (dr *buildArgsDockerRunner) ContextSupportCheck() error {
71+
return nil
72+
}
73+
74+
func lktBuildArgs(ymlPath string) map[string]string {
75+
76+
ymlBuildFile := filepath.Base(ymlPath)
77+
78+
pkglibConfig := pkglib.PkglibConfig{
79+
BuildYML: ymlBuildFile,
80+
HashCommit: defaultPkgCommit,
81+
Dev: false,
82+
Tag: defaultPkgTag,
83+
}
84+
pkgs, err := pkglib.NewFromConfig(pkglibConfig, filepath.Dir(ymlPath))
85+
if err != nil {
86+
panic(err)
87+
// silently ignore that this is not a linuxkit package
88+
}
89+
90+
var opts []pkglib.BuildOpt
91+
92+
badr := &buildArgsDockerRunner{
93+
buildArgs: map[string]string{},
94+
}
95+
96+
opts = append(opts, pkglib.WithBuildDocker(badr))
97+
opts = append(opts, pkglib.WithDryRun())
98+
tmpDir := os.TempDir()
99+
defer os.RemoveAll(tmpDir)
100+
opts = append(opts, pkglib.WithBuildCacheDir(tmpDir))
101+
opts = append(opts, pkglib.WithBuildSbomScanner("")) // but why?
102+
opts = append(opts, pkglib.WithBuildBuilderImage(defaultBuilderImage))
103+
opts = append(opts, pkglib.WithBuildBuilderRestart(false))
104+
opts = append(opts, pkglib.WithProgress("auto"))
105+
106+
for _, pkg := range pkgs {
107+
plats := []imagespec.Platform{{OS: TARGETOS, Architecture: TARGETARCH}}
108+
109+
var (
110+
pkgPlats = make([]imagespec.Platform, len(plats))
111+
)
112+
copy(pkgPlats, plats)
113+
// unless overridden, platforms are specific to a package, so this needs to be inside the for loop
114+
115+
// if there are no platforms to build for, do nothing.
116+
// note that this is *not* an error; we simply skip it
117+
if len(pkgPlats) == 0 {
118+
// fmt.Printf("Skipping %s with no architectures to build\n", p.Tag())
119+
continue
120+
}
121+
122+
opts = append(opts, pkglib.WithBuildPlatforms(pkgPlats...))
123+
124+
pkg.ProcessBuildArgs()
125+
126+
err := pkg.Build(opts...)
127+
if err != nil {
128+
panic(err)
129+
}
130+
}
131+
132+
return badr.buildArgs
133+
}

tools/get-deps/main.go

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ package main
55

66
import (
77
"bytes"
8+
"errors"
89
"flag"
910
"fmt"
10-
"io"
1111
"log"
1212
"os"
1313
"os/exec"
@@ -99,9 +99,13 @@ func (aeg *argsEnvGetter) Keys() []string {
9999
return keys
100100
}
101101

102-
func parseDockerfile(f io.Reader) []string {
103-
dt, err := io.ReadAll(f)
102+
func parseDockerfile(pkgName string) []string {
103+
dockerfilePath := filepath.Join(pkgName, "Dockerfile")
104+
dt, err := os.ReadFile(dockerfilePath)
104105
if err != nil {
106+
if errors.Is(err, os.ErrNotExist) {
107+
return []string{}
108+
}
105109
panic(err)
106110
}
107111

@@ -111,19 +115,38 @@ func parseDockerfile(f io.Reader) []string {
111115
}
112116
stages, metaArgs, err := instructions.Parse(dockerfile.AST, nil)
113117
if err != nil {
114-
panic(err)
118+
log.Fatalf("parsing instructions of %s failed: %v", dockerfilePath, err)
119+
}
120+
121+
aeg := createDockerEnvGetter(filepath.Join(pkgName, "build.yml"), metaArgs)
122+
123+
shlex := shell.NewLex(dockerfile.EscapeToken)
124+
125+
targetsMap := make(map[string]struct{})
126+
for _, st := range stages {
127+
pResult, err := shlex.ProcessWordWithMatches(st.BaseName, &aeg)
128+
if err != nil {
129+
panic(err)
130+
}
131+
targetsMap[pResult.Result] = struct{}{}
132+
}
133+
targets := make([]string, 0)
134+
for target := range targetsMap {
135+
targets = append(targets, target)
115136
}
137+
return targets
138+
}
116139

140+
func createDockerEnvGetter(buildYmlFile string, metaArgs []instructions.ArgCommand) argsEnvGetter {
117141
buildPlatform := []ocispecs.Platform{platforms.DefaultSpec()}[0]
118142
targetPlatform := ocispecs.Platform{
119143
Architecture: TARGETARCH,
120144
OS: TARGETOS,
121145
Variant: TARGETVARIANT,
122146
}
123147

124-
// from github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/platform.go:getPlatformArgs
125148
aeg := argsEnvGetter{
126-
// args: map[string]string{},
149+
// from github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/platform.go:getPlatformArgs
127150
args: map[string]string{
128151
"BUILDPLATFORM": platforms.Format(buildPlatform),
129152
"BUILDOS": buildPlatform.OS,
@@ -143,21 +166,11 @@ func parseDockerfile(f io.Reader) []string {
143166
}
144167
}
145168

146-
shlex := shell.NewLex(dockerfile.EscapeToken)
147-
148-
targetsMap := make(map[string]struct{})
149-
for _, st := range stages {
150-
pResult, err := shlex.ProcessWordWithMatches(st.BaseName, &aeg)
151-
if err != nil {
152-
panic(err)
153-
}
154-
targetsMap[pResult.Result] = struct{}{}
169+
for k, v := range lktBuildArgs(buildYmlFile) {
170+
aeg.args[k] = v
155171
}
156-
targets := make([]string, 0)
157-
for target := range targetsMap {
158-
targets = append(targets, target)
159-
}
160-
return targets
172+
173+
return aeg
161174
}
162175

163176
// Print a single dependency package, only suitable for dot file
@@ -243,15 +256,8 @@ func filterPkg(deps []string) []string {
243256
}
244257

245258
// Return a list of all dependencies (packages) listed in a Dockerfile
246-
func getDeps(dockerfile string) []string {
247-
var depList []string
248-
f, err := os.Open(dockerfile)
249-
if err != nil {
250-
fmt.Println(err)
251-
return depList
252-
}
253-
defer f.Close()
254-
ss := parseDockerfile(f)
259+
func getDeps(pkgName string) []string {
260+
ss := parseDockerfile(pkgName)
255261

256262
return filterPkg(ss)
257263
}
@@ -347,7 +353,7 @@ func main() {
347353

348354
// Get package dependencies from Dockerfile
349355
writeToFile(outfile, p.printSingleDep(pkgName))
350-
depList := getDeps(dockerFile)
356+
depList := getDeps(pkgName)
351357
for _, d := range depList {
352358
if d != pkgName {
353359
// Write a single dependency of the package

0 commit comments

Comments
 (0)