|
| 1 | +GIT_COMMIT := $(shell git rev-parse HEAD) |
| 2 | +GIT_TREE_STATE := $(shell test -n "`git status --porcelain`" && echo "-dirty" || echo "") |
| 3 | + |
| 4 | +# Image URL to use all building/pushing image targets |
| 5 | +REGISTRY ?= ghcr.io/kubeflow/notebooks |
| 6 | +TAG ?= sha-$(GIT_COMMIT)$(GIT_TREE_STATE) |
| 7 | + |
| 8 | +CONTROLLER_NAME ?= workspaces-controller |
| 9 | +CONTROLLER_IMG ?= $(REGISTRY)/$(CONTROLLER_NAME):$(TAG) |
| 10 | + |
| 11 | +BACKEND_NAME ?= workspaces-backend |
| 12 | +BACKEND_IMG ?= $(REGISTRY)/$(BACKEND_NAME):$(TAG) |
| 13 | + |
| 14 | +FRONTEND_NAME ?= workspaces-frontend |
| 15 | +FRONTEND_IMG ?= $(REGISTRY)/$(FRONTEND_NAME):$(TAG) |
| 16 | + |
| 17 | +KIND_CLUSTER_NAME ?= local-e2e |
| 18 | + |
| 19 | +# Setting SHELL to bash allows bash commands to be executed by recipes. |
| 20 | +# Options are set to exit when a recipe line exits non-zero or a piped command fails. |
| 21 | +SHELL = /usr/bin/env bash -o pipefail |
| 22 | +.SHELLFLAGS = -ec |
| 23 | + |
| 24 | + |
| 25 | +# Export KIND_EXPERIMENTAL_PROVIDER to honor it if set in user's environment |
| 26 | +# (e.g., KIND_EXPERIMENTAL_PROVIDER=podman for podman support) |
| 27 | +export KIND_EXPERIMENTAL_PROVIDER |
| 28 | + |
| 29 | +##@ General |
| 30 | + |
| 31 | +# The help target prints out all targets with their descriptions organized |
| 32 | +# beneath their categories. The categories are represented by '##@' and the |
| 33 | +# target descriptions by '##'. The awk command is responsible for reading the |
| 34 | +# entire set of makefiles included in this invocation, looking for lines of the |
| 35 | +# file as xyz: ## something, and then pretty-format the target and help. Then, |
| 36 | +# if there's a line with ##@ something, that gets pretty-printed as a category. |
| 37 | +# More info on the usage of ANSI control characters for terminal formatting: |
| 38 | +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters |
| 39 | +# More info on the awk command: |
| 40 | +# http://linuxcommand.org/lc3_adv_awk.php |
| 41 | + |
| 42 | +.PHONY: help |
| 43 | +help: ## Display this help. |
| 44 | + @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) |
| 45 | + |
| 46 | +##@ Deployment |
| 47 | + |
| 48 | +.PHONY: build-controller build-backend build-frontend build-all e2e |
| 49 | + |
| 50 | +deploy-controller: kind check-kind-context ## Build and deploy the controller. |
| 51 | + cd ../workspaces/controller && $(MAKE) docker-build IMG=$(CONTROLLER_IMG) |
| 52 | + $(KIND) load docker-image $(CONTROLLER_IMG) --name $(KIND_CLUSTER_NAME) |
| 53 | + cd ../workspaces/controller && $(MAKE) deploy IMG=$(CONTROLLER_IMG) |
| 54 | + |
| 55 | +deploy-backend: kind check-kind-context ## Build and deploy the backend. |
| 56 | + cd ../workspaces/backend && $(MAKE) docker-build IMG=$(BACKEND_IMG) |
| 57 | + $(KIND) load docker-image $(BACKEND_IMG) --name $(KIND_CLUSTER_NAME) |
| 58 | + cd ../workspaces/backend && $(MAKE) deploy IMG=$(BACKEND_IMG) |
| 59 | + |
| 60 | +deploy-frontend: kind check-kind-context ## Build and deploy the frontend. |
| 61 | + cd ../workspaces/frontend && $(MAKE) docker-build IMG=$(FRONTEND_IMG) |
| 62 | + $(KIND) load docker-image $(FRONTEND_IMG) --name $(KIND_CLUSTER_NAME) |
| 63 | + cd ../workspaces/frontend && $(MAKE) deploy IMG=$(FRONTEND_IMG) |
| 64 | + |
| 65 | +deploy-all: deploy-controller deploy-backend deploy-frontend ## Deploy all components. |
| 66 | + |
| 67 | +local-e2e: deploy-all istioctl ## Run e2e tests. |
| 68 | + @echo "TODO: Run e2e tests..." |
| 69 | + |
| 70 | + |
| 71 | +##@ Dependencies |
| 72 | + |
| 73 | +## Location to install dependencies to |
| 74 | +LOCALBIN ?= $(shell pwd)/bin |
| 75 | +$(LOCALBIN): |
| 76 | + mkdir -p $(LOCALBIN) |
| 77 | + |
| 78 | +## Tool Binaries |
| 79 | +KIND ?= $(LOCALBIN)/kind |
| 80 | +KUBECTL ?= kubectl |
| 81 | +ISTIOCTL ?= $(LOCALBIN)/istioctl |
| 82 | + |
| 83 | +## Tool Versions |
| 84 | +KIND_VERSION ?= v0.30.0 |
| 85 | +ISTIOCTL_VERSION ?= 1.27.3 |
| 86 | + |
| 87 | +.PHONY: kind |
| 88 | +kind: $(KIND) ## Download kind locally if necessary. |
| 89 | +$(KIND): $(LOCALBIN) |
| 90 | + $(call go-install-tool,$(KIND),sigs.k8s.io/kind,$(KIND_VERSION)) |
| 91 | + |
| 92 | +.PHONY: check-kubectl |
| 93 | +check-kubectl: ## Verify that kubectl is available in PATH. |
| 94 | + @if ! command -v $(KUBECTL) >/dev/null 2>&1; then \ |
| 95 | + echo "✗ ERROR: kubectl is not installed or not found in PATH"; \ |
| 96 | + echo " Please install kubectl: https://kubernetes.io/docs/tasks/tools/#kubectl"; \ |
| 97 | + exit 1; \ |
| 98 | + fi |
| 99 | + @echo "✓ kubectl found: $$($(KUBECTL) version --client 2>/dev/null || echo 'version check failed')" |
| 100 | + |
| 101 | +.PHONY: istioctl |
| 102 | +istioctl: $(ISTIOCTL) ## Download istioctl locally if necessary. |
| 103 | +$(ISTIOCTL): $(LOCALBIN) |
| 104 | + $(call go-install-tool,$(ISTIOCTL),istio.io/istio/istioctl/cmd/istioctl,$(ISTIOCTL_VERSION)) |
| 105 | + |
| 106 | +.PHONY: dependency-hash |
| 107 | +dependency-hash: ## Calculate hash of dependency versions for caching. |
| 108 | + @echo -e "KIND_VERSION=$(KIND_VERSION)\nISTIOCTL_VERSION=$(ISTIOCTL_VERSION)" | sha256sum | cut -d' ' -f1 | head -c 16 |
| 109 | + |
| 110 | +.PHONY: setup-cluster |
| 111 | +setup-cluster: check-kubectl kind istioctl ## Set up a complete kind cluster with cert-manager and Istio. |
| 112 | + @export PATH="$(LOCALBIN):$$PATH" && \ |
| 113 | + bash scripts/setup-kind.sh && \ |
| 114 | + bash scripts/setup-cert-manager.sh && \ |
| 115 | + bash scripts/setup-istio.sh |
| 116 | + @echo "✓ Cluster setup complete" |
| 117 | + |
| 118 | +.PHONY: check-kind-context |
| 119 | +check-kind-context: check-kubectl ## Verify that the current kubectl context is a kind cluster. |
| 120 | + @current_context=$$($(KUBECTL) config current-context 2>/dev/null) || { \ |
| 121 | + echo "Error: Unable to get current kubectl context. Is kubectl configured?"; \ |
| 122 | + exit 1; \ |
| 123 | + }; \ |
| 124 | + server_url=$$($(KUBECTL) config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null) || { \ |
| 125 | + echo "Error: Unable to get cluster server URL for context '$$current_context'"; \ |
| 126 | + exit 1; \ |
| 127 | + }; \ |
| 128 | + context_check=0; \ |
| 129 | + server_check=0; \ |
| 130 | + if echo "$$current_context" | grep -qE '^kind-'; then \ |
| 131 | + context_check=1; \ |
| 132 | + fi; \ |
| 133 | + if echo "$$server_url" | grep -qE '(127\.0\.0\.1|localhost)'; then \ |
| 134 | + server_check=1; \ |
| 135 | + fi; \ |
| 136 | + if [ $$context_check -ne 1 ] || [ $$server_check -ne 1 ]; then \ |
| 137 | + echo "✗ ERROR: Current context '$$current_context' does not appear to be a kind cluster!"; \ |
| 138 | + if [ $$context_check -ne 1 ]; then \ |
| 139 | + echo " ✗ Context name does not match kind-* pattern (got: $$current_context)"; \ |
| 140 | + fi; \ |
| 141 | + if [ $$server_check -ne 1 ]; then \ |
| 142 | + echo " ✗ Server URL does not use localhost/127.0.0.1 (got: $$server_url)"; \ |
| 143 | + fi; \ |
| 144 | + exit 1; \ |
| 145 | + fi |
| 146 | + |
| 147 | +# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist |
| 148 | +# $1 - target path with name of binary |
| 149 | +# $2 - package url which can be installed |
| 150 | +# $3 - specific version of package |
| 151 | +define go-install-tool |
| 152 | +@[ -f "$(1)-$(3)" ] || { \ |
| 153 | +set -e; \ |
| 154 | +package=$(2)@$(3) ;\ |
| 155 | +echo "Downloading $${package}" ;\ |
| 156 | +rm -f $(1) || true ;\ |
| 157 | +GOBIN=$(LOCALBIN) go install $${package} ;\ |
| 158 | +mv $(1) $(1)-$(3) ;\ |
| 159 | +} ;\ |
| 160 | +ln -sf $(1)-$(3) $(1) |
| 161 | +endef |
0 commit comments