Skip to content

Commit

Permalink
Add build.MultiArch.BuildPackageLists
Browse files Browse the repository at this point in the history
In the terraform module, we call BuildPackageList for each arch:
https://github.com/chainguard-dev/terraform-provider-apko/blob/812478b999411c183e87fefb9a9ece9fe7e8f2c1/internal/provider/config_data_source.go#L239

And then use that package list to actually build the image, so we
separate the solving from the building.

This bypasses chainguard-dev#1180 which
does this multi-arch constraining through a different entrypoint.

This adds another method to the multi-arch stuff that we can opt into
for just the solve part.

Signed-off-by: Jon Johnson <[email protected]>
  • Loading branch information
jonjohnsonjr committed Jul 10, 2024
1 parent fe1f30a commit a1f2de8
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 24 deletions.
36 changes: 14 additions & 22 deletions internal/cli/show-packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@ package cli
import (
"context"
"fmt"
"log/slog"
"os"
"path/filepath"
"text/template"

"github.com/spf13/cobra"
"golang.org/x/exp/slices"

"github.com/chainguard-dev/clog"

apkfs "chainguard.dev/apko/pkg/apk/fs"
"chainguard.dev/apko/pkg/build"
"chainguard.dev/apko/pkg/build/types"
)
Expand Down Expand Up @@ -166,25 +162,21 @@ func ShowPackagesCmd(ctx context.Context, format string, archs []types.Architect
return fmt.Errorf("failed to parse format: %w", err)
}

for _, arch := range archs {
arch := arch
log := clog.New(slog.Default().Handler()).With("arch", arch.ToAPK())
ctx = clog.WithLogger(ctx, log)

// working directory for this architecture
wd := filepath.Join(wd, arch.ToAPK())
bopts := slices.Clone(opts)
bopts = append(bopts, build.WithArch(arch))
fs := apkfs.DirFS(wd, apkfs.WithCreateDir())
bc, err := build.New(ctx, fs, bopts...)
if err != nil {
return err
}
log.Infof("using working directory %s", wd)
opts = append(opts, build.WithImageConfiguration(*ic))

mc, err := build.NewMultiArch(ctx, archs, opts...)
if err != nil {
return err
}

lists, err := mc.BuildPackageLists(ctx)
if err != nil {
return fmt.Errorf("failed to get package list for image: %w", err)
}

pkgs, _, err := bc.BuildPackageList(ctx)
if err != nil {
return fmt.Errorf("failed to get package list for image: %w", err)
for arch, pkgs := range lists {
if len(archs) != 1 {
log.Infof("packages for %s", arch)
}
var p pkgInfo
for _, pkg := range pkgs {
Expand Down
48 changes: 46 additions & 2 deletions pkg/build/multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,54 @@ func (m *MultiArch) BuildLayers(ctx context.Context) (map[types.Architecture]v1.

g.Go(func() error {
_, layer, err := bc.BuildLayer(ctx)

mu.Lock()
defer mu.Unlock()

if err != nil {
errs = append(errs, fmt.Errorf("for arch %q: %w", arch, err))
return nil
}

layers[arch] = layer

return nil
})
}

if err := g.Wait(); err != nil {
return nil, err
}

if err := errors.Join(errs...); err != nil {
return nil, fmt.Errorf("building layers: %w", err)
}

return layers, nil
}

func (m *MultiArch) BuildPackageLists(ctx context.Context) (map[types.Architecture][]*apk.RepositoryPackage, error) {
var (
g errgroup.Group
mu sync.Mutex
)
toInstalls := map[types.Architecture][]*apk.RepositoryPackage{}
errs := []error{}
for arch, bc := range m.Contexts {
arch, bc := arch, bc

g.Go(func() error {
toInstall, _, err := bc.apk.ResolveWorld(ctx)

mu.Lock()
defer mu.Unlock()
layers[arch] = layer

if err != nil {
errs = append(errs, fmt.Errorf("for arch %q: %w", arch, err))
return nil
}

toInstalls[arch] = toInstall

return nil
})
Expand All @@ -93,5 +133,9 @@ func (m *MultiArch) BuildLayers(ctx context.Context) (map[types.Architecture]v1.
return nil, err
}

return layers, errors.Join(errs...)
if err := errors.Join(errs...); err != nil {
return nil, fmt.Errorf("resolving apk packages: %w", err)
}

return toInstalls, errors.Join(errs...)
}

0 comments on commit a1f2de8

Please sign in to comment.