Skip to content

Commit

Permalink
Merge pull request #22 from cpuguy83/support_toolchain_named_target
Browse files Browse the repository at this point in the history
Allow the toolchain image to be set by a named context
  • Loading branch information
cpuguy83 authored Oct 6, 2023
2 parents 1e5283d + f5d7cf0 commit dcd4f81
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 19 deletions.
27 changes: 21 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,29 @@ jobs:
cache: false
- name: Expose GitHub tokens for caching
uses: crazy-max/ghaction-github-runtime@v3
- name: Setup dockerd
- name: Setup builder
run: |
cp /etc/docker/daemon.json /tmp/daemon.json || echo "{}" > /tmp/daemon.json
jq '.features += {"containerd-snapshotter": true}' /tmp/daemon.json | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
docker run -d --net=host registry
docker buildx create --use --driver-opt network=host
- name: build frontend tooling
run: |
docker buildx bake frontend mariner2-toolchain
set -e
# Build the frontend image and push it to the local registry
docker buildx bake \
--set frontend.output=type=registry \
--set frontend.tags=localhost:5000/dalec/frontend \
--set frontend.cache-from=type=gha,scope=dalec/frontend/ci \
--set frontend.cache-to=type=gha,scope=dalec/frontend/ci,mode=max \
frontend
- name: test
run: |
docker buildx bake test-runc
# Set the buildkit syntax to the one we stored in the local registry
# The bakefile will read this and pass it along to the runc target
export BUILDKIT_SYNTAX=localhost:5000/dalec/frontend
docker buildx bake \
--set mariner2-toolchain.cache-from=type=gha,scope=dalec/mariner2-toolchain/ci \
--set mariner2-toolchain.cache-to=type=gha,scope=dalec/mariner2-toolchain/ci,mode=max \
--set runc-mariner2-*.contexts.mariner2-toolchain=target:mariner2-toolchain \
test-runc
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ RUN \
FROM scratch AS frontend
COPY --from=frontend-build /frontend /frontend
LABEL moby.buildkit.frontend.network.none="true"
LABEL moby.buildkit.frontend.caps="moby.buildkit.frontend.inputs,moby.buildkit.frontend.subrequests"
LABEL moby.buildkit.frontend.caps="moby.buildkit.frontend.inputs,moby.buildkit.frontend.subrequests,moby.buildkit.frontend.contexts"
ENTRYPOINT ["/frontend"]
9 changes: 5 additions & 4 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
group "default" {
targets = ["frontend", "mariner2-toolchain"]
targets = ["frontend"]
}

target "frontend" {
target = "frontend"
tags = ["ghcr.io/azure/dalec/frontend:latest", "local/dalec/frontend", BUILDKIT_SYNTAX]
tags = ["ghcr.io/azure/dalec/frontend:latest", BUILDKIT_SYNTAX]
}

// Toolchain builds the full mariner container with the mariner build tookit
target "mariner2-toolchain" {
dockerfile = "./frontend/mariner2/Dockerfile"
target = "toolchain"
Expand Down Expand Up @@ -42,7 +41,6 @@ variable "RUNC_REVISION" {
default = "1"
}


variable "BUILDKIT_SYNTAX" {
default = "local/dalec/frontend"
}
Expand All @@ -59,6 +57,9 @@ target "runc" {
distro = ["mariner2"]
tgt = ["rpm", "container", "toolkitroot"]
}
contexts = {
"mariner2-toolchain" = "target:mariner2-toolchain"
}
target = "${distro}/${tgt}"
// only tag the container target
tags = tgt == "container" ? ["runc:${distro}"] : []
Expand Down
11 changes: 8 additions & 3 deletions frontend/mariner2/target_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ func handleContainer(ctx context.Context, client gwclient.Client, spec *dalec.Sp
caps := client.BuildOpts().LLBCaps
noMerge := !caps.Contains(pb.CapMergeOp)

st, err := specToContainerLLB(spec, targetKey, noMerge, getDigestFromClientFn(ctx, client), client, frontend.ForwarderFromClient(ctx, client))
baseImg, err := getBaseBuilderImg(ctx, client)
if err != nil {
return nil, nil, err
}

st, err := specToContainerLLB(spec, targetKey, noMerge, getDigestFromClientFn(ctx, client), client, frontend.ForwarderFromClient(ctx, client), baseImg)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -50,8 +55,8 @@ func handleContainer(ctx context.Context, client gwclient.Client, spec *dalec.Sp
return ref, &img, err
}

func specToContainerLLB(spec *dalec.Spec, target string, noMerge bool, getDigest getDigestFunc, mr llb.ImageMetaResolver, forward dalec.ForwarderFunc) (llb.State, error) {
st, err := specToRpmLLB(spec, noMerge, getDigest, mr, forward)
func specToContainerLLB(spec *dalec.Spec, target string, noMerge bool, getDigest getDigestFunc, mr llb.ImageMetaResolver, forward dalec.ForwarderFunc, baseImg llb.State) (llb.State, error) {
st, err := specToRpmLLB(spec, noMerge, getDigest, mr, forward, baseImg)
if err != nil {
return llb.Scratch(), fmt.Errorf("error creating rpm: %w", err)
}
Expand Down
68 changes: 63 additions & 5 deletions frontend/mariner2/target_rpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package mariner2

import (
"context"
"encoding/json"
"fmt"
"sort"
"strconv"
Expand All @@ -11,13 +12,15 @@ import (
"github.com/azure/dalec/frontend"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/exporter/containerimage/image"
"github.com/moby/buildkit/frontend/dockerui"
gwclient "github.com/moby/buildkit/frontend/gateway/client"
"github.com/moby/buildkit/solver/pb"
)

const (
marinerRef = "mcr.microsoft.com/cbl-mariner/base/core:2.0"
toolchainImgRef = "ghcr.io/azure/dalec/mariner2/toolchain:latest"
marinerRef = "mcr.microsoft.com/cbl-mariner/base/core:2.0"
toolchainImgRef = "ghcr.io/azure/dalec/mariner2/toolchain:latest"
toolchainNamedContext = "mariner2-toolchain"

cachedToolkitRPMDir = "/root/.cache/mariner2-toolkit-rpm-cache"
marinerToolkitPath = "/usr/local/toolkit"
Expand All @@ -27,11 +30,23 @@ var (
marinerTdnfCache = llb.AddMount("/var/tdnf/cache", llb.Scratch(), llb.AsPersistentCacheDir("mariner2-tdnf-cache", llb.CacheMountLocked))
)

var _ dockerUIClient = (*dockerui.Client)(nil)

type dockerUIClient interface {
MainContext(ctx context.Context, opts ...llb.LocalOption) (*llb.State, error)
NamedContext(ctx context.Context, name string, opts dockerui.ContextOpt) (*llb.State, *image.Image, error)
}

func handleRPM(ctx context.Context, client gwclient.Client, spec *dalec.Spec) (gwclient.Reference, *image.Image, error) {
caps := client.BuildOpts().LLBCaps
noMerge := !caps.Contains(pb.CapMergeOp)

st, err := specToRpmLLB(spec, noMerge, getDigestFromClientFn(ctx, client), client, frontend.ForwarderFromClient(ctx, client))
baseImg, err := getBaseBuilderImg(ctx, client)
if err != nil {
return nil, nil, err
}

st, err := specToRpmLLB(spec, noMerge, getDigestFromClientFn(ctx, client), client, frontend.ForwarderFromClient(ctx, client), baseImg)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -78,13 +93,56 @@ func getBuildDeps(spec *dalec.Spec) []string {
return out
}

func specToRpmLLB(spec *dalec.Spec, noMerge bool, getDigest getDigestFunc, mr llb.ImageMetaResolver, forward dalec.ForwarderFunc) (llb.State, error) {
func getBaseBuilderImg(ctx context.Context, client gwclient.Client) (llb.State, error) {
dc, err := dockerui.NewClient(client)
if err != nil {
return llb.Scratch(), err
}

// Check if the client passed in a named context for the toolkit.
namedSt, cfg, err := dc.NamedContext(ctx, toolchainNamedContext, dockerui.ContextOpt{})
if err != nil {
return llb.Scratch(), err
}

if namedSt != nil {
if cfg != nil {
dt, err := json.Marshal(cfg)
if err != nil {
return llb.Scratch(), err
}
return namedSt.WithImageConfig(dt)
}
return *namedSt, nil
}

// See if there is a named context using the toolchain image ref
namedSt, cfg, err = dc.NamedContext(ctx, toolchainImgRef, dockerui.ContextOpt{})
if err != nil {
return llb.Scratch(), err
}

if namedSt != nil {
if cfg != nil {
dt, err := json.Marshal(cfg)
if err != nil {
return llb.Scratch(), err
}
return namedSt.WithImageConfig(dt)
}
return *namedSt, nil
}

return llb.Image(marinerRef, llb.WithMetaResolver(client)), nil
}

func specToRpmLLB(spec *dalec.Spec, noMerge bool, getDigest getDigestFunc, mr llb.ImageMetaResolver, forward dalec.ForwarderFunc, baseImg llb.State) (llb.State, error) {
br, err := spec2ToolkitRootLLB(spec, noMerge, getDigest, mr, forward)
if err != nil {
return llb.Scratch(), err
}

st := llb.Image(toolchainImgRef, llb.WithMetaResolver(mr)).
st := baseImg.
// /.dockerenv is used by the toolkit to detect it's running in a container.
// This makes the toolkit use a different strategy for setting up chroots.
// Namely, it makes so the toolkit won't use "mount" to mount the stuff into the chroot which requires CAP_SYS_ADMIN.
Expand Down

0 comments on commit dcd4f81

Please sign in to comment.