### Makefile for tidb-opeator

# Ensure GOPATH is set before running build process.
ifeq "$(GOPATH)" ""
    $(error Please set the environment variable GOPATH before running `make`)
endif

path_to_add := $(addsuffix /bin,$(subst :,/bin:,$(GOPATH)))
export PATH := $(path_to_add):$(PATH)

VERSION   := $(if $(VERSION),$(VERSION),latest)
GOENV     := GO15VENDOREXPERIMENT="1" GOOS=linux GOARCH=amd64
GO        := $(GOENV) CGO_ENABLED=0 go
RETOOL    := GO15VENDOREXPERIMENT="1" retool do
GOTEST    := $(RETOOL) ginkgo
LINTENV   := CGO_ENABLED=0 $(RETOOL)
FILES     := $$(find . -name '*.go' -type f | grep -vE 'vendor' | grep -vE 'glide')
E2E_FILES := $$(find . -name '*.go' -type f | grep -vE 'vendor' | grep -vE 'glide' | grep 'e2e')
GOFILTER  := grep -vE 'render.Delims|bindata_assetfs|testutil|election|zz_generated'
STDOUT_IS_ERROR := awk '{ print } END { if (NR > 0) { exit 1 } }'
GOCHECKER := $(GOFILTER) | $(STDOUT_IS_ERROR)

TEST_PACKAGES := $$(go list ./... | grep -vE 'vendor|hack|clientset|v1alpha|e2e' | sed 's|github.com/pingcap/tidb-operator/||')
LINT_PACKAGES := go list ./... | grep -vE 'vendor|hack|clientset|v1alpha|informers|listers|externalstorage|goroutinemap' | sed 's|github.com/pingcap/tidb-operator/||'

LDFLAGS += -X "github.com/pingcap/tidb-operator/version.BuildTS=$(shell date -u '+%Y-%m-%d %I:%M:%S')"
LDFLAGS += -X "github.com/pingcap/tidb-operator/version.GitSHA=$(shell git rev-parse HEAD)"

E2E_VERSION     := $(shell git rev-parse --short HEAD)-$(shell date -u '+%Y-%m-%d_%I-%M-%S')
E2E_VERSION     := $(if $(DOCKER_REGISTRY),$(E2E_VERSION),latest)
DOCKER_REGISTRY := $(if $(DOCKER_REGISTRY),$(DOCKER_REGISTRY),127.0.0.1:5000)
NAMESPACE := $(if $(KUBE_NAMESPACE),$(KUBE_NAMESPACE),tidb-demo)

default: build

all: dev install

dev: lint-fast test build

setup:
	$(GO) get github.com/twitchtv/retool
	CGO_ENABLED=0 retool sync

# Release tags are used where recent ones are available, otherwise the lastest master commit was used
# Note that what is written here is the equivalent of the dep .toml file
tool-install: export CGO_ENABLED = 1
tool-install:
	retool add github.com/tsenart/deadcode 210d2dc333e90c7e3eedf4f2242507a8e83ed4ab
	retool add github.com/golang/lint/golint 06c8688daad7faa9da5a0c2f163a3d14aac986ca
	retool add github.com/gordonklaus/ineffassign 7bae11eba15a3285c75e388f77eb6357a2d73ee2
	retool add github.com/alexkohler/nakedret v1.0
	retool add github.com/client9/misspell/cmd/misspell v0.3.4
	retool add gopkg.in/alecthomas/gometalinter.v2 v2.0.5
	retool add github.com/onsi/ginkgo/ginkgo v1.5.0
	retool add github.com/onsi/gomega v1.4.0
	retool add honnef.co/go/tools/cmd/megacheck master
	retool add github.com/dnephin/govet 4a96d43e39d340b63daa8bc5576985aa599885f6


check: lint-slow lint

lint: ERRORS_ONLY=1
lint: lint-fast

lint-slow:
	$(LINTENV) gometalinter.v2 --disable-all --enable megacheck --deadline 65s $$(echo $$($(LINT_PACKAGES) | grep -v test)) \
	  2>&1 | $(GOCHECKER)

lint-fast:
	ONLY_STATIC=1 ERRORS_ONLY=$(if $(ERRORS_ONLY),$(ERRORS_ONLY),1) $(LINTENV) ./scripts/validate-go.sh $$($(LINT_PACKAGES)) 2>&1 \
	    | grep -vE 'test.*shadows' \
	    | $(GOCHECKER)
	ONLY_LINT=1 ERRORS_ONLY=$(if $(ERRORS_ONLY),$(ERRORS_ONLY),1) $(LINTENV) ./scripts/validate-go.sh $$($(LINT_PACKAGES)) 2>&1 \
	    | grep -v generated \
	    | grep -v 'name will be used as fake\.' \
	    | grep -vE 'test.*should not use dot imports' \
	    | grep -vE 'warning: exported func.*returns unexported type'

test:
	CGO_ENABLED=1 $(GOTEST) --race --cover $(TEST_PACKAGES)

new-operator-test:
	CGO_ENABLED=0 go test ./new-operator/pkg/... -v -cover

controller-manager:
	$(GO) build -ldflags '$(LDFLAGS)' -o bin/tidb-controller-manager cmd/controller-manager/main.go
scheduler:
	$(GO) build -ldflags '$(LDFLAGS)' -o bin/tidb-scheduler cmd/scheduler/main.go

volume-manager:
	$(GO) build -ldflags '$(LDFLAGS)' -o bin/tidb-volume-manager cmd/volume-manager/main.go

build: controller-manager scheduler volume-manager

# This was a previous name that should be removed in favor of docker-push
docker: docker-push

docker-push: docker-image
	docker tag "pingcap/tidb-operator:local" "$(DOCKER_REGISTRY)/pingcap/tidb-operator:$(VERSION)"
	docker push "$(DOCKER_REGISTRY)/pingcap/tidb-operator:$(VERSION)"

docker-image: build
	mkdir -p docker/bin && cp bin/tidb-* docker/bin/
	cd docker && docker build --tag "pingcap/tidb-operator:local" .

# For local testing
# Load the locally built operator docker image into the DinD Kubernetes registry
# Then reinstall the operator chart
dind-reload: docker-image
	docker tag pingcap/tidb-operator:local $(DOCKER_REGISTRY)/pingcap/tidb-operator:latest
	docker push $(DOCKER_REGISTRY)/pingcap/tidb-operator:latest
	helm del --purge tidb-operator || echo "tidb-operator not deleted. Maybe it was not running".
	helm install charts/tidb-operator -n tidb-operator --namespace=pingcap --set operatorImage=$(DOCKER_REGISTRY)/pingcap/tidb-operator:latest
	@echo "\nwaiting for tidb operator to startup"
	@ while kubectl get pods --namespace pingcap -l app=tidb-operator --no-headers | grep -v Running ; do sleep 2 ; echo "\nwaiting for tidb operator to startup" ; done

test-e2e: docker-push e2e e2e-run-tests

e2e-run-tests:
	./scripts/test-e2e.sh test/e2e/manifests/tidb-operator-e2e.yaml


e2e: e2e-build e2e-docker

e2e-build:
	CGO_ENABLED=0 $(GOTEST) build -cover test/e2e

e2e-docker:
	mkdir -p test/e2e/docker/bin
	mv test/e2e/e2e.test test/e2e/docker/bin/
	rm -rf test/e2e/docker/tidb-operator
	cp -r charts/tidb-operator test/e2e/docker/
	cp -r charts/tidb-cluster test/e2e/docker/
	cp -r charts/drainer test/e2e/docker/
	cp -r charts/lightning test/e2e/docker/
	cp -r charts/importer test/e2e/docker/
	cp test/e2e/docker/data/values.yaml test/e2e/docker/tidb-cluster/values.yaml
	cd test/e2e/docker && docker build --tag "$(DOCKER_REGISTRY)/pingcap/tidb-operator-e2e:$(E2E_VERSION)" .
	docker push "$(DOCKER_REGISTRY)/pingcap/tidb-operator-e2e:$(E2E_VERSION)"


# Run a MySQL container from our laptop connected to the dind network
dind-mysql:
	@ endpoint=$$(kubectl describe svc demo-cluster-tidb -n $(NAMESPACE) | grep 'Endpoints:' | awk '{print $$2}' | sed 's/,.*//') ; \
	host=$$(echo $$endpoint | cut -d : -f 1) ; \
	port=$$(echo $$endpoint | cut -d : -f 2) ; \
	docker run --rm -it --net e2e-v1.7.kubeadm-dind-net jbergknoff/mysql-client mysql -h $$host -P $$port
	# Direct access from the host network, works on some Linux configurations
	# mysql -h $$(docker inspect e2e-v1.7-kube-node-1 --format '{{(index .NetworkSettings.Networks "e2e-v1.7.kubeadm-dind-net").IPAddress }}') -P $$nodeport -u root

clean:
	$(GO) clean -i ./...
	rm -rf bin/tidb-*

.PHONY: update clean test test-e2e e2e-run-tests
