From 3b3a347bf04ab99f10c6e86dc729aa08bad50c2a Mon Sep 17 00:00:00 2001 From: Tyler Schade Date: Sun, 30 Jun 2024 20:44:38 -0400 Subject: [PATCH] Enable arm builds for OPA envoy plugin Signed-off-by: Tyler Schade --- .gitignore | 1 + Dockerfile | 9 +- Makefile | 171 +++++++++++++++++++++++--------- build/ensure-linux-toolchain.sh | 52 ++++++++++ build/get-plugin-rev.sh | 3 + 5 files changed, 184 insertions(+), 52 deletions(-) create mode 100755 build/ensure-linux-toolchain.sh diff --git a/.gitignore b/.gitignore index 714c1e2d7..89280165e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ opa_* _release site.tar.gz *.bak +.go/ # runtime artifacts policies diff --git a/Dockerfile b/Dockerfile index c8bb0ae96..1807324a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,18 +6,21 @@ ARG BASE FROM ${BASE} +LABEL org.opencontainers.image.authors="Ashutosh Narkar " + # Any non-zero number will do, and unfortunately a named user will not, as k8s # pod securityContext runAsNonRoot can't resolve the user ID: # https://github.com/kubernetes/kubernetes/issues/40958. ARG USER=1000:1000 USER ${USER} -MAINTAINER Ashutosh Narkar +ARG TARGETOS +ARG TARGETARCH WORKDIR /app -COPY opa_envoy_linux_GOARCH /app +COPY opa_envoy_${TARGETOS}_${TARGETARCH} /app -ENTRYPOINT ["./opa_envoy_linux_GOARCH"] +ENTRYPOINT ["./app"] CMD ["run"] diff --git a/Makefile b/Makefile index 3bb9405d0..fe7441bb2 100644 --- a/Makefile +++ b/Makefile @@ -8,21 +8,25 @@ VERSION_ISTIO := $(VERSION_OPA)-istio$(shell ./build/get-plugin-rev.sh) PACKAGES := $(shell go list ./.../ | grep -v 'vendor') +DOCKER := docker + +DOCKER_UID ?= 0 +DOCKER_GID ?= 0 CGO_ENABLED ?= 1 WASM_ENABLED ?= 1 +GOARCH ?= $(shell go env GOARCH) # GOPROXY=off: Don't pull anything off the network # see https://github.com/thepudds/go-module-knobs/blob/master/README.md -GO := CGO_ENABLED=$(CGO_ENABLED) GO111MODULE=on GOFLAGS=-mod=vendor GOPROXY=off go +GO := CGO_ENABLED=$(CGO_ENABLED) GOARCH=$(GOARCH) GO111MODULE=on GOFLAGS=-mod=vendor GOPROXY=off go GOVERSION := $(shell cat ./.go-version) -GOARCH := $(shell go env GOARCH) GOOS := $(shell go env GOOS) DISABLE_CGO := CGO_ENABLED=0 BIN := opa_envoy_$(GOOS)_$(GOARCH) -REPOSITORY := openpolicyagent +REPOSITORY ?= openpolicyagent IMAGE := $(REPOSITORY)/opa GO_TAGS := -tags= @@ -49,10 +53,9 @@ LDFLAGS := "-X github.com/open-policy-agent/opa/version.Version=$(VERSION) \ -X github.com/open-policy-agent/opa/version.Timestamp=$(BUILD_TIMESTAMP) \ -X github.com/open-policy-agent/opa/version.Hostname=$(BUILD_HOSTNAME)" -.PHONY: all build build-darwin build-linux build-linux-static build-windows clean check check-fmt check-vet check-lint \ - deploy-ci docker-login generate image image-quick image-static image-quick-static \ - push push-static push-latest push-latest-static tag-latest \ - tag-latest-static test test-cluster test-e2e version +export DOCKER_BUILDKIT := 1 + +DOCKER_PLATFORMS := linux/amd64,linux/arm64 ###################################################### # @@ -60,103 +63,145 @@ LDFLAGS := "-X github.com/open-policy-agent/opa/version.Version=$(VERSION) \ # ###################################################### +.PHONY: all all: build test check +.PHONY: version version: @echo $(VERSION) +.PHONY: generate generate: $(GO) generate ./... +.PHONY: build build: generate $(GO) build $(GO_TAGS) -o $(BIN) -ldflags $(LDFLAGS) ./cmd/opa-envoy-plugin/... +.PHONY: build-darwin build-darwin: @$(MAKE) build GOOS=darwin -build-linux: +.PHONY: build-linux +build-linux: ensure-release-dir ensure-linux-toolchain @$(MAKE) build GOOS=linux -build-linux-static: +.PHONY: build-linux-static +build-linux-static: ensure-release-dir ensure-linux-toolchain @$(MAKE) build GOOS=linux WASM_ENABLED=0 CGO_ENABLED=0 +.PHONY: build-windows build-windows: @$(MAKE) build GOOS=windows +.PHONY: image image: @$(MAKE) ci-go-build-linux @$(MAKE) image-quick +.PHONY: start-builder +start-builder: + @./build/buildx_workaround.sh + +.PHONY: image-static image-static: CGO_ENABLED=0 WASM_ENABLED=0 $(MAKE) ci-go-build-linux-static @$(MAKE) image-quick-static +.PHONY: image-quick image-quick: - sed -e 's/GOARCH/$(GOARCH)/g' Dockerfile > .Dockerfile_$(GOARCH) - docker build -t $(IMAGE):$(VERSION) --build-arg BASE=chainguard/glibc-dynamic -f .Dockerfile_$(GOARCH) . - docker tag $(IMAGE):$(VERSION) $(IMAGE):$(VERSION_ISTIO) - -image-quick-static: - sed -e 's/GOARCH/$(GOARCH)/g' Dockerfile > .Dockerfile_$(GOARCH) - docker build -t $(IMAGE):$(VERSION)-static --build-arg BASE=chainguard/static:latest -f .Dockerfile_$(GOARCH) . - docker tag $(IMAGE):$(VERSION)-static $(IMAGE):$(VERSION_ISTIO)-static - -push: - docker push $(IMAGE):$(VERSION) - docker push $(IMAGE):$(VERSION_ISTIO) - -push-static: - docker push $(IMAGE):$(VERSION)-static - docker push $(IMAGE):$(VERSION_ISTIO)-static - -tag-latest: - docker tag $(IMAGE):$(VERSION) $(IMAGE):latest-envoy - docker tag $(IMAGE):$(VERSION) $(IMAGE):latest-istio - -tag-latest-static: - docker tag $(IMAGE):$(VERSION)-static $(IMAGE):latest-envoy-static - docker tag $(IMAGE):$(VERSION)-static $(IMAGE):latest-istio-static - -push-latest: - docker push $(IMAGE):latest-envoy - docker push $(IMAGE):latest-istio + $(MAKE) image-quick-$(GOARCH) -push-latest-static: - docker push $(IMAGE):latest-envoy-static - docker push $(IMAGE):latest-istio-static +.PHONY: image-quick-% +image-quick-%: + $(DOCKER) build --platform=linux/$(GOARCH) -t $(IMAGE):$(VERSION) --build-arg BASE=chainguard/glibc-dynamic -f Dockerfile . +.PHONY: image-quick-static +image-quick-static: + $(MAKE) image-quick-static-$(GOARCH) + +.PHONY: image-quick-static-% +image-quick-static-%: + $(DOCKER) build --platform=linux/$* --push -t $(IMAGE):$(VERSION)-static --build-arg BASE=chainguard/static:latest -f Dockerfile . + +.PHONY: push-manifest-list +push-manifest-list: + $(DOCKER) buildx build --platform=$(DOCKER_PLATFORMS) \ + --push -t $(IMAGE):$(VERSION) \ + --build-arg BASE=chainguard/glibc-dynamic:latest \ + -f Dockerfile . + + $(DOCKER) buildx build --platform=$(DOCKER_PLATFORMS) \ + --push -t $(IMAGE):$(VERSION_ISTIO) \ + --build-arg BASE=chainguard/glibc-dynamic:latest \ + -f Dockerfile . + +.PHONY: push-manifest-list-latest +push-manifest-list-latest: + $(DOCKER) buildx build --platform=$(DOCKER_PLATFORMS) \ + --push -t $(IMAGE):latest-envoy \ + --build-arg BASE=chainguard/static:latest \ + -f Dockerfile . + + $(DOCKER) buildx build --platform=$(DOCKER_PLATFORMS) \ + --push -t $(IMAGE):latest-istio \ + --build-arg BASE=chainguard/static:latest \ + -f Dockerfile . + +.PHONY: push-manifest-list-static +push-manifest-list-static: + $(DOCKER) buildx build --platform=$(DOCKER_PLATFORMS) \ + --push -t $(IMAGE):$(VERSION)-static \ + --build-arg BASE=chainguard/static:latest \ + -f Dockerfile . + + $(DOCKER) buildx build --platform=$(DOCKER_PLATFORMS) \ + --push -t $(IMAGE):$(VERSION_ISTIO)-static \ + --build-arg BASE=chainguard/static:latest \ + -f Dockerfile . + +.PHONY: docker-login docker-login: @echo "Docker Login..." - @echo ${DOCKER_PASSWORD} | docker login -u ${DOCKER_USER} --password-stdin + @echo ${DOCKER_PASSWORD} | $(DOCKER) login -u ${DOCKER_USER} --password-stdin -deploy-ci: docker-login image image-static push tag-latest push-latest \ - push-static tag-latest-static push-latest-static +.PHONY: deploy-ci +deploy-ci: ensure-release-dir start-builder ci-build-binaries docker-login push-manifest-list-latest ci-build-binaries-static push-manifest-list-static +.PHONY: test test: generate $(DISABLE_CGO) $(GO) test -v -bench=. $(PACKAGES) +.PHONY: test-e2e test-e2e: bats -t test/bats/test.bats +.PHONY: test-cluster test-cluster: @./build/install-istio-with-kind.sh +.PHONY: clean clean: rm -f .Dockerfile_* rm -f opa_*_* rm -f *.so +.PHONY: check check: check-fmt check-vet check-lint +.PHONY: check-fmt check-fmt: ./build/check-fmt.sh +.PHONY: check-vet check-vet: ./build/check-vet.sh +.PHONY: check-lint check-lint: ./build/check-lint.sh +.PHONY: generatepb generatepb: protoc --proto_path=test/files \ --descriptor_set_out=test/files/combined.pb \ @@ -164,31 +209,59 @@ generatepb: test/files/example/Example.proto \ test/files/book/Book.proto -CI_GOLANG_DOCKER_MAKE := docker run \ +CI_GOLANG_DOCKER_MAKE := $(DOCKER) run \ $(DOCKER_FLAGS) \ - -u $(shell id -u):$(shell id -g) \ + -u $(DOCKER_UID):$(DOCKER_GID) \ -v $(PWD):/src \ -w /src \ -e GOCACHE=/src/.go/cache \ -e CGO_ENABLED=$(CGO_ENABLED) \ -e WASM_ENABLED=$(WASM_ENABLED) \ -e TELEMETRY_URL=$(TELEMETRY_URL) \ + -e GOARCH=$(GOARCH) \ golang:$(GOVERSION) \ - make + make + +.PHONY: ensure-linux-toolchain +ensure-linux-toolchain: +ifeq ($(CGO_ENABLED),1) + $(eval export CC = $(shell GOARCH=$(GOARCH) build/ensure-linux-toolchain.sh)) +else + @echo "CGO_ENABLED=$(CGO_ENABLED). No need to check gcc toolchain." +endif .PHONY: ci-go-% ci-go-%: $(CI_GOLANG_DOCKER_MAKE) "$*" +.PHONY: ci-build-binaries +ci-build-binaries: ensure-linux-toolchain + $(MAKE) ci-go-build-linux GOARCH=arm64 + $(MAKE) ci-go-build-linux GOARCH=amd64 + +.PHONY: ci-build-binaries-static +ci-build-binaries-static: ensure-linux-toolchain + $(MAKE) ci-go-build-linux-static GOARCH=arm64 + $(MAKE) ci-go-build-linux-static GOARCH=amd64 + +.PHONY: tag-latest +tag-latest: + docker tag $(IMAGE):$(VERSION) $(IMAGE):latest-envoy + docker tag $(IMAGE):$(VERSION) $(IMAGE):latest-istio + +.PHONY: tag-latest-static +tag-latest-static: + docker tag $(IMAGE):$(VERSION)-static $(IMAGE):latest-envoy-static + docker tag $(IMAGE):$(VERSION)-static $(IMAGE):latest-istio-static + .PHONY: release release: - docker run $(DOCKER_FLAGS) \ + $(DOCKER) run $(DOCKER_FLAGS) \ -v $(PWD)/$(RELEASE_DIR):/$(RELEASE_DIR) \ -v $(PWD):/_src \ $(RELEASE_BUILD_IMAGE) \ /_src/build/build-release.sh --version=$(VERSION) --output-dir=/$(RELEASE_DIR) --source-url=/_src - .PHONY: release-build-linux release-build-linux: ensure-release-dir @$(MAKE) build GOOS=linux CGO_ENABLED=0 WASM_ENABLED=0 @@ -200,7 +273,7 @@ release-build-darwin: ensure-release-dir mv opa_envoy_darwin_$(GOARCH) $(RELEASE_DIR)/ .PHONY: release-build-windows -release-build-windows: ensure-release-dir +release-build-windows: ensure-release-dirart @$(MAKE) build GOOS=windows CGO_ENABLED=0 WASM_ENABLED=0 mv opa_envoy_windows_$(GOARCH) $(RELEASE_DIR)/opa_envoy_windows_$(GOARCH).exe diff --git a/build/ensure-linux-toolchain.sh b/build/ensure-linux-toolchain.sh new file mode 100755 index 000000000..9f1c2ad47 --- /dev/null +++ b/build/ensure-linux-toolchain.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -eo pipefail + +case "$(uname -m | tr '[:upper:]' '[:lower:]')" in + amd64 | x86_64 | x64) + HOST_ARCH=amd64 + ;; + arm64 | aarch64) + HOST_ARCH=arm64 + ;; + *) + echo "Error: Host architecture not supported." >&2 + exit 1 + ;; +esac + +# Native build +if [ "${GOARCH}" = "${HOST_ARCH}" ]; then + if ! [ -x "$(command -v gcc)" ]; then + echo "Error: gcc not found." >&2 + exit 1 + fi + exit 0 +fi + +# Cross-compile +case "${GOARCH}" in + amd64) + PKG=gcc-x86-64-linux-gnu + CC=x86_64-linux-gnu-gcc + ;; + arm64) + PKG=gcc-aarch64-linux-gnu + CC=aarch64-linux-gnu-gcc + ;; + *) + echo "Error: Target architecture ${GOARCH} not supported." >&2 + exit 1 + ;; +esac + +type -f ${CC} 2>/dev/null && exit 0 + +if ! [ -x "$(command -v apt-get)" ]; then + echo "Error: apt-get not found. Could not install missing toolchain." >&2 + exit 1 +fi + +apt-get update >/dev/null && \ + apt-get install -y ${PKG} >/dev/null + +echo ${CC} \ No newline at end of file diff --git a/build/get-plugin-rev.sh b/build/get-plugin-rev.sh index f02499c7e..95c989603 100755 --- a/build/get-plugin-rev.sh +++ b/build/get-plugin-rev.sh @@ -1,6 +1,9 @@ #!/usr/bin/env bash # Script to get number of commits from the last OPA revendoring +# trust our mounted directory +git config --global --add safe.directory /src + LINE=$(git grep -n "github.com/open-policy-agent/opa " go.mod | awk -F: '{ print $2 }') GIT_SHA=$(git log -n 1 --pretty=format:%H -L $LINE,$LINE:go.mod | head -1) COMMITS=$(git rev-list $GIT_SHA..HEAD --count)