Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNM: WIP dagger integration. #905

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ require (
cloud.google.com/go/compute v1.23.3 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.5 // indirect
dagger.io/dagger v0.9.5 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/99designs/gqlgen v0.17.31 // indirect
github.com/Khan/genqlient v0.6.0 // indirect
github.com/MakeNowJust/heredoc/v2 v2.0.1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
github.com/adrg/xdg v0.4.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
Expand Down Expand Up @@ -154,6 +158,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/vbatts/tar-split v0.11.5 // indirect
github.com/vektah/gqlparser/v2 v2.5.6 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
go.lsp.dev/uri v0.3.0 // indirect
Expand Down
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8=
cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
dagger.io/dagger v0.9.5 h1:44ypKgOjKZKrzqHSoa/wIfqnrSZM87tuoAKJpo5tGV4=
dagger.io/dagger v0.9.5/go.mod h1:ic2UD6gS5iBp2e6VWPxyb7h6VpAyhFN6U7/TDlriox8=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/99designs/gqlgen v0.17.31 h1:VncSQ82VxieHkea8tz11p7h/zSbvHSxSDZfywqWt158=
github.com/99designs/gqlgen v0.17.31/go.mod h1:i4rEatMrzzu6RXaHydq1nmEPZkb3bKQsnxNRHS4DQB4=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk=
github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4DpWWCRM=
github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A=
github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
Expand All @@ -63,8 +69,13 @@ github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
Expand Down Expand Up @@ -121,6 +132,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
Expand Down Expand Up @@ -576,6 +588,8 @@ github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
github.com/vektah/gqlparser/v2 v2.5.6 h1:Ou14T0N1s191eRMZ1gARVqohcbe1e8FrcONScsq8cRU=
github.com/vektah/gqlparser/v2 v2.5.6/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
Expand Down Expand Up @@ -800,6 +814,7 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
10 changes: 10 additions & 0 deletions pkg/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -1381,13 +1381,23 @@ func (b *Build) WorkspaceConfig() *container.Config {
return b.containerConfig
}

type WorkspaceRunner interface {
Export(context.Context, string) error
}

// RetrieveWorkspace retrieves the workspace from the container and unpacks it
// to the workspace directory. The workspace retrieved from the runner is in a
// tar stream containing the workspace contents rooted at ./melange-out
func (b *Build) RetrieveWorkspace(ctx context.Context) error {
ctx, span := otel.Tracer("melange").Start(ctx, "RetrieveWorkspace")
defer span.End()

// Check if Runner is a WorkspaceRunner type
wr, ok := b.Runner.(WorkspaceRunner)
if ok {
return wr.Export(ctx, b.WorkspaceDir)
}

r, err := b.Runner.WorkspaceTar(ctx, b.containerConfig)
if err != nil {
return err
Expand Down
194 changes: 194 additions & 0 deletions pkg/container/dagger_runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// Copyright 2022 Chainguard, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package container

import (
"context"
"io"
"os"
"path/filepath"

apko_build "chainguard.dev/apko/pkg/build"
apko_oci "chainguard.dev/apko/pkg/build/oci"
apko_types "chainguard.dev/apko/pkg/build/types"
"chainguard.dev/apko/pkg/log"
"dagger.io/dagger"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"go.opentelemetry.io/otel"
)

const DaggerName = "dagger"
const imageTarName = "image.tar"

type daggerRunner struct {
logger log.Logger
client *dagger.Client
container *dagger.Container
tmpDir string
}

// DaggerRunner returns a Dagger Runner implementation.
func DaggerRunner(ctx context.Context, logger log.Logger) (Runner, error) {
// initialize Dagger client
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
if err != nil {
return nil, err
}
tmpDir, err := os.MkdirTemp("", "melange-dagger-")
if err != nil {
return nil, err
}
return &daggerRunner{
logger: logger,
client: client,
tmpDir: tmpDir,
}, nil
}

// Name name of the runner
func (bw *daggerRunner) Name() string {
return DaggerName
}

// Run runs a Dagger task given a Config and command string.
func (d *daggerRunner) Run(ctx context.Context, cfg *Config, args ...string) error {
_, span := otel.Tracer("melange").Start(ctx, "dagger.Run")
defer span.End()

for key, val := range cfg.Environment {
d.container = d.container.WithEnvVariable(key, val)
}
d.container = d.container.WithExec(args, dagger.ContainerWithExecOpts{})

var err error
// Force execution
d.container, err = d.container.Sync(ctx)
return err
}

// TestUsability determines if the Bubblewrap runner can be used
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bubblewrap?

// as a container runner.
func (d *daggerRunner) TestUsability(ctx context.Context) bool {
return true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the sdk exposes a simple health check somewhere we could leverage here

}

// OCIImageLoader used to load OCI images in, if needed. dagger does not need it.
func (d *daggerRunner) OCIImageLoader() Loader {
return &daggerLoader{
client: d.client,
tmpDir: d.tmpDir,
}
}

// TempDir returns the base for temporary directory. For dagger, this is empty.
func (d *daggerRunner) TempDir() string {
return ""
}

// StartPod starts a pod if necessary. On Bubblewrap, we just run
// ldconfig to prime ld.so.cache for glibc < 2.37 builds.
func (d *daggerRunner) StartPod(ctx context.Context, cfg *Config) error {
_, span := otel.Tracer("melange").Start(ctx, "dagger.StartPod")
defer span.End()

// Initialize the Container from disk
imgPath := filepath.Join(d.tmpDir, imageTarName)
d.container = d.client.Container().Import(d.client.Host().File(imgPath))

// Add our cache dir
d.container = d.container.WithMountedCache("/var/cache/melange/", d.client.CacheVolume("build-cache"))

for _, mnt := range cfg.Mounts {

// We skip mounting in some files that we don't need in this mode
if mnt.Source == "/etc/resolv.conf" {
continue
}

// check if its a file or a directory
fi, err := os.Stat(mnt.Source)
if err != nil {
return err
}

d.logger.Infof("mounting %s to %s", mnt.Source, mnt.Destination)

if fi.IsDir() {
host := d.client.Host().Directory(mnt.Source)
d.container = d.container.WithMountedDirectory(mnt.Destination, host)
} else {
host := d.client.Host().File(mnt.Source)
d.container = d.container.WithMountedFile(mnt.Destination, host)
}
}

script := "[ -x /sbin/ldconfig ] && /sbin/ldconfig /lib || true"
d.container = d.container.WithExec([]string{"/bin/sh", "-c", script})
return nil
}

// TerminatePod terminates a pod if necessary. Not implemented
// for Bubblewrap runners.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bubblewrap again

func (d *daggerRunner) TerminatePod(ctx context.Context, cfg *Config) error {
return nil
}

func (d *daggerRunner) WorkspaceTar(ctx context.Context, cfg *Config) (io.ReadCloser, error) {
return nil, nil
}

// WorkspaceTar implements Runner
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong method name

func (d *daggerRunner) Export(ctx context.Context, p string) error {
ctx, span := otel.Tracer("melange").Start(ctx, "docker.Export")
defer span.End()
output := d.container.Directory("/home/build/melange-out")
if _, err := output.Export(ctx, p+"/melange-out"); err != nil {
return err
}
return nil
}

type daggerLoader struct {
tmpDir string
client *dagger.Client
}

func (d *daggerLoader) LoadImage(ctx context.Context, layer v1.Layer, arch apko_types.Architecture, bc *apko_build.Context) (string, error) {
ctx, span := otel.Tracer("melange").Start(ctx, "docker.LoadImage")

Check failure on line 171 in pkg/container/dagger_runner.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to ctx (ineffassign)
defer span.End()

creationTime, err := bc.GetBuildDateEpoch()
if err != nil {
return "", err
}

img, err := apko_oci.BuildImageFromLayer(layer, bc.ImageConfiguration(), creationTime, arch, bc.Logger())
if err != nil {
return "", err
}

ref, err := name.ParseReference("melange:latest")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see having a fixed name here creating races in the load/run phase when performing multiple builds locally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is just at throwaway name but could be wrong.

if err != nil {
return "", err
}

tarPath := filepath.Join(d.tmpDir, imageTarName)
if err := tarball.WriteToFile(tarPath, ref, img); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be really inefficient. I need to look to see if dagger exposes a better interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I know. I think the only better option is to round trip through a registry. I looked and couldn't find much else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OR change the entire setup so dagger also invokes apko for us.

return "", err
}
return ref.String(), nil
}
2 changes: 2 additions & 0 deletions pkg/container/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func GetRunner(ctx context.Context, s string, log log.Logger) (Runner, error) {
return LimaRunner(ctx, log)
case KubernetesName:
return KubernetesRunner(ctx, log)
case DaggerName:
return DaggerRunner(ctx, log)
}
return nil, fmt.Errorf("unknown virtualizer %q", s)
}
Expand Down
Loading