Skip to content

Commit

Permalink
Introduce Makefile-v2.mk (#2084)
Browse files Browse the repository at this point in the history
* Introduce Makefile.v2

This commit temporarily introduces a Makefile.v2, introduced initially
as a separate file for easier comparison to the existing Makefile.

Makefile.v2 is intended to eventually replace the original Makefile and
follows the designed outlined in #2052.

It includes targets only needed for local development and testing.
Targets only intended for CI are purposefully omitted to keep the
Makefile as simple as possible.

It is controlled primarily by environment variables, which are
documented at the comment at the top of the Makefile. That comment may
be printed to stdout by calling `make -f Makefile.v2 help`.

The new build image, grafana/agent-build-image:v0.15.0, is used for
proxying Makefile commands when the `USE_CONTAINER=1` environment
variable is set.

A Docker volume cache can be initialized to speed up builds in the build
container. Run `make -f Makefile.v2 build-container-cache` to create the
cache and `make -f Makefile.v2 clean` to remove it. The cache stores the
Go module cache and Go build cache. The Makefile will detect the cache
and automatically use it when proxying commands to the build container.
Credit to @captncraig for the idea of using Docker volumes for caching
builds.

This first commit is opened early for feedback on the approach. Missing
functionality will be added in future commits if the approach seems OK:

1. There is currently no equivalent target to test-packages
2. The Dockerfiles still build the agent instead of copying over a built
   binary

* rename Makefile.v2 to Makefile-v2.mk

This allows Github syntax highlighting to work properly.

* add new Dockerfiles

Add new Dockerfiles which use Makefile-v2.mk for building the image and
caches for running the make command.

This allows the Dockerfile to continue building the image while taking
advantage of a shared Go module and Go build cache for improved
subsequent build times.

The Dockerfile.new files are added as new files to make comparison
easier. They will fully replace the Dockerfile and Dockerfile.buildx
variants once Makefile-v2 replaces the existing Makefile.

This does not support building multiplatform images, which is only
useful from the context of CI (as producing multiplatform images
requires pushing the images to the registry, which should never be done
locally during development)

* add dist* targets

* make dist-agent-installer work

* address review feedback
  • Loading branch information
rfratto authored Sep 7, 2022
1 parent cbbfabb commit 0b2804e
Show file tree
Hide file tree
Showing 11 changed files with 848 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
build/
data/
data-agent/
dist/
web/ui/node_modules/
web/ui/build/
packaging/windows/LICENSE
packaging/windows/agent-windows-amd64.exe
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ data-agent
/cmd/agentctl/agentctl
/cmd/agent-operator/agent-operator
/cmd/grafana-agent-crow/grafana-agent-crow
/build/
/dist/
/packaging/windows/LICENSE
/packaging/windows/agent-windows-amd64.exe
Expand Down
296 changes: 296 additions & 0 deletions Makefile-v2.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
## Build, test, and generate code for various parts of Grafana Agent.
##
## At least Go 1.18, git, and a moderately recent version of Docker is required
## to be able to use the Makefile. This list isn't exhaustive and there are other
## dependencies for the generate-* targets. If you do not have the full list of
## build dependencies, you may set USE_CONTAINER=1 to proxy build commands to a
## build container.
##
## Other environment variables can be used to tweak behaviors of targets.
## See the bottom of this help section for the full list of supported
## environment variables.
##
## Usage:
## make <target>
##
## Targets for running tests:
##
## test Run tests
## lint Lint code
##
## Targets for building binaries:
##
## binaries Compiles all binaries.
## agent Compiles cmd/agent to $(AGENT_BINARY)
## agentctl Compiles cmd/agentctl to $(AGENTCTL_BINARY)
## operator Compiles cmd/agent-operator to $(OPERATOR_BINARY)
## crow Compiles tools/crow to $(CROW_BINARY)
## smoke Compiles tools/smoke to $(SMOKE_BINARY)
##
## Targets for building Docker images:
##
## images Builds all Docker images.
## agent-image Builds agent Docker image.
## agentctl-image Builds agentctl Docker image.
## operator-image Builds operator Docker image.
## crow-image Builds crow Docker image.
## smoke-image Builds smoke test Docker image.
##
## Targets for packaging:
##
## dist Produce release assets for everything.
## dist-agent-binaries Produce release-ready agent binaries.
## dist-agentctl-binaries Produce release-ready agentctl binaries.
## dist-packages Produce release-ready DEB and RPM packages.
## dist-agent-installer Produce a Windows installer for Grafana Agent.
##
## Targets for generating assets:
##
## generate Generate everything.
## generate-crds Generate Grafana Agent Operator CRDs.
## generate-manifests Generate production/kubernetes YAML manifests.
## generate-dashboards Generate dashboards in example/docker-compose after
## changing Jsonnet.
## generate-protos Generate protobuf files.
##
## Other targets:
##
## build-container-cache Create a cache for the build container to speed up
## subsequent proxied builds
## clean Clean caches and built binaries
## help Displays this message
## info Print Makefile-specific environment variables
##
## Environment variables:
##
## USE_CONTAINER Set to 1 to enable proxying commands to build container
## AGENT_IMAGE Image name:tag built by `make agent-image`
## AGENTCTL_IMAGE Image name:tag built by `make agentctl-image`
## OPERATOR_IMAGE Image name:tag built by `make operator-image`
## CROW_IMAGE Image name:tag built by `make crow-image`
## SMOKE_IMAGE Image name:tag built by `make smoke-image`
## BUILD_IMAGE Image name:tag used by USE_CONTAINER=1
## AGENT_BINARY Output path of `make agent` (default build/agent)
## AGENTCTL_BINARY Output path of `make agentctl` (default build/agentctl)
## OPERATOR_BINARY Output path of `make operator` (default build/agent-operator)
## CROW_BINARY Output path of `make crow` (default build/agent-crow)
## SMOKE_BINARY Output path of `make smoke` (default build/agent-smoke)
## GOOS Override OS to build binaries for
## GOARCH Override target architecture to build binaries for
## GOARM Override ARM version (6 or 7) when GOARCH=arm
## CGO_ENABLED Set to 0 to disable Cgo for builds
## RELEASE_BUILD Set to 1 to build release binaries
## VERSION Version to inject into built binaries.
## GO_TAGS Extra tags to use when building.

# TODO(rfratto): test-packages target
#
# This depends on some reworking of how the Go tests in ./packaging works to
# assume that packages have already been built so we don't have to hook in
# packaging code here.

include tools/make/*.mk

AGENT_IMAGE ?= grafana/agent:latest
AGENTCTL_IMAGE ?= grafana/agentctl:latest
OPERATOR_IMAGE ?= grafana/agent-operator:latest
CROW_IMAGE ?= us.gcr.io/kubernetes-dev/grafana/agent-crow:latest
SMOKE_IMAGE ?= us.gcr.io/kubernetes-dev/grafana/agent-smoke:latest
AGENT_BINARY ?= build/agent
AGENTCTL_BINARY ?= build/agentctl
OPERATOR_BINARY ?= build/agent-operator
CROW_BINARY ?= build/agent-crow
SMOKE_BINARY ?= build/agent-smoke
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)
GOARM ?= $(shell go env GOARM)
CGO_ENABLED ?= 1
RELEASE_BUILD ?= 0

# List of all environment variables which will propagate to the build
# container. USE_CONTAINER must _not_ be included to avoid infinite recursion.
PROPAGATE_VARS := \
AGENT_IMAGE AGENTCTL_IMAGE OPERATOR_IMAGE CROW_IMAGE SMOKE_IMAGE \
BUILD_IMAGE GOOS GOARCH GOARM CGO_ENABLED RELEASE_BUILD \
AGENT_BINARY AGENTCTL_BINARY OPERATOR_BINARY CROW_BINARY SMOKE_BINARY \
VERSION GO_TAGS

#
# Constants for targets
#

GO_ENV := GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) CGO_ENABLED=$(CGO_ENABLED)

VERSION ?= $(shell ./tools/image-tag)
GIT_REVISION := $(shell git rev-parse --short HEAD)
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
VPREFIX := github.com/grafana/agent/pkg/build
GO_LDFLAGS := -X $(VPREFIX).Branch=$(GIT_BRANCH) \
-X $(VPREFIX).Version=$(VERSION) \
-X $(VPREFIX).Revision=$(GIT_REVISION) \
-X $(VPREFIX).BuildUser=$(shell whoami)@$(shell hostname) \
-X $(VPREFIX).BuildDate=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")

DEFAULT_FLAGS := $(GO_FLAGS)
DEBUG_GO_FLAGS := -gcflags "all=-N -l" -ldflags "$(GO_LDFLAGS)" -tags "netgo $(GO_TAGS)"
RELEASE_GO_FLAGS := -ldflags "-s -w $(GO_LDFLAGS)" -tags "netgo $(GO_TAGS)"

ifeq ($(RELEASE_BUILD),1)
GO_FLAGS := $(DEFAULT_FLAGS) $(RELEASE_GO_FLAGS)
else
GO_FLAGS := $(DEFAULT_FLAGS) $(DEBUG_GO_FLAGS)
endif

#
# Targets for running tests
#
# These targets currently don't support proxying to a build container due to
# difficulties with testing ./pkg/util/k8s and testing packages.
#

.PHONY: lint
lint:
golangci-lint run -v --timeout=10m

.PHONY: test
# We have to run test twice: once for all packages with -race and then once
# more without -race for packages that have known race detection issues.
test:
$(GO_ENV) go test $(CGO_FLAGS) -race ./...
$(GO_ENV) go test $(CGO_FLAGS) ./pkg/integrations/node_exporter ./pkg/logs ./pkg/operator ./pkg/util/k8s

#
# Targets for building binaries
#

.PHONY: binaries agent agentctl operator crow smoke
binaries: agent agentctl operator crow smoke

agent:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
$(GO_ENV) go build $(GO_FLAGS) -o $(AGENT_BINARY) ./cmd/agent
endif

agentctl:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
$(GO_ENV) go build $(GO_FLAGS) -o $(AGENTCTL_BINARY) ./cmd/agentctl
endif

operator:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
$(GO_ENV) go build $(GO_FLAGS) -o $(OPERATOR_BINARY) ./cmd/agent-operator
endif

crow:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
$(GO_ENV) go build $(GO_FLAGS) -o $(CROW_BINARY) ./tools/crow
endif

smoke:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
$(GO_ENV) go build $(GO_FLAGS) -o $(SMOKE_BINARY) ./tools/smoke
endif

#
# Targets for building Docker images
#

DOCKER_FLAGS := --build-arg RELEASE_BUILD=$(RELEASE_BUILD) --build-arg VERSION=$(VERSION)

.PHONY: images agent-image agentctl-image operator-image crow-image smoke-image
images: agent-image agentctl-image operator-image crow-image smoke-image

agent-image:
DOCKER_BUILDKIT=1 docker build $(DOCKER_FLAGS) -t $(AGENT_IMAGE) -f cmd/agent/Dockerfile.new .
agentctl-image:
DOCKER_BUILDKIT=1 docker build $(DOCKER_FLAGS) -t $(AGENTCTL_IMAGE) -f cmd/agentctl/Dockerfile.new .
operator-image:
DOCKER_BUILDKIT=1 docker build $(DOCKER_FLAGS) -t $(OPERATOR_IMAGE) -f cmd/agent-operator/Dockerfile.new .
crow-image:
DOCKER_BUILDKIT=1 docker build $(DOCKER_FLAGS) -t $(CROW_IMAGE) -f tools/crow/Dockerfile.new .
smoke-image:
DOCKER_BUILDKIT=1 docker build $(DOCKER_FLAGS) -t $(SMOKE_IMAGE) -f tools/smoke/Dockerfile.new .

#
# Targets for generating assets
#

.PHONY: generate generate-crds generate-manifests generate-dashboards generate-protos
generate: generate-crds generate-manifests generate-dashboards generate-protos

generate-crds:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
bash ./tools/generate-crds.bash
endif

generate-manifests:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
cd production/kubernetes/build && bash build.sh
endif

generate-dashboards:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
cd example/docker-compose && jb install && \
cd grafana/dashboards && jsonnet template.jsonnet -J ../../vendor -m .
endif

generate-protos:
ifeq ($(USE_CONTAINER),1)
$(RERUN_IN_CONTAINER)
else
go generate ./pkg/agentproto/
endif

#
# Other targets
#
# build-container-cache and clean-build-container-cache are defined in
# Makefile.build-container.
#

.PHONY: clean
clean: clean-dist clean-build-container-cache
rm -rf ./build/*

.PHONY: info
info:
@printf "USE_CONTAINER = $(USE_CONTAINER)\n"
@printf "AGENT_IMAGE = $(AGENT_IMAGE)\n"
@printf "AGENTCTL_IMAGE = $(AGENTCTL_IMAGE)\n"
@printf "OPERATOR_IMAGE = $(OPERATOR_IMAGE)\n"
@printf "CROW_IMAGE = $(CROW_IMAGE)\n"
@printf "SMOKE_IMAGE = $(SMOKE_IMAGE)\n"
@printf "BUILD_IMAGE = $(BUILD_IMAGE)\n"
@printf "AGENT_BINARY = $(AGENT_BINARY)\n"
@printf "AGENTCTL_BINARY = $(AGENTCTL_BINARY)\n"
@printf "OPERATOR_BINARY = $(OPERATOR_BINARY)\n"
@printf "CROW_BINARY = $(CROW_BINARY)\n"
@printf "SMOKE_BINARY = $(SMOKE_BINARY)\n"
@printf "GOOS = $(GOOS)\n"
@printf "GOARCH = $(GOARCH)\n"
@printf "GOARM = $(GOARM)\n"
@printf "CGO_ENABLED = $(CGO_ENABLED)\n"
@printf "RELEASE_BUILD = $(RELEASE_BUILD)\n"
@printf "VERSION = $(VERSION)\n"
@printf "GO_TAGS = $(GO_TAGS)\n"

# awk magic to print out the comment block at the top of this file.
.PHONY: help
help:
@awk 'BEGIN {FS="## "} /^##\s*(.*)/ { print $$2 }' $(MAKEFILE_LIST)
35 changes: 35 additions & 0 deletions cmd/agent-operator/Dockerfile.new
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# syntax=docker/dockerfile:1.4

# NOTE: This Dockerfile can only be built using BuildKit. BuildKit is used by
# default when running `docker buildx build` or when DOCKER_BUILDKIT=1 is set
# in environment variables.

FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.15.0 as build
ARG BUILDPLATFORM
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG RELEASE_BUILD=1
ARG VERSION

COPY . /src/agent
WORKDIR /src/agent

RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
GOOS=$TARGETOS GOARCH=$TARGETARCH GOARM=${TARGETVARIANT#v} \
RELEASE_BUILD=${RELEASE_BUILD} VERISON=${VERSION} \
make -f Makefile-v2.mk operator

FROM ubuntu:jammy

# Install dependencies needed at runtime.
RUN <<EOF
apt-get update
apt-get install -qy libsystemd-dev tzdata ca-certificates
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
EOF

COPY --from=build /src/agent/build/agent-operator /bin/agent-operator
ENTRYPOINT ["/bin/agent-operator"]
49 changes: 49 additions & 0 deletions cmd/agent/Dockerfile.new
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# syntax=docker/dockerfile:1.4

# NOTE: This Dockerfile can only be built using BuildKit. BuildKit is used by
# default when running `docker buildx build` or when DOCKER_BUILDKIT=1 is set
# in environment variables.

FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.15.0 as build
ARG BUILDPLATFORM
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG RELEASE_BUILD=1
ARG VERSION

# TODO(rfratto): move this to the base image. The base image isn't properly
# specifying the platform to install libbpfcc-dev for so it's a no-op on arm64
# hosts.
RUN apt-get update && apt-get install -qy libbpfcc-dev:amd64

COPY . /src/agent
WORKDIR /src/agent

RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
GOOS=$TARGETOS GOARCH=$TARGETARCH GOARM=${TARGETVARIANT#v} \
RELEASE_BUILD=${RELEASE_BUILD} VERISON=${VERSION} \
make -f Makefile-v2.mk agent

FROM ubuntu:jammy

# Install dependencies needed at runtime. On x86_64 (arm64), libbpfcc is also
# needed for the eBPF integration.
RUN <<EOF
apt-get update
apt-get install -qy libsystemd-dev tzdata ca-certificates

if [ `uname -m` = "x86_64" ]; then
apt-get install -qy libbpfcc
fi

rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
EOF

COPY --from=build /src/agent/build/agent /bin/agent
COPY cmd/agent/agent-local-config.yaml /etc/agent/agent.yaml

ENTRYPOINT ["/bin/agent"]
CMD ["--config.file=/etc/agent/agent.yaml", "--metrics.wal-directory=/etc/agent/data"]
Loading

0 comments on commit 0b2804e

Please sign in to comment.