From 78d2e902f240306f69735ff0b11ec87378a187d1 Mon Sep 17 00:00:00 2001 From: Anurag Madnawat Date: Sat, 7 Dec 2024 13:08:35 -0800 Subject: [PATCH] [feat]: [CI-15228]: Package buildkit tarball as part of buildx image (#50) * Modify dockerfiles * Update docker.go * make changes * Update .drone.yml * update --- .drone.yml | 41 ++++++++++-------- app.go | 13 ++++++ buildkit/release.sh | 57 +++++++++++++------------ docker.go | 63 +++++++++++++++------------- docker/docker/Dockerfile.linux.amd64 | 8 ++++ docker/docker/Dockerfile.linux.arm64 | 7 ++++ 6 files changed, 115 insertions(+), 74 deletions(-) diff --git a/.drone.yml b/.drone.yml index 8207562..256e2ee 100644 --- a/.drone.yml +++ b/.drone.yml @@ -14,7 +14,6 @@ steps: - name: vet image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - go vet ./... environment: @@ -25,7 +24,6 @@ steps: - name: test image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - go test -cover ./... environment: @@ -61,7 +59,6 @@ steps: environment: CGO_ENABLED: 0 commands: - - sh buildkit/release.sh linux/amd64 - go build -o release/windows/amd64/drone-docker.exe ./cmd/drone-docker - name: build docker plugin image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4 @@ -105,7 +102,6 @@ steps: environment: CGO_ENABLED: 0 commands: - - sh buildkit/release.sh linux/amd64 - go build -o release/windows/amd64/drone-docker.exe ./cmd/drone-docker - name: build docker plugin image: plugins/docker @@ -147,7 +143,6 @@ steps: - name: build-push image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-docker ./cmd/drone-docker' environment: CGO_ENABLED: 0 @@ -159,7 +154,6 @@ steps: - name: build-tag image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-docker ./cmd/drone-docker' environment: CGO_ENABLED: 0 @@ -170,9 +164,13 @@ steps: - name: executable image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - ./release/linux/amd64/drone-docker --help + - name: buildkit-tarball + image: docker:27.3.1-dind + commands: + - sh buildkit/release.sh + - name: publish image: plugins/docker:18 settings: @@ -215,7 +213,6 @@ steps: - name: build-push image: golang:1.22 commands: - - sh buildkit/release.sh linux/arm64 - 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-docker ./cmd/drone-docker' environment: CGO_ENABLED: 0 @@ -227,7 +224,6 @@ steps: - name: build-tag image: golang:1.22 commands: - - sh buildkit/release.sh linux/arm64 - 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-docker ./cmd/drone-docker' environment: CGO_ENABLED: 0 @@ -238,9 +234,13 @@ steps: - name: executable image: golang:1.22 commands: - - sh buildkit/release.sh linux/arm64 - ./release/linux/arm64/drone-docker --help + - name: buildkit-tarball + image: docker:27.3.1-dind + commands: + - sh buildkit/release.sh + - name: publish image: plugins/docker:18 settings: @@ -318,7 +318,6 @@ steps: - name: build-push image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-heroku ./cmd/drone-heroku' environment: CGO_ENABLED: 0 @@ -329,7 +328,6 @@ steps: - name: build-tag image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-heroku ./cmd/drone-heroku' environment: CGO_ENABLED: 0 @@ -337,6 +335,11 @@ steps: event: - tag + - name: buildkit-tarball + image: docker:27.3.1-dind + commands: + - sh buildkit/release.sh + - name: publish image: plugins/docker:18 settings: @@ -379,7 +382,6 @@ steps: - name: build-push image: golang:1.22 commands: - - sh buildkit/release.sh linux/arm64 - 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-heroku ./cmd/drone-heroku' environment: CGO_ENABLED: 0 @@ -390,13 +392,18 @@ steps: - name: build-tag image: golang:1.22 commands: - - sh buildkit/release.sh linux/arm64 - 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-heroku ./cmd/drone-heroku' environment: CGO_ENABLED: 0 when: event: - tag + + - name: buildkit-tarball + image: docker:27.3.1-dind + commands: + - sh buildkit/release.sh + - name: publish image: plugins/docker:18 settings: @@ -470,13 +477,11 @@ steps: pull: always image: golang:1.22 commands: - - sh buildkit/release.sh linux/amd64 - GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-linux-amd64 ./cmd/drone-docker - - GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-darwin-amd64 ./cmd/drone-docker - - GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-windows-amd64 ./cmd/drone-docker - - sh buildkit/release.sh linux/arm64 - GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-linux-arm64 ./cmd/drone-docker + - GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-darwin-amd64 ./cmd/drone-docker - GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-darwin-arm64 ./cmd/drone-docker + - GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -a -tags netgo -o release/drone-buildx-windows-amd64 ./cmd/drone-docker environment: CGO_ENABLED: 0 diff --git a/app.go b/app.go index ea6758b..4a6b1da 100644 --- a/app.go +++ b/app.go @@ -374,6 +374,17 @@ func Run() { Usage: "Use preloaded buildkit image. Default is true.", EnvVar: "PLUGIN_USE_LOADED_BUILDKIT", }, + cli.StringFlag{ + Name: "buildkit-assets-dir", + Usage: "directory where buildkit assets are stored", + Value: "buildkit", + EnvVar: "PLUGIN_BUILDKIT_ASSETS_DIR", + }, + cli.StringFlag{ + Name: "buildkit-version", + Usage: "Buildkit version to use", + EnvVar: "PLUGIN_BUILDKIT_VERSION", + }, } if err := app.Run(os.Args); err != nil { @@ -457,6 +468,8 @@ func run(c *cli.Context) error { DriverOptsNew: c.Generic("builder-driver-opts-new").(*CustomStringSliceFlag).GetValue(), RemoteConn: c.String("builder-remote-conn"), UseLoadedBuildkit: c.BoolT("use-loaded-buildkit"), + AssestsDir: c.String("buildkit-assets-dir"), + BuildkitVersion: c.String("buildkit-version"), }, BaseImageRegistry: c.String("docker.baseimageregistry"), BaseImageUsername: c.String("docker.baseimageusername"), diff --git a/buildkit/release.sh b/buildkit/release.sh index cdf85bb..274f80b 100644 --- a/buildkit/release.sh +++ b/buildkit/release.sh @@ -1,29 +1,32 @@ #!/bin/bash -# Usage: ./release.sh -# Example: ./release.sh linux/amd64 - -set -e - -# Default platform -platform="${1:-linux/amd64}" - -# Extract the full buildkit version (e.g., "harness/buildkit:1.0.6") without jq or grep -P -full_buildkit_version=$(grep '"buildkit_version"' buildkit/version.json | awk -F'"' '{print $4}') - -# Extract only the version number (e.g., "1.0.6") -buildkit_version=${full_buildkit_version##*:} - -# Parse platform components -os=${platform%%/*} -arch=${platform##*/} - -# Construct GCS tarball URL -tarball_url="https://storage.cloud.google.com/harness-ti/buildkit/${buildkit_version}/harness-buildkit-${buildkit_version}-${os}-${arch}.tar" - -# Download the tarball -echo "Downloading Buildkit tarball from ${tarball_url}..." -mkdir -p buildkit -curl -L -o buildkit/buildkit.tar "${tarball_url}" - -echo "Buildkit tarball downloaded to buildkit/buildkit.tar" +image_name=$(grep '"buildkit_version"' buildkit/version.json | awk -F'"' '{print $4}') + +# Check if image name was extracted successfully +if [ -z "$image_name" ]; then + echo "Error: Unable to extract image name from JSON file." + exit 1 +fi + +# Check for an optional platform override +platform_override=${1:-} +if [ -n "$platform_override" ]; then + echo "Using platform override: $platform_override" +else + echo "No platform override provided. Using default platform." +fi + +# Pull the Docker image with optional platform specification +echo "Pulling Docker image: $image_name" +if [ -n "$platform_override" ]; then + docker pull --platform "$platform_override" "$image_name" +else + docker pull "$image_name" +fi + +# Save the Docker image to a tarball +tar_file="buildkit/buildkit.tar" +echo "Saving Docker image to tarball: $tar_file" +docker save "$image_name" -o "$tar_file" + +echo "Done. Docker image saved to $tar_file" diff --git a/docker.go b/docker.go index ea7e188..007ceb4 100644 --- a/docker.go +++ b/docker.go @@ -2,7 +2,6 @@ package docker import ( "bytes" - "embed" "encoding/json" "fmt" "os" @@ -43,6 +42,8 @@ type ( DriverOptsNew []string // Buildx driver opts new RemoteConn string // Buildx remote connection endpoint UseLoadedBuildkit bool // Use loaded buildkit or no + AssestsDir string // Assets directory + BuildkitVersion string // Buildkit version } // Login defines Docker login parameters. @@ -138,12 +139,6 @@ type ( } ) -//go:embed buildkit/buildkit.tar -var buildkitTarball embed.FS - -//go:embed buildkit/version.json -var buildKitVersionFile embed.FS - // Exec executes the plugin step func (p Plugin) Exec() error { @@ -248,29 +243,29 @@ func (p Plugin) Exec() error { var config BuildKitConfig if p.Builder.UseLoadedBuildkit { - configData, err := buildKitVersionFile.ReadFile("buildkit/version.json") + // Build paths for the version.json and buildkit.tar + versionFilePath := filepath.Join(p.Builder.AssestsDir, "version.json") + tarballFilePath := filepath.Join(p.Builder.AssestsDir, "buildkit.tar") + + // Read the version.json file from the filesystem + configData, err := os.ReadFile(versionFilePath) if err != nil { - fmt.Printf("Failed to read embedded buildkit version.json: %v\n", err) loadedBuildkitVersion = false - } - - if err := json.Unmarshal(configData, &config); err != nil { - fmt.Printf("Failed to read buildkit version.json: %v\n", err) + } else if err := json.Unmarshal(configData, &config); err != nil { loadedBuildkitVersion = false } - // Read the tarball from the embedded filesystem - data, err := buildkitTarball.ReadFile("buildkit/buildkit.tar") + // Read the tarball file from the filesystem + data, err := os.ReadFile(tarballFilePath) if err != nil { - fmt.Printf("Failed to load buildkit tarball: %v\n", err) loadedBuildkitTarball = false - } + } else { + loadCmd := commandLoad() + loadCmd.Stdin = bytes.NewReader(data) - loadCmd := commandLoad() - loadCmd.Stdin = bytes.NewReader(data) - if loadedBuildkitTarball { + // Attempt to load the tarball if err := loadCmd.Run(); err != nil { - fmt.Printf("error while loading buildkit image: %s\n", err) + fmt.Printf("Error while loading buildkit image: %s\n", err) loadedBuildkitTarball = false } } @@ -307,15 +302,16 @@ func (p Plugin) Exec() error { } } if shouldFallback { - // Replace the image in driver opts with the buildkit version - if p.Builder.UseLoadedBuildkit && loadedBuildkitTarball && loadedBuildkitVersion { - fmt.Printf("Using BuildKit Version: %s\n", config.BuildkitVersion) - for i, opt := range p.Builder.DriverOpts { - if strings.HasPrefix(opt, "image=") { - // Replace the part after image= with config.BuildkitVersion - p.Builder.DriverOpts[i] = fmt.Sprintf("image=%s", config.BuildkitVersion) - } + // Main code block + if (p.Builder.UseLoadedBuildkit && loadedBuildkitTarball && loadedBuildkitVersion) || p.Builder.BuildkitVersion != "" { + var version string + if p.Builder.UseLoadedBuildkit && loadedBuildkitTarball && loadedBuildkitVersion { + version = config.BuildkitVersion + } else { + version = p.Builder.BuildkitVersion } + fmt.Printf("Using BuildKit Version: %s\n", version) + updateImageVersion(&p.Builder.DriverOpts, version) } createCmd := cmdSetupBuildx(p.Builder, p.Builder.DriverOpts) raw, err = createCmd.Output() @@ -839,3 +835,12 @@ func writeSSHPrivateKey(key string) (path string, err error) { func trace(cmd *exec.Cmd) { fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) } + +// Helper function to update image version in driver options +func updateImageVersion(driverOpts *[]string, version string) { + for i, opt := range *driverOpts { + if strings.HasPrefix(opt, "image=") { + (*driverOpts)[i] = fmt.Sprintf("image=%s", version) + } + } +} diff --git a/docker/docker/Dockerfile.linux.amd64 b/docker/docker/Dockerfile.linux.amd64 index 279ecaa..f2c0776 100644 --- a/docker/docker/Dockerfile.linux.amd64 +++ b/docker/docker/Dockerfile.linux.amd64 @@ -5,6 +5,7 @@ ENV DOCKER_HOST=unix:///var/run/docker.sock ENV DOCKER_BUILDKIT=1 ENV BUILDKIT_PROGRESS=plain ENV DOCKER_CLI_EXPERIMENTAL=enabled +ENV PLUGIN_BUILDKIT_ASSETS_DIR=/buildkit ARG BUILDX_URL=https://github.com/docker/buildx/releases/download/v0.18.0/buildx-v0.18.0.linux-amd64 @@ -12,5 +13,12 @@ RUN mkdir -p $HOME/.docker/cli-plugins && \ wget -O $HOME/.docker/cli-plugins/docker-buildx $BUILDX_URL && \ chmod a+x $HOME/.docker/cli-plugins/docker-buildx +# Create /buildkit directory +RUN mkdir -p /buildkit + +# Add buildkit.tar and version +COPY buildkit/buildkit.tar /buildkit/buildkit.tar +COPY buildkit/version.json /buildkit/version.json + ADD release/linux/amd64/drone-docker /bin/ ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "/bin/drone-docker"] diff --git a/docker/docker/Dockerfile.linux.arm64 b/docker/docker/Dockerfile.linux.arm64 index 28ea4f8..ba886e8 100644 --- a/docker/docker/Dockerfile.linux.arm64 +++ b/docker/docker/Dockerfile.linux.arm64 @@ -5,6 +5,7 @@ ENV DOCKER_HOST=unix:///var/run/docker.sock ENV DOCKER_BUILDKIT=1 ENV BUILDKIT_PROGRESS=plain ENV DOCKER_CLI_EXPERIMENTAL=enabled +ENV PLUGIN_BUILDKIT_ASSETS_DIR=/buildkit ARG BUILDX_URL=https://github.com/docker/buildx/releases/download/v0.18.0/buildx-v0.18.0.linux-arm64 @@ -12,6 +13,12 @@ RUN mkdir -p $HOME/.docker/cli-plugins && \ wget -O $HOME/.docker/cli-plugins/docker-buildx $BUILDX_URL && \ chmod a+x $HOME/.docker/cli-plugins/docker-buildx +# Create /buildkit directory +RUN mkdir -p /buildkit + +# Add buildkit.tar and version +COPY buildkit/buildkit.tar /buildkit/buildkit.tar +COPY buildkit/version.json /buildkit/version.json ADD release/linux/arm64/drone-docker /bin/ ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "/bin/drone-docker"]