diff --git a/Makefile b/Makefile index 5ad22c02..8e78ef42 100644 --- a/Makefile +++ b/Makefile @@ -12,26 +12,98 @@ # See the License for the specific language governing permissions and # limitations under the License. -PROJECTNAME := $(shell basename "$(PWD)") -GOFILES := $(wildcard controller/*.go) -GOBIN := $(GOBASE)/bin +.DEFAULT_GOAL := help +.SUFFIXES: # remove legacy builtin suffixes to allow easier make debugging +SHELL = /usr/bin/env bash +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -#CMDS=cosi-controller-manager -all: unit build -#.PHONY: reltools -reltools: release-tools/build.make -release-tools/build.make: - echo "TODO: update kubernetes/test-infra when controller and sidecar can build successfully" +## +## ==== ARGS ===== # -build: -test: -unit: -codegen: - @echo "Running update-codegen to generate the code..." - bash ./hack/update-codegen.sh +## Container build tool compatible with `docker` API +DOCKER ?= docker - @echo "Running update-crd to generate the crd..." - bash ./hack/update-crd.sh +## Platform for 'build' +PLATFORM ?= linux/$(GOARCH) -include release-tools/build.make +## Image tag for controller image build +CONTROLLER_TAG ?= cosi-controller:latest + +## Image tag for sidecar image build +SIDECAR_TAG ?= cosi-provisioner-sidecar:latest + + +##@ Development + +.PHONY: all .gen +.gen: generate codegen # can be done in parallel with 'make -j' +.NOTPARALLEL: all # codegen must be finished before fmt/vet +all: .gen fmt vet build ## Build all targets, plus their prerequisites (faster with 'make -j') + +.PHONY: generate +generate: controller/Dockerfile sidecar/Dockerfile ## Generate files + $(MAKE) -C client crds + $(MAKE) -C proto generate + +.PHONY: codegen +codegen: codegen.client codegen.proto ## Generate code + +.PHONY: fmt +fmt: fmt.client fmt.controller fmt.sidecar ## Format code + +.PHONY: vet +vet: vet.client vet.controller vet.sidecar ## Vet code + +.PHONY: test +test: .test.proto test.client test.controller test.sidecar ## Run tests including unit tests + + +##@ Build + +.PHONY: build +build: build.controller build.sidecar ## Build all container images for development + +.PHONY: build.controller build.sidecar +build.controller: controller/Dockerfile ## Build only the controller container image + $(DOCKER) build --file controller/Dockerfile --platform $(PLATFORM) --tag $(CONTROLLER_TAG) . +build.sidecar: sidecar/Dockerfile ## Build only the sidecar container image + $(DOCKER) build --file sidecar/Dockerfile --platform $(PLATFORM) --tag $(SIDECAR_TAG) . + +.PHONY: clean +## Clean build environment +clean: + $(MAKE) -C proto clean + +.PHONY: clobber +## Clean build environment and cached tools +clobber: + $(MAKE) -C proto clobber + + +## +## === INTERMEDIATES === # + +%/Dockerfile: hack/Dockerfile.in hack/gen-dockerfile.sh + hack/gen-dockerfile.sh $* > "$@" + +codegen.%: FORCE + $(MAKE) -C $* codegen + +fmt.%: FORCE + cd $* && go fmt ./... + +vet.%: FORCE + cd $* && go vet ./... + +test.%: fmt.% vet.% FORCE + cd $* && go test ./... + +.PHONY: .test.proto +.test.proto: # gRPC proto has a special unit test + $(MAKE) -C proto check + +.PHONY: FORCE # use this to force phony behavior for targets with pattern rules +FORCE: diff --git a/client/Makefile b/client/Makefile index 4791d068..87a3954b 100644 --- a/client/Makefile +++ b/client/Makefile @@ -1,5 +1,3 @@ -GO ?= go - # # Setting SHELL to bash allows bash commands to be executed by recipes. # Options are set to exit when a recipe line exits non-zero or a piped command fails. SHELL = /usr/bin/env bash -o pipefail @@ -15,34 +13,14 @@ help: ## Display this help. ##@ Development .PHONY: generate -generate: crds codegen fmt module vendor ## Run all code generation/modification tools. - -.PHONY: test -test: vet ## Run all tests +generate: crds codegen fmt ## Run all code generation/modification tools. ##@ Generators .PHONY: crds crds: ## Generate CustomResourceDefinitions. - $(GO) run -v ./vendor/sigs.k8s.io/controller-tools/cmd/controller-gen crd paths="./apis/objectstorage/..." + go run -v ./vendor/sigs.k8s.io/controller-tools/cmd/controller-gen crd paths="./apis/objectstorage/..." .PHONY: codegen: ## Generate deepcopy, client, informer, and lister implementations. ./hack/update-codegen.sh - -.PHONY: fmt -fmt: ## Run go fmt - $(GO) fmt ./... - -.PHONY: module ## Update go mod - $(GO) mod tidy - -.PHONY: vendor -vendor: ## Update vendor dir - $(GO) mod vendor - -##@ Tests - -.PHONY: vet -vet: ## Run go vet - $(GO) vet ./... diff --git a/controller/Dockerfile b/controller/Dockerfile index af2aaf1f..cd96dd26 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -1,43 +1,46 @@ -# NOTE: context is expected to be repo root, not controller/ dir +# DO NOT EDIT! This file is generated by 'hack/gen-dockerfile.sh' from 'Dockerfile.in' # # BUILDER # -FROM docker.io/library/golang:1.22.5 AS builder +FROM docker.io/library/golang:1.22 AS builder WORKDIR /buildroot # Cache deps before building and copying source, so that we don't need to re-download # as much and so that source changes don't invalidate our downloaded layer. COPY client/ client/ +COPY proto/ proto/ COPY internal/ internal/ + COPY controller/go.mod controller/go.mod COPY controller/go.sum controller/go.sum -WORKDIR /buildroot/controller - -RUN go mod download +RUN cd controller && go mod download -COPY controller/cmd/ cmd/ -COPY controller/pkg/ pkg/ +COPY controller/cmd/ controller/cmd/ +COPY controller/pkg/ controller/pkg/ -ENV CGO_ENABLED=0 +WORKDIR /buildroot/controller -RUN go build -o artifacts/controller-manager cmd/controller-manager/*.go +RUN CGO_ENABLED=0 go build -o /buildroot/artifacts/controller cmd/*.go # # FINAL IMAGE # -FROM gcr.io/distroless/static:latest +FROM gcr.io/distroless/static:nonroot LABEL maintainers="Kubernetes Authors" -LABEL description="COSI Controller" +LABEL description="COSI controller" -LABEL org.opencontainers.image.title="COSI Controller" -LABEL org.opencontainers.image.description="Container Object Storage Interface (COSI) Controller" +LABEL org.opencontainers.image.title="COSI controller" +LABEL org.opencontainers.image.description="Container Object Storage Interface (COSI) controller" LABEL org.opencontainers.image.source="https://github.com/kubernetes-sigs/container-object-storage-interface-api/controller" LABEL org.opencontainers.image.licenses="APACHE-2.0" -COPY --from=builder /buildroot/controller/artifacts/controller-manager . -ENTRYPOINT ["/controller-manager"] +WORKDIR / +COPY --from=builder /buildroot/artifacts/controller . +USER 65532:65532 + +ENTRYPOINT ["/controller"] diff --git a/controller/Makefile b/controller/Makefile deleted file mode 100644 index c5f666b6..00000000 --- a/controller/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -.DEFAULT_GOAL := help -SHELL = /usr/bin/env bash -THIS_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) - -# 'go env' vars aren't always available in make environments, so get defaults for needed ones -GOARCH ?= $(shell go env GOARCH) - -## -## ==== ARGS ===== # - -## Container build tool compatible with `docker` API -DOCKER ?= docker - -## Platform for 'build' -PLATFORM ?= linux/$(GOARCH) - -## Image tag for all builds -IMAGE_TAG ?= cosi-controller:latest - -## -## === TARGETS === # - -.PHONY: build -## Build local image for development, defaulting linux/ -build: - cd .. && $(DOCKER) build --file $(THIS_DIR)/Dockerfile --platform $(PLATFORM) --tag $(IMAGE_TAG) . - -.PHONY: test -## Test packages -test: - go vet ./... - go test ./... - -# print out lines beginning with double-comments, plus next line as basic help text -.PHONY: help -## Show this help text -help: - @sed -n -e "/^##/{N;s/^/\n/p;}" $(MAKEFILE_LIST) diff --git a/controller/cmd/controller-manager/controller-manager.go b/controller/cmd/controller-manager.go similarity index 100% rename from controller/cmd/controller-manager/controller-manager.go rename to controller/cmd/controller-manager.go diff --git a/hack/Dockerfile.in b/hack/Dockerfile.in new file mode 100644 index 00000000..7b8206f2 --- /dev/null +++ b/hack/Dockerfile.in @@ -0,0 +1,44 @@ +# +# BUILDER +# +FROM docker.io/library/golang:1.22 AS builder + +WORKDIR /buildroot + +# Cache deps before building and copying source, so that we don't need to re-download +# as much and so that source changes don't invalidate our downloaded layer. +COPY client/ client/ +COPY proto/ proto/ +COPY internal/ internal/ + +COPY {{COMPONENT}}/go.mod {{COMPONENT}}/go.mod +COPY {{COMPONENT}}/go.sum {{COMPONENT}}/go.sum + +RUN cd {{COMPONENT}} && go mod download + +COPY {{COMPONENT}}/cmd/ {{COMPONENT}}/cmd/ +COPY {{COMPONENT}}/pkg/ {{COMPONENT}}/pkg/ + +WORKDIR /buildroot/{{COMPONENT}} + +RUN CGO_ENABLED=0 go build -o /buildroot/artifacts/{{COMPONENT}} cmd/*.go + + +# +# FINAL IMAGE +# +FROM gcr.io/distroless/static:nonroot + +LABEL maintainers="Kubernetes Authors" +LABEL description="COSI {{COMPONENT}}" + +LABEL org.opencontainers.image.title="COSI {{COMPONENT}}" +LABEL org.opencontainers.image.description="Container Object Storage Interface (COSI) {{COMPONENT}}" +LABEL org.opencontainers.image.source="https://github.com/kubernetes-sigs/container-object-storage-interface-api/{{COMPONENT}}" +LABEL org.opencontainers.image.licenses="APACHE-2.0" + +WORKDIR / +COPY --from=builder /buildroot/artifacts/{{COMPONENT}} . +USER 65532:65532 + +ENTRYPOINT ["/{{COMPONENT}}"] diff --git a/hack/gen-dockerfile.sh b/hack/gen-dockerfile.sh new file mode 100755 index 00000000..d62000ba --- /dev/null +++ b/hack/gen-dockerfile.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +# set -o xtrace + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +COMPONENT="$1" + +echo "# DO NOT EDIT! This file is generated by '${BASH_SOURCE[0]}' from 'Dockerfile.in'" +echo "" # empty line +sed "s/{{COMPONENT}}/$COMPONENT/g" "$SCRIPT_DIR"/Dockerfile.in diff --git a/proto/Makefile b/proto/Makefile index b9673e6e..32b118b4 100644 --- a/proto/Makefile +++ b/proto/Makefile @@ -1,4 +1,6 @@ -all: build +all: check + +.SUFFIXES: # remove legacy builtin suffixes to allow easier make debugging ######################################################################## ## GOLANG ## @@ -39,7 +41,8 @@ endif PROTOC_ZIP := protoc-$(PROTOC_VER)-$(PROTOC_OS)-$(PROTOC_ARCH).zip PROTOC_URL := https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VER)/$(PROTOC_ZIP) PROTOC_TMP_DIR := .protoc -PROTOC := $(PROTOC_TMP_DIR)/bin/protoc +PROTOC_BIN_DIR := $(PROTOC_TMP_DIR)/bin +PROTOC := $(PROTOC_BIN_DIR)/protoc PROTOC_TMP_INC := $(PROTOC_TMP_DIR)/include $(PROTOC): @@ -50,17 +53,19 @@ $(PROTOC): chmod 0755 "$@" stat "$@" > /dev/null 2>&1 -$(GOBIN)/protoc-gen-go: go.mod - go install google.golang.org/protobuf/cmd/protoc-gen-go +$(PROTOC_BIN_DIR)/protoc-gen-go: go.mod + GOBIN="$(CURDIR)"/$(PROTOC_BIN_DIR) go install google.golang.org/protobuf/cmd/protoc-gen-go -$(GOBIN)/protoc-gen-go-grpc: - go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 +$(PROTOC_BIN_DIR)/protoc-gen-go-grpc: + GOBIN="$(CURDIR)"/$(PROTOC_BIN_DIR) go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 -$(GOBIN)/protoc-gen-go-json: - go install github.com/mitchellh/protoc-gen-go-json@v1.1.0 +$(PROTOC_BIN_DIR)/protoc-gen-go-json: + GOBIN="$(CURDIR)"/$(PROTOC_BIN_DIR) go install github.com/mitchellh/protoc-gen-go-json@v1.1.0 -PROTOC_ALL := $(GOBIN)/protoc-gen-go $(GOBIN)/protoc-gen-go-grpc $(GOBIN)/protoc-gen-go-json $(PROTOC) +PROTOC_ALL := $(PROTOC_BIN_DIR)/protoc-gen-go $(PROTOC_BIN_DIR)/protoc-gen-go-grpc $(PROTOC_BIN_DIR)/protoc-gen-go-json $(PROTOC) +# Update PATH to discover the protoc binaries +export PATH := $(PROTOC_BIN_DIR):$(PATH) ######################################################################## ## PROTOC-GEN-GO-FAKE ## @@ -68,14 +73,10 @@ PROTOC_ALL := $(GOBIN)/protoc-gen-go $(GOBIN)/protoc-gen-go-grpc $(GOBIN)/protoc # This is the recipe for getting and installing the grpc go PROTOC_GEN_GO_FAKE_SRC := ./hack/fake-gen -PROTOC_GEN_GO_FAKE := $(PROTOC_TMP_DIR)/bin/protoc-gen-gofake -$(PROTOC_GEN_GO_FAKE): +PROTOC_GEN_GO_FAKE := $(PROTOC_BIN_DIR)/protoc-gen-gofake +$(PROTOC_GEN_GO_FAKE): $(PROTOC_GEN_GO_FAKE_SRC) go build -o $(PROTOC_GEN_GO_FAKE) $(PROTOC_GEN_GO_FAKE_SRC) -# Update PATH to discover the protoc-gen-gofake binary -export PATH := $(PROTOC_TMP_DIR)/bin:$(PATH) - - ######################################################################## ## BUILD ## ######################################################################## @@ -104,7 +105,7 @@ $(COSI_PROTO): $(COSI_SPEC) echo "// Code generated by make; DO NOT EDIT." > "$(COSI_PROTO)" cat $(COSI_SPEC) | sed -n -e '/```protobuf$$/,/^```$$/ p' | sed '/^```/d' >> "$(COSI_PROTO)" -$(COSI_GO) $(COSI_GO_GRPC) $(COSI_GO_JSON) $(COSI_GO_FAKE): $(COSI_PROTO) $(PROTOC_ALL) $(PROTOC_GEN_GO_FAKE) +$(COSI_GO) $(COSI_GO_GRPC) $(COSI_GO_JSON) $(COSI_GO_FAKE) &: $(COSI_PROTO) $(PROTOC_ALL) $(PROTOC_GEN_GO_FAKE) mkdir -p "$(BUILD_TMP_DIR)" mkdir -p "$(BUILD_TMP_DIR)/fake" $(PROTOC) -I. -I$(PROTOC_TMP_INC) \ @@ -113,17 +114,29 @@ $(COSI_GO) $(COSI_GO_GRPC) $(COSI_GO_JSON) $(COSI_GO_FAKE): $(COSI_PROTO) $(PROT --go-json_out=$(GO_JSON_OPTS):$(BUILD_TMP_DIR) \ --gofake_out=$(GO_FAKE_OPTS):$(BUILD_TMP_DIR)/fake \ "$(\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Development + +.PHONY: generate generate: $(COSI_PROTO) ## Generate cosi.proto -build: generate $(BUILD_TMP_COSI_A) ## Generate protobuf files, and ensure they build +.PHONY: codegen +codegen: $(COSI_GO) $(COSI_GO_GRPC) $(COSI_GO_JSON) $(COSI_GO_FAKE) ## Generate protobuf files + +.PHONY: check +check: $(BUILD_TMP_COSI_A) ## Generate protobuf files, and ensure they build .PHONY: clean clean: ## Clean all builds and generated files diff --git a/sidecar/Dockerfile b/sidecar/Dockerfile index dac57552..3952564d 100644 --- a/sidecar/Dockerfile +++ b/sidecar/Dockerfile @@ -1,44 +1,46 @@ -# NOTE: context is expected to be repo root, not sidecar/ dir +# DO NOT EDIT! This file is generated by 'hack/gen-dockerfile.sh' from 'Dockerfile.in' # # BUILDER # -FROM docker.io/library/golang:1.22.5 AS builder +FROM docker.io/library/golang:1.22 AS builder WORKDIR /buildroot # Cache deps before building and copying source, so that we don't need to re-download # as much and so that source changes don't invalidate our downloaded layer. COPY client/ client/ -COPY internal/ internal/ COPY proto/ proto/ +COPY internal/ internal/ + COPY sidecar/go.mod sidecar/go.mod COPY sidecar/go.sum sidecar/go.sum -WORKDIR /buildroot/sidecar +RUN cd sidecar && go mod download -RUN go mod download +COPY sidecar/cmd/ sidecar/cmd/ +COPY sidecar/pkg/ sidecar/pkg/ -COPY sidecar/cmd/ cmd/ -COPY sidecar/pkg/ pkg/ - -ENV CGO_ENABLED=0 +WORKDIR /buildroot/sidecar -RUN go build -o artifacts/objectstorage-sidecar cmd/objectstorage-sidecar/*.go +RUN CGO_ENABLED=0 go build -o /buildroot/artifacts/sidecar cmd/*.go # # FINAL IMAGE # -FROM gcr.io/distroless/static:latest +FROM gcr.io/distroless/static:nonroot LABEL maintainers="Kubernetes Authors" -LABEL description="COSI Storage Sidecar" +LABEL description="COSI sidecar" -LABEL org.opencontainers.image.title="COSI Storage Sidecar" -LABEL org.opencontainers.image.description="Container Object Storage Interface (COSI) Storage Provisioner Sidecar" -LABEL org.opencontainers.image.source="https://github.com/kubernetes-sigs/container-object-storage-interface-provisioner-api/sidecar" +LABEL org.opencontainers.image.title="COSI sidecar" +LABEL org.opencontainers.image.description="Container Object Storage Interface (COSI) sidecar" +LABEL org.opencontainers.image.source="https://github.com/kubernetes-sigs/container-object-storage-interface-api/sidecar" LABEL org.opencontainers.image.licenses="APACHE-2.0" -COPY --from=builder /buildroot/sidecar/artifacts/objectstorage-sidecar . -ENTRYPOINT ["/objectstorage-sidecar"] +WORKDIR / +COPY --from=builder /buildroot/artifacts/sidecar . +USER 65532:65532 + +ENTRYPOINT ["/sidecar"] diff --git a/sidecar/Makefile b/sidecar/Makefile deleted file mode 100644 index 52540807..00000000 --- a/sidecar/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -.DEFAULT_GOAL := help -SHELL = /usr/bin/env bash -THIS_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) - -# 'go env' vars aren't always available in make environments, so get defaults for needed ones -GOARCH ?= $(shell go env GOARCH) - -## -## ==== ARGS ===== # - -## Container build tool compatible with `docker` API -DOCKER ?= docker - -## Platform for 'build' -PLATFORM ?= linux/$(GOARCH) - -## Image tag for all builds -IMAGE_TAG ?= cosi-provisioner-sidecar:latest - -## -## === TARGETS === # - -.PHONY: build -## Build local image for development, defaulting linux/ -build: - cd .. && $(DOCKER) build --file $(THIS_DIR)/Dockerfile --platform $(PLATFORM) --tag $(IMAGE_TAG) . - -.PHONY: test -## Test packages -test: - go vet ./... - go test ./... - -# print out lines beginning with double-comments, plus next line as basic help text -.PHONY: help -## Show this help text -help: - @sed -n -e "/^##/{N;s/^/\n/p;}" $(MAKEFILE_LIST) diff --git a/sidecar/cmd/objectstorage-sidecar/cmd.go b/sidecar/cmd/cmd.go similarity index 100% rename from sidecar/cmd/objectstorage-sidecar/cmd.go rename to sidecar/cmd/cmd.go diff --git a/sidecar/cmd/objectstorage-sidecar/main.go b/sidecar/cmd/main.go similarity index 100% rename from sidecar/cmd/objectstorage-sidecar/main.go rename to sidecar/cmd/main.go