blob: e82b876a0ef734e4ddd3c0133ca07d47fc1716b8 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Image URL to use all building/pushing image targets
VERSION ?= 2.0.0-rc4
RELEASE_SRC = apache-apisix-ingress-controller-${VERSION}-src
IMAGE_TAG ?= dev
IMG ?= apache/apisix-ingress-controller:$(IMAGE_TAG)
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.30.0
KIND_NAME ?= apisix-ingress-cluster
ADC_VERSION ?= 0.21.0
DIR := $(shell pwd)
GINKGO_VERSION ?= 2.20.0
TEST_TIMEOUT ?= 80m
TEST_DIR ?= ./test/e2e/apisix/
E2E_NODES ?= 4
# CRD Reference Documentation
CRD_REF_DOCS_VERSION ?= v0.1.0
CRD_REF_DOCS ?= $(LOCALBIN)/crd-ref-docs
CRD_DOCS_CONFIG ?= docs/assets/crd/config.yaml
CRD_DOCS_OUTPUT ?= docs/en/latest/reference/api-reference.md
CRD_DOCS_TEMPLATE ?= docs/assets/template
# go
VERSYM="github.com/apache/apisix-ingress-controller/internal/version._buildVersion"
GITSHASYM="github.com/apache/apisix-ingress-controller/internal/version._buildGitRevision"
BUILDOSSYM="github.com/apache/apisix-ingress-controller/internal/version._buildOS"
GO_LDFLAGS ?= "-X=$(VERSYM)=$(VERSION) -X=$(GITSHASYM)=$(GITSHA) -X=$(BUILDOSSYM)=$(OSNAME)/$(OSARCH)"
# gateway-api
GATEAY_API_VERSION ?= v1.3.0
## https://github.com/kubernetes-sigs/gateway-api/blob/v1.3.0/pkg/features/httproute.go
SUPPORTED_EXTENDED_FEATURES = "HTTPRouteDestinationPortMatching,HTTPRouteMethodMatching,HTTPRoutePortRedirect,HTTPRouteRequestMirror,HTTPRouteSchemeRedirect,GatewayAddressEmpty,HTTPRouteResponseHeaderModification,GatewayPort8080"
CONFORMANCE_TEST_REPORT_OUTPUT ?= $(DIR)/apisix-ingress-controller-conformance-report.yaml
## https://github.com/kubernetes-sigs/gateway-api/blob/v1.3.0/conformance/utils/suite/profiles.go
CONFORMANCE_PROFILES ?= GATEWAY-HTTP,GATEWAY-GRPC
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
GOOS ?= linux
GOARCH ?= amd64
ifeq ($(shell uname -s),Darwin)
GOOS = darwin
endif
ifeq ($(shell uname -m),arm64)
GOARCH = arm64
endif
ifeq ($(shell uname -m), aarch64)
GOARCH = arm64
endif
# CONTAINER_TOOL defines the container tool to be used for building images.
# Be aware that the target commands are only tested with Docker which is
# scaffolded by default. However, you might want to replace it to use other
# tools. (i.e. podman)
CONTAINER_TOOL ?= docker
# 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
.SHELLFLAGS = -ec
.PHONY: all
all: build
##@ General
# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk command is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php
.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\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: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=apisix-ingress-manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
.PHONY: fmt
fmt: ## Run go fmt against code.
go fmt ./...
.PHONY: vet
vet: ## Run go vet against code.
go vet ./...
.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e | grep -v /conformance) -coverprofile cover.out
.PHONY: kind-e2e-test
kind-e2e-test: kind-up build-image kind-load-images e2e-test
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
.PHONY: e2e-test
e2e-test: adc
go test $(TEST_DIR) -test.timeout=$(TEST_TIMEOUT) -v -ginkgo.v -ginkgo.focus="$(TEST_FOCUS)" -ginkgo.label-filter="$(TEST_LABEL)"
.PHONY: ginkgo-e2e-test
ginkgo-e2e-test: adc
@ginkgo -cover -coverprofile=coverage.txt -r --randomize-all --randomize-suites --trace --focus=$(E2E_FOCUS) --nodes=$(E2E_NODES) --label-filter="$(TEST_LABEL)" $(TEST_DIR)
.PHONY: install-ginkgo
install-ginkgo:
@go install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
.PHONY: conformance-test
conformance-test:
go test -v ./test/conformance -tags conformance,experimental -timeout 60m \
--supported-features=$(SUPPORTED_EXTENDED_FEATURES) \
--conformance-profiles=$(CONFORMANCE_PROFILES) \
--report-output=$(CONFORMANCE_TEST_REPORT_OUTPUT)
.PHONY: lint
lint: sort-import golangci-lint ## Run golangci-lint linter
$(GOLANGCI_LINT) run
.PHONY: lint-fix
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes
$(GOLANGCI_LINT) run --fix
.PHONY: kind-up
kind-up:
@kind get clusters 2>&1 | grep -v $(KIND_NAME) \
&& kind create cluster --name $(KIND_NAME) \
|| echo "kind cluster already exists"
kubectl wait --for=condition=Ready nodes --all
.PHONY: kind-down
kind-down:
@kind get clusters 2>&1 | grep $(KIND_NAME) \
&& kind delete cluster --name $(KIND_NAME) \
|| echo "kind cluster does not exist"
.PHONY: kind-load-images
kind-load-images: pull-infra-images kind-load-ingress-image kind-load-adc-image
@kind load docker-image kennethreitz/httpbin:latest --name $(KIND_NAME)
@kind load docker-image jmalloc/echo-server:latest --name $(KIND_NAME)
.PHONY: kind-load-ingress-image
kind-load-ingress-image:
@kind load docker-image $(IMG) --name $(KIND_NAME)
.PHONY: kind-load-adc-image
kind-load-adc-image:
@docker pull ghcr.io/api7/adc:$(ADC_VERSION)
@docker tag ghcr.io/api7/adc:$(ADC_VERSION) ghcr.io/api7/adc:dev
@kind load docker-image ghcr.io/api7/adc:dev --name $(KIND_NAME)
.PHONY: pull-infra-images
pull-infra-images:
@docker pull kennethreitz/httpbin:latest
@docker pull jmalloc/echo-server:latest
##@ Build
.PHONY: build
build: manifests generate fmt vet ## Build manager binary.
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 go build -o bin/apisix-ingress-controller_$(GOARCH) -ldflags $(GO_LDFLAGS) cmd/main.go
linux-build:
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o bin/apisix-ingress-controller -ldflags $(GO_LDFLAGS) cmd/main.go
.PHONY: build-image
build-image: docker-build
.PHONY: build-push-image
build-push-image: docker-build
@docker push ${IMG}
.PHONY: build-multi-arch
build-multi-arch:
@CGO_ENABLED=0 GOARCH=amd64 go build -o bin/apisix-ingress-controller_amd64 -ldflags $(GO_LDFLAGS) cmd/main.go
@CGO_ENABLED=0 GOARCH=arm64 go build -o bin/apisix-ingress-controller_arm64 -ldflags $(GO_LDFLAGS) cmd/main.go
.PHONY: build-multi-arch-image
build-multi-arch-image: build-multi-arch
# daemon.json: "features":{"containerd-snapshotter": true}
@docker buildx build --load --platform linux/amd64,linux/arm64 -t $(IMG) .
.PHONY: build-push-multi-arch-image
build-push-multi-arch-image: build-multi-arch
@docker buildx build --push --platform linux/amd64,linux/arm64 -t $(IMG) .
.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./cmd/main.go
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
.PHONY: docker-build
docker-build: set-e2e-goos build ## Build docker image with the manager.
$(CONTAINER_TOOL) build -t ${IMG} -f Dockerfile .
.PHONY: docker-push
docker-push: ## Push docker image with the manager.
$(CONTAINER_TOOL) push ${IMG}
# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/
# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
.PHONY: docker-buildx
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name apisix-ingress-builder
$(CONTAINER_TOOL) buildx use apisix-ingress-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm apisix-ingress-builder
rm Dockerfile.cross
.PHONY: build-installer
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
mkdir -p dist
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default > dist/install.yaml
##@ Deployment
ifndef ignore-not-found
ignore-not-found = false
endif
.PHONY: e2e-ldap
e2e-ldap:
ifeq ("$(E2E_FOCUS)", "")
chmod +x ./test/e2e/testdata/ldap/cmd.sh && ./test/e2e/testdata/ldap/cmd.sh start
endif
ifneq ("$(E2E_FOCUS)", "")
echo $(E2E_FOCUS) | grep -E 'suite-plugins-authentication|consumer|ldap' || exit 0 \
&& chmod +x ./test/e2e/testdata/ldap/cmd.sh \
&& ./test/e2e/testdata/ldap/cmd.sh start
endif
.PHONY: install-gateway-api
install-gateway-api: ## Install Gateway API CRDs into the K8s cluster specified in ~/.kube/config.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/$(GATEAY_API_VERSION)/experimental-install.yaml
.PHONY: uninstall-gateway-api
uninstall-gateway-api: ## Uninstall Gateway API CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
kubectl delete -f https://github.com/kubernetes-sigs/gateway-api/releases/download/$(GATEAY_API_VERSION)/experimental-install.yaml
.PHONY: install
install: manifests kustomize install-gateway-api ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -
.PHONY: uninstall
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
.PHONY: undeploy
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
##@ Dependencies
## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)
## Tool Binaries
KUBECTL ?= kubectl
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
ADC_BIN ?= $(LOCALBIN)/adc
## Tool Versions
KUSTOMIZE_VERSION ?= v5.4.2
CONTROLLER_TOOLS_VERSION ?= v0.17.2
ENVTEST_VERSION ?= release-0.18
GOLANGCI_LINT_VERSION ?= v2.1.5
## export PATH so that the tools are found
export PATH := $(LOCALBIN):$(PATH)
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE): $(LOCALBIN)
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))
.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
$(CONTROLLER_GEN): $(LOCALBIN)
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))
.PHONY: envtest
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
$(ENVTEST): $(LOCALBIN)
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
.PHONY: golangci-lint
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s $(GOLANGCI_LINT_VERSION)
.PHONY: adc
adc: $(ADC_BIN) ## Download adc locally if necessary.
$(ADC_BIN):
ifeq ($(ADC_VERSION),dev)
@echo "ADC_VERSION=dev, skip download"
else
curl -sSfL https://github.com/api7/adc/releases/download/v${ADC_VERSION}/adc_${ADC_VERSION}_${GOOS}_${GOARCH}.tar.gz \
| tar -xz -C $(LOCALBIN)
endif
gofmt: ## Apply go fmt
@gofmt -w -r 'interface{} -> any' .
@gofmt -w -r 'FIt -> It' test
@gofmt -w -r 'FContext -> Context' test
@gofmt -w -r 'FDescribe -> Describe' test
@gofmt -w -r 'FDescribeTable -> DescribeTable' test
@go fmt ./...
.PHONY: gofmt
set-e2e-goos:
$(eval GOOS=linux)
@echo "e2e GOOS: $(GOOS)"
.PHONY: set-e2e-goos
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
# $3 - specific version of package
define go-install-tool
@[ -f "$(1)-$(3)" ] || { \
set -e; \
package=$(2)@$(3) ;\
echo "Downloading $${package}" ;\
rm -f $(1) || true ;\
GOBIN=$(LOCALBIN) go install $${package} ;\
mv $(1) $(1)-$(3) ;\
} ;\
ln -sf $(1)-$(3) $(1)
endef
helm-build-crds:
@echo "build gateway-api standard crds"
$(KUSTOMIZE) build github.com/kubernetes-sigs/gateway-api/config/crd\?ref=${GATEAY_API_VERSION} > charts/crds/gwapi-crds.yaml
@echo "build apisix ic crds"
$(KUSTOMIZE) build config/crd > charts/crds/apisixic-crds.yaml
sort-import:
@./scripts/goimports-reviser.sh >/dev/null 2>&1
.PHONY: sort-import
.PHONY: generate-crd-docs
generate-crd-docs: manifests ## Generate CRD reference documentation in a single file
@mkdir -p $(dir $(CRD_DOCS_OUTPUT))
@echo "Generating CRD reference documentation"
@$(CRD_REF_DOCS) \
--source-path=./api \
--config=$(CRD_DOCS_CONFIG) \
--renderer=markdown \
--templates-dir=$(CRD_DOCS_TEMPLATE) \
--output-path=$(CRD_DOCS_OUTPUT) \
--max-depth=100
@echo "CRD reference documentation generated at $(CRD_DOCS_OUTPUT)"
.PHONY: generate-crd-docs-grouped
generate-crd-docs-grouped: manifests ## Generate CRD reference documentation grouped by API group
@mkdir -p docs/crd/groups
@echo "Generating CRD reference documentation (grouped by API)"
@$(CRD_REF_DOCS) \
--source-path=./api \
--config=$(CRD_DOCS_CONFIG) \
--renderer=markdown \
--templates-dir=$(CRD_DOCS_TEMPLATE) \
--output-path=docs/crd/groups \
--output-mode=group
@echo "CRD reference documentation generated in docs/crd/groups directory"
### verify-license: Verify license headers.
.PHONY: verify-license
verify-license:
docker run -it --rm -v $(PWD):/github/workspace apache/skywalking-eyes header check -v info
### update-license: Update license headers.
.PHONY: update-license
update-license:
docker run -it --rm -v $(PWD):/github/workspace apache/skywalking-eyes header fix
### verify-mdlint: Verify markdown files lint rules.
.PHONY: verify-mdlint
verify-mdlint:
docker run -it --rm -v $(PWD):/work tmknom/markdownlint '**/*.md' --ignore node_modules --ignore CHANGELOG.md
### update-mdlint: Update markdown files lint rules.
.PHONY: update-mdlint
update-mdlint:
docker run -it --rm -v $(PWD):/work tmknom/markdownlint '**/*.md' -f --ignore node_modules --ignore vendor --ignore CHANGELOG.md
### verify-yamllint: Verify yaml files lint rules for `examples` directory.
.PHONY: verify-yamllint
verify-yamllint:
docker run -it --rm -v $(PWD):/yaml peterdavehello/yamllint yamllint examples
### update-yamlfmt: Update yaml files format for `examples` directory.
.PHONY: update-yamlfmt
update-yamlfmt:
go install github.com/google/yamlfmt/cmd/yamlfmt@latest && yamlfmt examples
### verify-all: Verify all verify- rules.
.PHONY: verify-all
verify-all: verify-license verify-mdlint verify-yamllint
### update-all: Update all update- rules.
.PHONY: update-all
update-all: update-license update-mdlint update-gofmt
### release-src: Release source
release-src:
tar -zcvf $(RELEASE_SRC).tgz \
--exclude .github \
--exclude .git \
--exclude .idea \
--exclude .gitignore \
--exclude .DS_Store \
--exclude docs \
--exclude examples \
--exclude scripts \
--exclude samples \
--exclude test \
--exclude release \
--exclude $(RELEASE_SRC).tgz \
.
gpg --batch --yes --armor --detach-sig $(RELEASE_SRC).tgz
shasum -a 512 $(RELEASE_SRC).tgz > $(RELEASE_SRC).tgz.sha512
mkdir -p release
mv $(RELEASE_SRC).tgz release/$(RELEASE_SRC).tgz
mv $(RELEASE_SRC).tgz.asc release/$(RELEASE_SRC).tgz.asc
mv $(RELEASE_SRC).tgz.sha512 release/$(RELEASE_SRC).tgz.sha512