Skip to content

Commit

Permalink
feat: bazel oci rule support (#9048)
Browse files Browse the repository at this point in the history
* feat: bazel oci rule support

* fix: bazel test by creating starstand fake tar

* chore: remove todo

* chore: fix linting issues
  • Loading branch information
ericzzzzzzz committed Aug 31, 2023
1 parent fc367c1 commit 1255d6c
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 40 deletions.
11 changes: 11 additions & 0 deletions integration/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ var tests = []struct {
dir: "examples/bazel",
pods: []string{"bazel"},
},
{
description: "bazel oci",
dir: "testdata/bazel-rules-oci",
deployments: []string{"helloweb"},
},
{
description: "bazel oci sub-directory",
dir: "testdata/bazel-rules-oci",
args: []string{"-p", "target-with-package"},
deployments: []string{"helloweb"},
},
{
description: "jib",
dir: "testdata/jib",
Expand Down
7 changes: 7 additions & 0 deletions integration/testdata/bazel-rules-oci/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
load("@rules_oci//oci:defs.bzl", "oci_tarball")

oci_tarball(
name = "hello.tar",
image = "@hello//:hello",
repo_tags = ["hello:latest"],
)
30 changes: 30 additions & 0 deletions integration/testdata/bazel-rules-oci/WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "rules_oci",
sha256 = "db57efd706f01eb3ce771468366baa1614b5b25f4cce99757e2b8d942155b8ec",
strip_prefix = "rules_oci-1.0.0",
url = "https://github.com/bazel-contrib/rules_oci/releases/download/v1.0.0/rules_oci-v1.0.0.tar.gz",
)

load("@rules_oci//oci:dependencies.bzl", "rules_oci_dependencies")

rules_oci_dependencies()

load("@rules_oci//oci:repositories.bzl", "LATEST_CRANE_VERSION", "LATEST_ZOT_VERSION", "oci_register_toolchains")

oci_register_toolchains(
name = "oci",
crane_version = LATEST_CRANE_VERSION,
# Uncommenting the zot toolchain will cause it to be used instead of crane for some tasks.
# Note that it does not support docker-format images.
# zot_version = LATEST_ZOT_VERSION,
)

load("@rules_oci//oci:pull.bzl", "oci_pull")

oci_pull(
name = "hello",
digest = "sha256:845f77fab71033404f4cfceaa1ddb27b70c3551ceb22a5e7f4498cdda6c9daea",
image = "us-docker.pkg.dev/google-samples/containers/gke/hello-app",
)
25 changes: 25 additions & 0 deletions integration/testdata/bazel-rules-oci/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloweb
labels:
app: hello
spec:
selector:
matchLabels:
app: hello
tier: web
template:
metadata:
labels:
app: hello
tier: web
spec:
containers:
- name: hello-app
image: hello-image
ports:
- containerPort: 8080
resources:
requests:
cpu: 200m
23 changes: 23 additions & 0 deletions integration/testdata/bazel-rules-oci/skaffold.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: skaffold/v4beta5
kind: Config
metadata:
name: hello
build:
tagPolicy:
sha256: {}
artifacts:
- image: hello-image
bazel:
target: //:hello.tar
deploy:
kubectl: {}
manifests:
rawYaml:
- "deploy.yaml"
profiles:
- name: target-with-package
build:
artifacts:
- image: hello-image
bazel:
target: //sub-dir:hello.tar
7 changes: 7 additions & 0 deletions integration/testdata/bazel-rules-oci/sub-dir/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
load("@rules_oci//oci:defs.bzl", "oci_tarball")

oci_tarball(
name = "hello.tar",
image = "@hello//:hello",
repo_tags = ["hello-whatever:latest"],
)
39 changes: 13 additions & 26 deletions pkg/skaffold/build/bazel/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"path/filepath"
"strings"

"github.com/google/go-containerregistry/pkg/v1/tarball"

"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/docker"
"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/output"
"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/output/log"
Expand All @@ -51,7 +53,7 @@ func (b *Builder) Build(ctx context.Context, out io.Writer, artifact *latest.Art
if b.pushImages {
return docker.Push(tarPath, tag, b.cfg, nil)
}
return b.loadImage(ctx, out, tarPath, a, tag)
return b.loadImage(ctx, out, tarPath, tag)
}

func (b *Builder) SupportedPlatforms() platform.Matcher { return platform.All }
Expand Down Expand Up @@ -88,14 +90,22 @@ func (b *Builder) buildTar(ctx context.Context, out io.Writer, workspace string,
return tarPath, nil
}

func (b *Builder) loadImage(ctx context.Context, out io.Writer, tarPath string, a *latest.BazelArtifact, tag string) (string, error) {
func (b *Builder) loadImage(ctx context.Context, out io.Writer, tarPath string, tag string) (string, error) {
manifest, err := tarball.LoadManifest(func() (io.ReadCloser, error) {
return os.Open(tarPath)
})

if err != nil {
return "", fmt.Errorf("loading manifest from tarball failed: %w", err)
}

imageTar, err := os.Open(tarPath)
if err != nil {
return "", fmt.Errorf("opening image tarball: %w", err)
}
defer imageTar.Close()

bazelTag := buildImageTag(a.BuildTarget)
bazelTag := manifest[0].RepoTags[0]
imageID, err := b.localDocker.Load(ctx, out, imageTar, bazelTag)
if err != nil {
return "", fmt.Errorf("loading image into docker daemon: %w", err)
Expand Down Expand Up @@ -143,26 +153,3 @@ func bazelTarPath(ctx context.Context, workspace string, a *latest.BazelArtifact

return filepath.Join(execRoot, targetPath), nil
}

func trimTarget(buildTarget string) string {
// TODO(r2d4): strip off leading //:, bad
trimmedTarget := strings.TrimPrefix(buildTarget, "//")
// Useful if root target "//:target"
trimmedTarget = strings.TrimPrefix(trimmedTarget, ":")

return trimmedTarget
}

func buildImageTag(buildTarget string) string {
imageTag := trimTarget(buildTarget)
imageTag = strings.TrimPrefix(imageTag, ":")

// TODO(r2d4): strip off trailing .tar, even worse
imageTag = strings.TrimSuffix(imageTag, ".tar")

if strings.Contains(imageTag, ":") {
return fmt.Sprintf("bazel/%s", imageTag)
}

return fmt.Sprintf("bazel:%s", imageTag)
}
8 changes: 0 additions & 8 deletions pkg/skaffold/build/bazel/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,6 @@ func TestBazelTarPath(t *testing.T) {
})
}

func TestBuildImageTag(t *testing.T) {
buildTarget := "//:skaffold_example.tar"

imageTag := buildImageTag(buildTarget)

testutil.CheckDeepEqual(t, "bazel:skaffold_example", imageTag)
}

func fakeLocalDaemon() docker.LocalDaemon {
return docker.NewLocalDaemon(&testutil.FakeAPIClient{}, nil, false, nil)
}
Expand Down
23 changes: 17 additions & 6 deletions testutil/fake_image_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"fmt"
"io"
"math"
"os"
"strings"
"sync"
"sync/atomic"
Expand All @@ -32,6 +31,9 @@ import (
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/client"
reg "github.com/docker/docker/registry"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/random"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
Expand Down Expand Up @@ -307,16 +309,25 @@ func (f *FakeAPIClient) DiskUsage(ctx context.Context) (types.DiskUsage, error)

func (f *FakeAPIClient) Close() error { return nil }

// TODO(dgageot): create something that looks more like an actual tar file.
func CreateFakeImageTar(ref string, path string) error {
return os.WriteFile(path, []byte(ref), os.ModePerm)
image, err := random.Image(1024, 1)
if err != nil {
return fmt.Errorf("failed to create fake image %w", err)
}
reference, err := name.ParseReference(ref)
if err != nil {
return fmt.Errorf("failed to parse reference %w", err)
}
return tarball.WriteToFile(path, reference, image)
}

func ReadRefFromFakeTar(input io.Reader) (string, error) {
buf, err := io.ReadAll(input)
manifest, err := tarball.LoadManifest(func() (io.ReadCloser, error) {
return io.NopCloser(input), nil
})
if err != nil {
return "", fmt.Errorf("reading tar")
return "", fmt.Errorf("loading manifest %w", err)
}

return string(buf), nil
return manifest[0].RepoTags[0], nil
}

0 comments on commit 1255d6c

Please sign in to comment.