diff --git a/sidecar/otelcol/.gitignore b/sidecar/otelcol/.gitignore index 904b44e3..6b3d1d89 100644 --- a/sidecar/otelcol/.gitignore +++ b/sidecar/otelcol/.gitignore @@ -1,3 +1 @@ -bin/ -cmd/ -dist/ +builder-config.yaml diff --git a/sidecar/otelcol/.goreleaser.yaml b/sidecar/otelcol/.goreleaser.yaml deleted file mode 100644 index 35aa7eb1..00000000 --- a/sidecar/otelcol/.goreleaser.yaml +++ /dev/null @@ -1,92 +0,0 @@ -# This is an example .goreleaser.yml file with some sensible defaults. -# Make sure to check the documentation at https://goreleaser.com - -# The lines below are called `modelines`. See `:help modeline` -# Feel free to remove those if you don't want/need to use them. -# yaml-language-server: $schema=https://goreleaser.com/static/schema.json -# vim: set ts=2 sw=2 tw=0 fo=cnqoj - -version: 1 - -project_name: otelcol-sidecar - -env: - - GHCR_IMAGE={{ if index .Env "GHCR_IMAGE" }}{{ .Env.GHCR_IMAGE }}{{ else }}ghcr.io/sumologic/tailing-sidecar-otel{{ end }} - - ECR_IMAGE={{ if index .Env "ECR_IMAGE" }}{{ .Env.ECR_IMAGE }}{{ else }}public.ecr.aws/sumologic/tailing-sidecar-otel{{ end }} - - DOCKERHUB_IMAGE={{ if index .Env "DOCKERHUB_IMAGE" }}{{ .Env.DOCKERHUB_IMAGE }}{{ else }}sumologic/tailing-sidecar-otel{{ end }} - -before: - hooks: - - make generate-sources VERSION={{ .Version }} - -builds: - - dir: ./cmd - env: - - CGO_ENABLED=0 - goos: - - linux - goarch: - - amd64 - - arm64 - -# disable archiving -archives: - - format: binary - -dockers: - - image_templates: - - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-amd64" - - "{{ .Env.ECR_IMAGE }}:main-amd64" - - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-amd64" - - "{{ .Env.GHCR_IMAGE }}:main-amd64" - - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-amd64" - - "{{ .Env.DOCKERHUB_IMAGE }}:main-amd64" - use: buildx - goarch: amd64 - build_flag_templates: - - "--platform=linux/amd64" - extra_files: - - "config.yaml" - - image_templates: - - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-arm64" - - "{{ .Env.ECR_IMAGE }}:main-arm64" - - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-arm64" - - "{{ .Env.GHCR_IMAGE }}:main-arm64" - - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-arm64" - - "{{ .Env.DOCKERHUB_IMAGE }}:main-arm64" - use: buildx - goarch: arm64 - build_flag_templates: - - "--platform=linux/arm64" - extra_files: - - "config.yaml" - -docker_manifests: - - name_template: "{{ .Env.GHCR_IMAGE }}:{{ .Version }}" - image_templates: - - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-amd64" - - "{{ .Env.GHCR_IMAGE }}:{{ .Version }}-arm64" - - name_template: "{{ .Env.GHCR_IMAGE }}:main" - image_templates: - - "{{ .Env.GHCR_IMAGE }}:main-amd64" - - "{{ .Env.GHCR_IMAGE }}:main-arm64" - - name_template: "{{ .Env.ECR_IMAGE }}:{{ .Version }}" - image_templates: - - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-amd64" - - "{{ .Env.ECR_IMAGE }}:{{ .Version }}-arm64" - - name_template: "{{ .Env.ECR_IMAGE }}:main" - image_templates: - - "{{ .Env.ECR_IMAGE }}:main-amd64" - - "{{ .Env.ECR_IMAGE }}:main-arm64" - - name_template: "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}" - image_templates: - - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-amd64" - - "{{ .Env.DOCKERHUB_IMAGE }}:{{ .Version }}-arm64" - - name_template: "{{ .Env.DOCKERHUB_IMAGE }}:main" - image_templates: - - "{{ .Env.DOCKERHUB_IMAGE }}:main-amd64" - - "{{ .Env.DOCKERHUB_IMAGE }}:main-arm64" - -# we only want to build and publish docker images -release: - disable: true diff --git a/sidecar/otelcol/Dockerfile b/sidecar/otelcol/Dockerfile index e369bacc..ce954bfe 100644 --- a/sidecar/otelcol/Dockerfile +++ b/sidecar/otelcol/Dockerfile @@ -1,9 +1,80 @@ -# Prepare the necessary directories in an Alpine container where we have the necessary tooling -FROM alpine:3.21.3 AS directories -RUN mkdir /etc/otel/ -RUN mkdir /var/lib/otc -RUN touch /var/log/otelcol.log +ARG ALPINE_VERSION=3.22.1 +ARG GO_VERSION=1.24.5 +ARG OCB_VERSION=0.130.0 +ARG YQ_VERSION=4.46.1 +################################################################################# +# Set version information in builder config. +################################################################################# +FROM mikefarah/yq:${YQ_VERSION} AS config + +ARG BUILDPLATFORM +ARG TARGETPLATFORM +ARG VERSION +ARG OCB_VERSION + +RUN echo "I am running on ${BUILDPLATFORM}, building for ${TARGETPLATFORM}" + +# Temporarily switch to root to install required packages +USER root +# hadolint ignore=DL3018 +RUN apk add --no-cache bash +USER yq + +WORKDIR /workdir + +# Copy the builder template and generate builder config script to the stage +COPY builder-template.yaml builder-template.yaml +COPY generate-builder-config.sh /usr/local/bin/generate-builder-config.sh + +ENV DIST_VERSION=${VERSION} +ENV OT_VERSION=${OCB_VERSION} + +RUN generate-builder-config.sh + +################################################################################# +# Generate the collector source. +################################################################################# +FROM otel/opentelemetry-collector-builder:${OCB_VERSION} AS source + +# Temporarily switch to root to install required packages +USER root +# hadolint ignore=DL3018 +RUN apk add --no-cache git +USER ocb + +WORKDIR /build + +# Copy the builder config +COPY --from=config /workdir/builder-config.yaml /build/config.yaml + +RUN ocb --config=config.yaml --skip-compilation=true + +################################################################################# +# Build the collector. +################################################################################# +FROM golang:${GO_VERSION} AS builder + +WORKDIR /go + +# Copy the collector source code +COPY --from=source --chown=root:root /build/cmd . + +ENV CGO_ENABLED=0 + +RUN go build . + +################################################################################# +# Prepare the necessary directories in an Alpine container where we have the +# necessary tooling. +################################################################################# +FROM alpine:${ALPINE_VERSION} AS directories +RUN mkdir /etc/otel /var/lib/otc && touch /var/log/otelcol.log + +################################################################################# +# Build a minimal image from scratch, copying over the binary & directories from +# the previous stages. +################################################################################# FROM scratch ARG USER_UID=10001 @@ -13,9 +84,10 @@ COPY --from=directories --chown=${USER_UID}:${USER_UID} /etc/otel/ /etc/otel/ COPY --from=directories --chown=${USER_UID}:${USER_UID} /var/lib/otc /var/lib/otc COPY --from=directories --chown=${USER_UID}:${USER_UID} /var/log/otelcol.log /var/log/otelcol.log -# copy the default tailing-sidecar configuration file +COPY --from=builder /go/sidecar /otelcol + +# Copy the default tailing-sidecar configuration file COPY ./config.yaml /etc/otel/config.yaml -COPY otelcol-sidecar /otelcol ENTRYPOINT ["/otelcol"] CMD ["--config", "/etc/otel/config.yaml"] diff --git a/sidecar/otelcol/Makefile b/sidecar/otelcol/Makefile index 5786a265..0faa129c 100644 --- a/sidecar/otelcol/Makefile +++ b/sidecar/otelcol/Makefile @@ -1,87 +1,26 @@ -BINARY_NAME ?= otelcol-sidecar -OTELCOL_VERSION ?= 0.90.1 -BUILDER_REPO ?= github.com/open-telemetry/opentelemetry-collector -GO ?= go - -OS ?= $(shell uname -s | tr A-Z a-z) -ARCH ?= $(shell uname -m | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) -LOCALBIN ?= $(shell pwd)/bin - -GORELEASER ?= $(LOCALBIN)/goreleaser - -BUILDER_BIN_NAME ?= opentelemetry-collector-builder$(BUILDER_BIN_EXT) -BUILDER_BIN_PATH ?= $(LOCALBIN) -BUILDER=$(BUILDER_BIN_PATH)/$(BUILDER_BIN_NAME) - -INSTALLED_VERSION := $(shell $(BUILDER) version 2>&1) - -# go-get-tool will 'go get' any package $2 and install it to $1. -PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) -define go-get-tool -@[ -f $(1) ] || { \ -set -e ;\ -TMP_DIR=$$(mktemp -d) ;\ -cd $$TMP_DIR ;\ -go mod init tmp ;\ -echo "Downloading $(2)" ;\ -go get -d $(2)@$(3) ;\ -GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\ -rm -rf $$TMP_DIR ;\ -} -endef - -.PHONY: install-builder -install-builder: - @mkdir -p "$(BUILDER_BIN_PATH)" - curl -L -o "$(BUILDER_BIN_PATH)/$(BUILDER_BIN_NAME)" https://$(BUILDER_REPO)/releases/download/cmd/builder/v$(OTELCOL_VERSION)/ocb_$(OTELCOL_VERSION)_$(OS)_$(ARCH)$(BUILDER_BIN_EXT) - @chmod +x "$(BUILDER_BIN_PATH)/$(BUILDER_BIN_NAME)" - @$(MAKE) ensure-correct-builder-version - -.PHONY: install-goreleaser -install-goreleaser: - $(call go-get-tool,$(GORELEASER),github.com/goreleaser/goreleaser,latest) - - -.PHONY: ensure-correct-builder-version -ensure-correct-builder-version: -ifneq ($(lastword $(INSTALLED_VERSION)),$(OTELCOL_VERSION)) - @$(error Installed opentelemetry-collector-builder version \ - "$(INSTALLED_VERSION)" \ - does not match the requested "$(OTELCOL_VERSION)" \ - Please check if "$(BUILDER_BIN_PATH)" can be found in your PATH \ - and if not, then install it using 'make install-builder' from otelcolbuilder's directory\ - ) -endif +DOCKER ?= docker .PHONY: build -build: ensure-correct-builder-version install-goreleaser - @$(GORELEASER) release --snapshot --clean +build: TARGET ?= local +build: export TAG = $(shell git describe --tags --always) +build: export VERSION = $(TAG:v%=%) +build: + $(DOCKER) bake $(TARGET) .PHONY: release-dev release-dev: TAG = $(shell git describe --tags --always) -release-dev: ensure-correct-builder-version install-goreleaser - git tag "$(TAG)" - GORELEASER_CURRENT_TAG=$(TAG) \ - ECR_IMAGE=public.ecr.aws/sumologic/tailing-sidecar-otel-dev \ - GHCR_IMAGE=ghcr.io/sumologic/tailing-sidecar-otel \ - DOCKERHUB_IMAGE=sumologic/tailing-sidecar-otel-dev \ - make release - git tag -d "$(TAG)" +release-dev: + make build TARGET=dev .PHONY: release -release: ensure-correct-builder-version install-goreleaser - @$(GORELEASER) release --clean +release: + make build TARGET=prod .PHONY: build-test-image -build-test-image: GHCR_IMAGE = ghcr.io/sumologic/tailing-sidecar-otel -build-test-image: build - docker tag $(GHCR_IMAGE):main-$(ARCH) $(TAG) - -.PHONY: generate-sources -generate-sources: - $(BUILDER) \ - --go $(GO) \ - --version "$(VERSION)" \ - --config .otelcol-builder.yaml \ - --skip-compilation=true +build-test-image: + make build TARGET=test +.PHONY: print-tag +print-tag: TAG = $(shell git describe --tags --always) +print-tag: + @echo $(TAG) diff --git a/sidecar/otelcol/.otelcol-builder.yaml b/sidecar/otelcol/builder-template.yaml similarity index 51% rename from sidecar/otelcol/.otelcol-builder.yaml rename to sidecar/otelcol/builder-template.yaml index c6ab175a..a38af743 100644 --- a/sidecar/otelcol/.otelcol-builder.yaml +++ b/sidecar/otelcol/builder-template.yaml @@ -4,30 +4,23 @@ dist: # the module name for the new distribution, following Go mod conventions. Optional, but recommended. module: github.com/SumoLogic/tailing-sidecar/sidecar # the OpenTelemetry Collector version to use as base for the distribution. - otelcol_version: 0.90.1 + version: ${DIST_VERSION} # the path to write the output (sources and binary). output_path: ./cmd exporters: - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.90.1 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v${OT_VERSION} # Note: These components aren't strictly necessary, but they don't measurably increase the binary size processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.90.1 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.90.1 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/groupbyattrsprocessor v0.90.1 + - gomod: go.opentelemetry.io/collector/processor/batchprocessor v${OT_VERSION} + - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v${OT_VERSION} + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/groupbyattrsprocessor v${OT_VERSION} receivers: - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.90.1 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v${OT_VERSION} extensions: - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.90.1 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.90.1 - import: github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding v0.90.1 - import: github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/textencodingextension - -# Replacement paths are relative to the output_path (location of source files) -replaces: - - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter => github.com/SumoLogic/opentelemetry-collector-contrib/exporter/fileexporter 687035f9f64c57e96d74d523b398f526e698f9e4 - - github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/textencodingextension => github.com/SumoLogic/opentelemetry-collector-contrib/extension/encoding/textencodingextension 687035f9f64c57e96d74d523b398f526e698f9e4 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v${OT_VERSION} + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v${OT_VERSION} + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/textencodingextension v${OT_VERSION} diff --git a/sidecar/otelcol/docker-bake.hcl b/sidecar/otelcol/docker-bake.hcl new file mode 100644 index 00000000..1c02fddb --- /dev/null +++ b/sidecar/otelcol/docker-bake.hcl @@ -0,0 +1,116 @@ +################################################################################# +# Variables +################################################################################# + +variable "TAGS" { + type = set(string) + default = [ + "local/tailing-sidecar-otel:main", + "local/tailing-sidecar-otel:${VERSION}", + ] + + validation { + condition = TAGS != "" + error_message = "The variable 'TAGS' must not be empty." + } +} + +# NOTE: Must be passed the output of the command: git describe --tags --always +# Example value: v0.17.2 +variable "VERSION" { + type = string + + validation { + condition = VERSION != "" + error_message = "The variable 'VERSION' must not be empty." + } +} + +################################################################################# +# Groups +################################################################################# + +group "default" { + targets = [ + "local" + ] +} + +################################################################################# +# Base targets +################################################################################# + +target "_common" { + context = "./" + attest = [ + { + type = "provenance", + disabled = true, + }, + { + type = "sbom", + disabled = true, + }, + ] + args = { + VERSION = "${VERSION}" + } + dockerfile = "./Dockerfile" +} + +target "_common-local" { + inherits = ["_common"] + output = [{ type = "docker" }] +} + +target "_common-multiplatform" { + inherits = ["_common"] + platforms = [ + "linux/amd64", + "linux/arm64" + ] +} + +################################################################################# +# Composite targets +################################################################################# + +target "local" { + inherits = ["_common-local"] + tags = [ + "local/tailing-sidecar-otel:main", + "local/tailing-sidecar-otel:${VERSION}" + ] +} + +target "test" { + inherits = ["_common-multiplatform"] + tags = [ + "ghcr.io/sumologic/tailing-sidecar-otel:main", + "ghcr.io/sumologic/tailing-sidecar-otel:${VERSION}" + ] +} + +target "dev" { + inherits = ["_common-multiplatform"] + tags = [ + "public.ecr.aws/sumologic/tailing-sidecar-otel-dev:main", + "public.ecr.aws/sumologic/tailing-sidecar-otel-dev:${VERSION}", + "ghcr.io/sumologic/tailing-sidecar-otel:main", + "ghcr.io/sumologic/tailing-sidecar-otel:${VERSION}", + "sumologic/tailing-sidecar-otel-dev:main", + "sumologic/tailing-sidecar-otel-dev:${VERSION}" + ] +} + +target "prod" { + inherits = ["_common-multiplatform"] + tags = [ + "public.ecr.aws/sumologic/tailing-sidecar-otel-dev:main", + "public.ecr.aws/sumologic/tailing-sidecar-otel-dev:${VERSION}", + "ghcr.io/sumologic/tailing-sidecar-otel:main", + "ghcr.io/sumologic/tailing-sidecar-otel:${VERSION}", + "sumologic/tailing-sidecar-otel-dev:main", + "sumologic/tailing-sidecar-otel-dev:${VERSION}" + ] +} diff --git a/sidecar/otelcol/generate-builder-config.sh b/sidecar/otelcol/generate-builder-config.sh new file mode 100755 index 00000000..e7499a42 --- /dev/null +++ b/sidecar/otelcol/generate-builder-config.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash + +################################################################################# +# This script reads a builder config template, replaces the dist version and +# otel versions, and then outputs a builder config. +################################################################################# + +set -euo pipefail + +################################################################################# +# Command options +################################################################################# + +OPT_SHORT_HELP="h" +OPT_LONG_HELP="help" +readonly OPT_SHORT_HELP OPT_LONG_HELP + +OPT_SHORT_INPUT="i" +OPT_LONG_INPUT="input" +readonly OPT_SHORT_INPUT OPT_LONG_INPUT + +OPT_SHORT_OUTPUT="o" +OPT_LONG_OUTPUT="output" +readonly OPT_SHORT_OUTPUT OPT_LONG_OUTPUT + +################################################################################# +# Default values +################################################################################# + +DEFAULT_INPUT_PATH="builder-template.yaml" +DEFAULT_OUTPUT_PATH="builder-config.yaml" +DEFAULT_DIST_VERSION="" +if command -v git; then + DEFAULT_DIST_VERSION="$(git describe --tags --always)" +fi + +INPUT_PATH="${INPUT_PATH:-$DEFAULT_INPUT_PATH}" +OUTPUT_PATH="${OUTPUT_PATH:-$DEFAULT_OUTPUT_PATH}" +DIST_VERSION="${DIST_VERSION:-$DEFAULT_DIST_VERSION}" +OT_VERSION="${OT_VERSION:-}" + +################################################################################# +# Functions +################################################################################# + +function usage() { + cat <<-EOF +Usage: + generate-builder-config.sh [OPTIONS] + +The following OPTIONS are accepted: +-${OPT_SHORT_HELP}, --${OPT_LONG_HELP} Print this usage information message +-${OPT_SHORT_INPUT}, --${OPT_LONG_INPUT} Path to the config template (default: ${DEFAULT_INPUT_PATH}) +-${OPT_SHORT_OUTPUT}, --${OPT_LONG_OUTPUT} Path to output the generated config to (default: ${DEFAULT_OUTPUT_PATH}) + +The following ENVIRONMENT VARIABLES are accepted: +DIST_VERSION The version to embed into the collector binary (default: ${DEFAULT_DIST_VERSION}) +OT_VERSION The version of opentelemetry-collector-contrib to use (required) +EOF +} + +function exit_with_usage() { + usage >&2 + exit 1 +} + +function exit_with_usage_and_error() { + local msg="$1" + readonly msg + + usage >&2 + printf "\nError: %s\n" "${msg}" >&2 + exit 1 +} + +function parse_option_with_argument() { + if [[ -n "$2" && "$2" != -* ]]; then + echo "$2" + else + exit_with_usage_and_error "$1 requires a non-empty argument" + fi +} + +function parse_options() { + while [[ $# -gt 0 ]]; do + case "$1" in + "-${OPT_SHORT_INPUT}" | "--${OPT_LONG_INPUT}") + INPUT_PATH="$(parse_option_with_argument "$@")" + shift 2 + ;; + "-${OPT_SHORT_OUTPUT}" | "--${OPT_LONG_OUTPUT}") + OUTPUT_PATH="$(parse_option_with_argument "$@")" + shift 2 + ;; + "-${OPT_SHORT_HELP}" | "--${OPT_LONG_HELP}") + exit_with_usage + ;; + -*) + exit_with_usage_and_error "unrecognized option: $1" + ;; + *) + # Positional argument + exit_with_usage_and_error "position arguments are unsupported: $1" + ;; + esac + done +} + +function missing_environment_variable() { + exit_with_usage_and_error "missing required environment variable: $1" +} + +parse_options "$@" + +# Verify that the input template exists +if [ ! -f "${INPUT_PATH}" ]; then + exit_with_usage_and_error "file not found: ${INPUT_PATH}" +fi + +# Verify that the required environment variables are set, and then export them +if [ "${DIST_VERSION}" == "" ]; then + missing_environment_variable "DIST_VERSION" +fi +export DIST_VERSION + +if [ "${OT_VERSION}" == "" ]; then + missing_environment_variable "OT_VERSION" +fi +export OT_VERSION + +# Replace environment variables in the template and output config file +yq -e '(.. | select(tag == "!!str")) |= envsubst(nu)' "${INPUT_PATH}" >"${OUTPUT_PATH}" + +cat "${OUTPUT_PATH}"