Skip to content

Commit

Permalink
Remove MUSL and enable threadless libgit2 support
Browse files Browse the repository at this point in the history
Use of MUSL was a temporary solution to mitigate cross-platform
issues while building openssl and libssh2. Since Unmanaged transport has
been deprecated, openssl and libssh2 dependencies are no longer required
and by extension MUSL.

Enables libgit2 threadless support and provides a regression assurance
for #339.

Signed-off-by: Paulo Gomes <paulo.gomes@weave.works>
  • Loading branch information
Paulo Gomes committed Jul 31, 2022
1 parent 11851a0 commit 3990e9c
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 142 deletions.
41 changes: 9 additions & 32 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.18
ARG XX_VERSION=1.1.0
ARG XX_VERSION=1.1.2

ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2-all
ARG LIBGIT2_TAG=v0.1.2
ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2-only
ARG LIBGIT2_TAG=v0.2.0

FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} AS libgit2-libs

Expand All @@ -17,7 +17,7 @@ FROM gostable AS go-linux
# These will be used at current arch to yield execute the cross compilations.
FROM go-${TARGETOS} AS build-base

RUN apk add --no-cache clang lld pkgconfig
RUN apk add clang lld pkgconfig

COPY --from=xx / /

Expand All @@ -37,23 +37,6 @@ COPY go.sum go.sum
# Cache modules
RUN go mod download

# The musl-tool-chain layer is an adhoc solution
# for the problem in which xx gets confused during compilation
# and a) looks for gold linker and then b) cannot find musl's dynamic linker.
FROM --platform=$BUILDPLATFORM alpine as musl-tool-chain

COPY --from=xx / /

RUN apk add bash curl tar

WORKDIR /workspace
COPY hack/download-musl.sh .

ARG TARGETPLATFORM
ARG TARGETARCH
RUN ROOT_DIR="$(pwd)" TARGET_ARCH="$(xx-info alpine-arch)" ENV_FILE=true \
./download-musl.sh

# Build stage install per target platform
# dependency and effectively cross compile the application.
FROM build-go-mod as build
Expand All @@ -64,7 +47,7 @@ COPY --from=libgit2-libs /usr/local/ /usr/local/

# Some dependencies have to installed
# for the target platform: https://github.com/tonistiigi/xx#go--cgo
RUN xx-apk add musl-dev gcc lld
RUN xx-apk add musl-dev gcc clang lld

WORKDIR /workspace

Expand All @@ -74,20 +57,14 @@ COPY controllers/ controllers/
COPY pkg/ pkg/
COPY internal/ internal/

COPY --from=musl-tool-chain /workspace/build /workspace/build

ARG TARGETPLATFORM
ARG TARGETARCH
ENV CGO_ENABLED=1

# Performance related changes:
# - Use read-only bind instead of copying go source files.
# - Cache go packages.
RUN export $(cat build/musl/$(xx-info alpine-arch).env | xargs) && \
export LIBRARY_PATH="/usr/local/$(xx-info triple):/usr/local/$(xx-info triple)/lib64" && \
export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \
export CGO_LDFLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2) -static" && \
GOARCH=$TARGETARCH go build \
RUN export LIBRARY_PATH="/usr/local/$(xx-info triple)" && \
export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig" && \
export CGO_LDFLAGS="$(pkg-config --static --libs --cflags libgit2) -static -fuse-ld=lld" && \
xx-go build \
-ldflags "-s -w" \
-tags 'netgo,osusergo,static_build' \
-o /image-automation-controller -trimpath main.go;
Expand Down
30 changes: 4 additions & 26 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ TAG ?= latest
CRD_OPTIONS ?= crd:crdVersions=v1

# Base image used to build the Go binary
LIBGIT2_IMG ?= ghcr.io/fluxcd/golang-with-libgit2-all
LIBGIT2_TAG ?= v0.1.2
LIBGIT2_IMG ?= ghcr.io/fluxcd/golang-with-libgit2-only
LIBGIT2_TAG ?= v0.2.0

# Allows for defining additional Docker buildx arguments,
# e.g. '--push'.
Expand Down Expand Up @@ -42,37 +42,20 @@ LIBGIT2_PATH := $(BUILD_DIR)/libgit2/$(LIBGIT2_TAG)
LIBGIT2_LIB_PATH := $(LIBGIT2_PATH)/lib
LIBGIT2_LIB64_PATH := $(LIBGIT2_PATH)/lib64
LIBGIT2 := $(LIBGIT2_LIB_PATH)/libgit2.a
MUSL-CC =

export CGO_ENABLED=1
export PKG_CONFIG_PATH=$(LIBGIT2_LIB_PATH)/pkgconfig
export LIBRARY_PATH=$(LIBGIT2_LIB_PATH)
export CGO_CFLAGS=-I$(LIBGIT2_PATH)/include -I$(LIBGIT2_PATH)/include/openssl

export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libgit2 2>/dev/null)

# The pkg-config command will yield warning messages until libgit2 is downloaded.
ifeq ($(shell uname -s),Darwin)
export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2 2>/dev/null)
GO_STATIC_FLAGS=-ldflags "-s -w" -tags 'netgo,osusergo,static_build'
else
export PKG_CONFIG_PATH:=$(PKG_CONFIG_PATH):$(LIBGIT2_LIB64_PATH)/pkgconfig
export LIBRARY_PATH:=$(LIBRARY_PATH):$(LIBGIT2_LIB64_PATH)
export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2 2>/dev/null)
endif

ifeq ($(shell uname -s),Linux)
ifeq ($(shell uname -m),x86_64)
# Linux x86_64 seem to be able to cope with the static libraries
# by having only musl-dev installed, without the need of using musl toolchain.
GO_STATIC_FLAGS=-ldflags "-s -w" -tags 'netgo,osusergo,static_build'
else
MUSL-PREFIX=$(BUILD_DIR)/musl/$(shell uname -m)-linux-musl-native/bin/$(shell uname -m)-linux-musl
MUSL-CC=$(MUSL-PREFIX)-gcc
export CC=$(MUSL-PREFIX)-gcc
export CXX=$(MUSL-PREFIX)-g++
export AR=$(MUSL-PREFIX)-ar
GO_STATIC_FLAGS=-ldflags "-s -w -extldflags \"-static\"" -tags 'netgo,osusergo,static_build'
endif
endif

# API (doc) generation utilities
Expand Down Expand Up @@ -213,16 +196,11 @@ controller-gen: ## Download controller-gen locally if necessary.
libgit2: $(LIBGIT2) ## Detect or download libgit2 library

COSIGN = $(GOBIN)/cosign
$(LIBGIT2): $(MUSL-CC)
$(LIBGIT2):
$(call go-install-tool,$(COSIGN),github.com/sigstore/cosign/cmd/cosign@latest)

IMG=$(LIBGIT2_IMG) TAG=$(LIBGIT2_TAG) PATH=$(PATH):$(GOBIN) ./hack/install-libraries.sh

$(MUSL-CC):
ifneq ($(shell uname -s),Darwin)
./hack/download-musl.sh
endif

# Find or download gen-crd-api-reference-docs
GEN_CRD_API_REFERENCE_DOCS = $(GOBIN)/gen-crd-api-reference-docs
.PHONY: gen-crd-api-reference-docs
Expand Down
22 changes: 22 additions & 0 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"testing"
"time"

git2go "github.com/libgit2/git2go/v33"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -53,6 +54,8 @@ func init() {
}

func TestMain(m *testing.M) {
mustHaveNoThreadSupport()

utilruntime.Must(imagev1_reflect.AddToScheme(scheme.Scheme))
utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme))
utilruntime.Must(imagev1.AddToScheme(scheme.Scheme))
Expand Down Expand Up @@ -90,3 +93,22 @@ func TestMain(m *testing.M) {

os.Exit(code)
}

// This provides a regression assurance for image-automation-controller/#339.
// Validates that:
// - libgit2 was built with no support for threads.
// - git2go accepts libgit2 built with no support for threads.
//
// The logic below does the validation of the former, whilst
// referring to git2go forces its init() execution, which is
// where any validation to that effect resides.
//
// git2go does not support threadless libgit2 by default,
// hence a fork is being used which disables such validation.
//
// TODO: extract logic into pkg.
func mustHaveNoThreadSupport() {
if git2go.Features()&git2go.FeatureThreads != 0 {
panic("libgit2 must not be build with thread support")
}
}
10 changes: 10 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ go 1.18

replace github.com/fluxcd/image-automation-controller/api => ./api

// A temporary fork of git2go was created to enable use
// of libgit2 without thread support to fix:
// fluxcd/image-automation-controller/#339.
//
// This can be removed once libgit2/git2go#918 is merged.
//
// The fork automatically releases new patches based on upstream:
// https://github.com/pjbgf/git2go/commit/d72e39cdc20f7fe014ba73072b01ba7b569e9253
replace github.com/libgit2/git2go/v33 => github.com/pjbgf/git2go/v33 v33.0.9-nothread-check

require (
github.com/Masterminds/sprig/v3 v3.2.2
github.com/ProtonMail/go-crypto v0.0.0-20220714114130-e85cedf506cd
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/libgit2/git2go/v33 v33.0.9 h1:4ch2DJed6IhJO28BEohkUoGvxLsRzUjxljoNFJ6/O78=
github.com/libgit2/git2go/v33 v33.0.9/go.mod h1:KdpqkU+6+++4oHna/MIOgx4GCQ92IPCdpVRMRI80J+4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
Expand Down Expand Up @@ -536,6 +534,8 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pjbgf/git2go/v33 v33.0.9-nothread-check h1:gSK7FaLECIM3VSuBOAsVZQtWd+51iTB5lv9RyxhOYMk=
github.com/pjbgf/git2go/v33 v33.0.9-nothread-check/go.mod h1:KdpqkU+6+++4oHna/MIOgx4GCQ92IPCdpVRMRI80J+4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
71 changes: 0 additions & 71 deletions hack/download-musl.sh

This file was deleted.

8 changes: 4 additions & 4 deletions hack/install-libraries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ install_libraries(){
fi
fi

FILE_NAME="linux-$(uname -m)-all-libs.tar.gz"
DIR="libgit2-linux-all-libs"
FILE_NAME="linux-$(uname -m)-libgit2-only.tar.gz"
DIR="linux-libgit2-only"
if [[ $OSTYPE == 'darwin'* ]]; then
FILE_NAME="darwin-all-libs.tar.gz"
DIR="darwin-all-libs"
FILE_NAME="darwin-libgit2-only.tar.gz"
DIR="darwin-libgit2-only"
fi

download_files "${FILE_NAME}"
Expand Down
11 changes: 4 additions & 7 deletions tests/fuzz/oss_fuzz_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

set -euxo pipefail

LIBGIT2_TAG="${LIBGIT2_TAG:-v0.1.2}"
LIBGIT2_TAG="${LIBGIT2_TAG:-v0.2.0}"
GOPATH="${GOPATH:-/root/go}"
GO_SRC="${GOPATH}/src"
PROJECT_PATH="github.com/fluxcd/image-automation-controller"
Expand All @@ -28,9 +28,9 @@ export TARGET_DIR="$(/bin/pwd)/build/libgit2/${LIBGIT2_TAG}"
# For most cases, libgit2 will already be present.
# The exception being at the oss-fuzz integration.
if [ ! -d "${TARGET_DIR}" ]; then
curl -o output.tar.gz -LO "https://github.com/fluxcd/golang-with-libgit2/releases/download/${LIBGIT2_TAG}/linux-$(uname -m)-all-libs.tar.gz"
curl -o output.tar.gz -LO "https://github.com/fluxcd/golang-with-libgit2/releases/download/${LIBGIT2_TAG}/linux-$(uname -m)-libgit2-only.tar.gz"

DIR=libgit2-linux-all-libs
DIR=linux-libgit2-only
NEW_DIR="$(/bin/pwd)/build/libgit2/${LIBGIT2_TAG}"
INSTALLED_DIR="/home/runner/work/golang-with-libgit2/golang-with-libgit2/build/${DIR}"

Expand Down Expand Up @@ -77,7 +77,6 @@ SOURCE_VER=$(go list -m github.com/fluxcd/source-controller/api | awk '{print $2
REFLECTOR_VER=$(go list -m github.com/fluxcd/image-reflector-controller/api | awk '{print $2}')

go mod download
go mod tidy -go=1.18
go get -d github.com/fluxcd/image-automation-controller
go get -d github.com/AdaLogics/go-fuzz-headers

Expand All @@ -103,9 +102,7 @@ function go_compile(){
go-fuzz -tags gofuzz -func="${function}" -o "${fuzzer}.a" .
${CXX} ${CXXFLAGS} ${LIB_FUZZING_ENGINE} -o "${OUT}/${fuzzer}" \
"${fuzzer}.a" \
"${TARGET_DIR}/lib/libgit2.a" "${TARGET_DIR}/lib/libssh2.a" \
"${TARGET_DIR}/lib/libz.a" "${TARGET_DIR}/lib64/libssl.a" \
"${TARGET_DIR}/lib64/libcrypto.a" \
"${TARGET_DIR}/lib/libgit2.a" \
-fsanitize="${SANITIZER}"
fi
}
Expand Down

0 comments on commit 3990e9c

Please sign in to comment.