Merge pull request #1194 from aluzzardi/engine-pull

engine.#Pull implementation
This commit is contained in:
Andrea Luzzardi 2021-12-13 16:33:42 +01:00 committed by GitHub
commit a83987841d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 176 additions and 22 deletions

View File

@ -44,12 +44,12 @@ integration: core-integration universe-test doc-test
.PHONY: core-integration
core-integration: dagger-debug
yarn --cwd "./tests" install
DAGGER_BINARY="../cmd/dagger/dagger-debug" yarn --cwd "./tests" test
DAGGER_BINARY="$(shell pwd)/cmd/dagger/dagger-debug" yarn --cwd "./tests" test
.PHONY: universe-test
universe-test: dagger-debug
yarn --cwd "./universe" install
DAGGER_BINARY="../cmd/dagger/dagger-debug" yarn --cwd "./universe" test
DAGGER_BINARY="$(shell pwd)/cmd/dagger/dagger-debug" yarn --cwd "./universe" test
.PHONY: doc-test
doc-test: dagger-debug

View File

@ -31,6 +31,17 @@ func (v *Value) FillPath(p cue.Path, x interface{}) error {
return v.val.Err()
}
// FillFields fills multiple fields, in place
func (v *Value) FillFields(values map[string]interface{}) (*Value, error) {
for p, x := range values {
if err := v.FillPath(cue.ParsePath(p), x); err != nil {
return nil, err
}
}
return v, nil
}
// LookupPath is a concurrency safe wrapper around cue.Value.LookupPath
func (v *Value) LookupPath(p cue.Path) *Value {
v.cc.rlock()

View File

@ -3,7 +3,6 @@ package task
import (
"context"
"cuelang.org/go/cue"
"github.com/moby/buildkit/client/llb"
"go.dagger.io/dagger/compiler"
"go.dagger.io/dagger/plancontext"
@ -69,9 +68,7 @@ func (c importTask) Run(ctx context.Context, pctx *plancontext.Context, s solver
}
fs := pctx.FS.New(result)
out := compiler.NewValue()
if err := out.FillPath(cue.ParsePath("fs"), fs.MarshalCUE()); err != nil {
return nil, err
}
return out, nil
return compiler.NewValue().FillFields(map[string]interface{}{
"fs": fs.MarshalCUE(),
})
}

71
plan/task/pull.go Normal file
View File

@ -0,0 +1,71 @@
package task
import (
"context"
"encoding/json"
"fmt"
"github.com/docker/distribution/reference"
"github.com/moby/buildkit/client/llb"
"go.dagger.io/dagger/compiler"
"go.dagger.io/dagger/plancontext"
"go.dagger.io/dagger/solver"
)
func init() {
Register("Pull", func() Task { return &pullTask{} })
}
type pullTask struct {
}
func (c *pullTask) Run(ctx context.Context, pctx *plancontext.Context, s solver.Solver, v *compiler.Value) (*compiler.Value, error) {
// FIXME: handle auth
rawRef, err := v.Lookup("source").String()
if err != nil {
return nil, err
}
ref, err := reference.ParseNormalizedNamed(rawRef)
if err != nil {
return nil, fmt.Errorf("failed to parse ref %s: %w", rawRef, err)
}
// Add the default tag "latest" to a reference if it only has a repo name.
ref = reference.TagNameOnly(ref)
st := llb.Image(
ref.String(),
withCustomName(v, "FetchContainer %s", rawRef),
)
// Load image metadata and convert to to LLB.
platform := pctx.Platform.Get()
image, digest, err := s.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{
LogName: vertexNamef(v, "load metadata for %s", ref.String()),
Platform: &platform,
})
if err != nil {
return nil, err
}
imageJSON, err := json.Marshal(image)
if err != nil {
return nil, err
}
// Apply Image Config on top of LLB instructions
st, err = st.WithImageConfig(imageJSON)
if err != nil {
return nil, err
}
result, err := s.Solve(ctx, st, pctx.Platform.Get())
if err != nil {
return nil, err
}
fs := pctx.FS.New(result)
return compiler.NewValue().FillFields(map[string]interface{}{
"output": fs.MarshalCUE(),
"digest": digest,
"config": image.Config,
})
}

View File

@ -5,7 +5,6 @@ import (
"fmt"
"os"
"cuelang.org/go/cue"
"github.com/rs/zerolog/log"
"go.dagger.io/dagger/compiler"
"go.dagger.io/dagger/plancontext"
@ -37,9 +36,7 @@ func (c secretEnvTask) Run(ctx context.Context, pctx *plancontext.Context, _ sol
return nil, fmt.Errorf("environment variable %q not set", secretEnv.Envvar)
}
secret := pctx.Secrets.New(env)
out := compiler.NewValue()
if err := out.FillPath(cue.ParsePath("contents"), secret.MarshalCUE()); err != nil {
return nil, err
}
return out, nil
return compiler.NewValue().FillFields(map[string]interface{}{
"contents": secret.MarshalCUE(),
})
}

View File

@ -4,7 +4,6 @@ import (
"context"
"os"
"cuelang.org/go/cue"
"github.com/rs/zerolog/log"
"go.dagger.io/dagger/compiler"
"go.dagger.io/dagger/plancontext"
@ -37,9 +36,7 @@ func (c secretFileTask) Run(ctx context.Context, pctx *plancontext.Context, _ so
}
secret := pctx.Secrets.New(string(plaintext))
out := compiler.NewValue()
if err := out.FillPath(cue.ParsePath("contents"), secret.MarshalCUE()); err != nil {
return nil, err
}
return out, nil
return compiler.NewValue().FillFields(map[string]interface{}{
"contents": secret.MarshalCUE(),
})
}

View File

@ -7,8 +7,12 @@ import (
"go.dagger.io/dagger/compiler"
)
func withCustomName(v *compiler.Value, format string, a ...interface{}) llb.ConstraintsOpt {
func vertexNamef(v *compiler.Value, format string, a ...interface{}) string {
prefix := fmt.Sprintf("@%s@", v.Path().String())
name := fmt.Sprintf(format, a...)
return llb.WithCustomName(prefix + " " + name)
return prefix + " " + name
}
func withCustomName(v *compiler.Value, format string, a ...interface{}) llb.ConstraintsOpt {
return llb.WithCustomName(vertexNamef(v, format, a...))
}

View File

@ -0,0 +1,45 @@
package engine
// A ref is an address for a remote container image
//
// Examples:
// - "index.docker.io/dagger"
// - "dagger"
// - "index.docker.io/dagger:latest"
// - "index.docker.io/dagger:latest@sha256:a89cb097693dd354de598d279c304a1c73ee550fbfff6d9ee515568e0c749cfe"
#Ref: string
// Container image config. See [OCI](https://opencontainers.org/).
// Spec left open on purpose to account for additional fields.
// [Image Spec](https://github.com/opencontainers/image-spec/blob/main/specs-go/v1/config.go)
// [Docker Superset](https://github.com/moby/buildkit/blob/master/frontend/dockerfile/dockerfile2llb/image.go)
#ImageConfig: {
Env?: [...string]
User?: string
Cmd?: [...string]
...
}
// Download a container image from a remote repository
#Pull: {
_type: "Pull"
// Repository source ref
source: #Ref
// Authentication
auth: [...{
target: string
username: string
secret: string | #Secret
}]
// Root filesystem of downloaded image
output: #FS
// Image digest
digest: string
// Downloaded container image config
config: #ImageConfig
}

10
tests/tasks.bats Normal file
View File

@ -0,0 +1,10 @@
setup() {
load 'helpers'
common_setup
}
@test "task: #Pull" {
cd "$TESTDIR"/tasks/pull
dagger --europa up
}

View File

@ -0,0 +1 @@
module: ""

View File

@ -0,0 +1,3 @@
# generated by dagger
alpha.dagger.io
dagger.lock

18
tests/tasks/pull/pull.cue Normal file
View File

@ -0,0 +1,18 @@
package main
import (
"alpha.dagger.io/dagger/engine"
)
engine.#Plan & {
actions: pull: engine.#Pull & {
source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3"
} & {
// assert result
digest: "sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3"
config: {
Env: ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
Cmd: ["/bin/sh"]
}
}
}