generated from ContainerCraft/Konductor
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Makefile
249 lines (213 loc) · 10.8 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# --- Global Variables ---
LOWERCASE_GITHUB_REPOSITORY := $(shell echo ${GITHUB_REPOSITORY} | tr '[:upper:]' '[:lower:]')
REPO_NAME := $(shell echo ${LOWERCASE_GITHUB_REPOSITORY} | awk -F '/' '{print $$2}')
REPO_ORG := $(shell echo ${LOWERCASE_GITHUB_REPOSITORY} | awk -F '/' '{print $$1}')
PROJECT ?= $(or $(REPO_NAME),kargo)
DEPLOYMENT ?= $(or $(ENVIRONMENT),ci)
# Check if PULUMI_BACKEND_URL starts with 'file://'
ifeq ($(findstring file://,$(PULUMI_BACKEND_URL)),file://)
ORGANIZATION = organization
$(info ORGANIZATION: ${ORGANIZATION})
else
ORGANIZATION = ${GITHUB_USER}
$(info ORGANIZATION is set to ${GITHUB_USER})
endif
# Set Pulumi stack identifier to <organization>/<project>/<deployment>
PULUMI_STACK_IDENTIFIER := ${ORGANIZATION}/${PROJECT}/${DEPLOYMENT}
# Escape special characters in sensitive tokens
ESCAPED_PAT := $(shell echo "${PULUMI_ACCESS_TOKEN}" | sed -e 's/[\/&]/\\&/g')
ESCAPED_GITHUB_TOKEN := $(shell echo "${GITHUB_TOKEN}" | sed -e 's/[\/&]/\\&/g')
# Define file paths for configurations
TALOS_CONFIG_FILE := ${PWD}/.talos/config
KUBE_CONFIG_FILE := ${PWD}/.kube/config
# Check if PULUMI_ACCESS_TOKEN is set
ifeq ($(ESCAPED_PAT),)
$(warning PULUMI_ACCESS_TOKEN is not set)
endif
# Check if GITHUB_TOKEN is set
ifeq ($(ESCAPED_GITHUB_TOKEN),)
$(warning GITHUB_TOKEN is not set)
endif
# --- Targets ---
.PHONY: help detect-arch pulumi-login pulumi-up up talos-gen-config talos-cluster kind-cluster clean clean-all act konductor test-kind test-talos stop force-terminating-ns
# --- Default Command ---
all: help
# --- Help ---
# Display available commands
help:
@echo "Available commands:"
@echo " help - Display this help message."
@echo " login - Authenticate with Pulumi."
@echo " esc ENV=foobar - Run Pulumi ESC environment. Default: ENV='kubernetes'."
@echo " up - Deploy Pulumi infrastructure."
@echo " pulumi-down - Destroy deployed Pulumi infrastructure."
@echo " talos-cluster - Deploy a Talos Kubernetes cluster."
@echo " talos-config - Generate and validate Talos configuration."
@echo " talos - Create and configure a Talos Kubernetes cluster."
@echo " kind - Create a local Kubernetes cluster using Kind."
@echo " clean - Clean up resources."
@echo " clean-all - Perform 'clean' and remove Docker volumes."
@echo " act - Test GitHub Actions locally."
@echo " konductor - Maintain .github/devcontainer submodule."
@echo " test - Run setup tests."
@echo " stop - Stop Github Codespaces."
# --- Detect Architecture ---
detect-arch:
@echo $(shell uname -m | awk '{ if ($$1 == "x86_64") print "amd64"; else if ($$1 == "aarch64" || $$1 == "arm64") print "arm64"; else print "unknown" }')
# --- Pulumi Login ---
pulumi-login:
@echo "Logging into Pulumi..."
@direnv allow || true
@PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} pulumi login \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@pulumi install || true
@set -ex; pulumi stack select --create ${PULUMI_STACK_IDENTIFIER} || true
@echo "Login successful."
# --- Pulumi Deployment ---
pulumi-up:
@echo "Deploying Pulumi infrastructure..."
@KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} \
pulumi up --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g'
@echo "Deployment complete."
pulumi-down:
@echo "Deploying Pulumi infrastructure..."
@KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} \
pulumi down --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || \
KUBECONFIG=${KUBE_CONFIG_FILE} PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} PULUMI_K8S_DELETE_UNREACHABLE=true \
pulumi down --yes --skip-preview --refresh --stack ${PULUMI_STACK_IDENTIFIER} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g' || true
@echo "Deployment complete."
login: pulumi-login
up: pulumi-login pulumi-up wait-all-pods
down: pulumi-login pulumi-down
# ----------------------------------------------------------------------------------------------
# --- Control Flow ---
# ----------------------------------------------------------------------------------------------
# --- Wait for All Pods Ready ---
wait-all-pods:
@echo "Waiting for all pods in the cluster to be ready..."
@bash -c 'until [ "$$(kubectl get pods --all-namespaces --no-headers | grep -v "Running\|Completed\|Succeeded" | wc -l)" -eq 0 ]; do echo "Waiting for pods to be ready..."; sleep 5; done'
@kubectl get pods --all-namespaces --show-labels --kubeconfig ${KUBE_CONFIG_FILE}
@echo "All pods in the cluster are ready."
# ----------------------------------------------------------------------------------------------
# --- Talos Kubernetes Cluster ---
# ----------------------------------------------------------------------------------------------
# --- Talos Configuration ---
talos-gen-config:
@echo "Generating Talos Config..."
@mkdir -p ${HOME}/.kube .kube .pulumi .talos
@touch ${HOME}/.kube/config ${KUBE_CONFIG_FILE} ${TALOS_CONFIG_FILE}
@chmod 600 ${HOME}/.kube/config ${KUBE_CONFIG_FILE} ${TALOS_CONFIG_FILE}
@sudo talosctl gen config kargo https://10.5.0.2:6443 \
--config-patch @.talos/patch/machine.yaml --output .talos/manifest
@sudo talosctl validate --mode container \
--config .talos/manifest/controlplane.yaml
@echo "Talos Config generated."
# --- Talos Cluster ---
talos-cluster: detect-arch talos-gen-config
@echo "Creating Talos Kubernetes Cluster..."
@sudo talosctl cluster create \
--arch=$$(make detect-arch) \
--workers 1 \
--controlplanes 1 \
--provisioner docker
@pulumi config set kubernetes talos || true
@echo "Talos Cluster provisioning..."
# --- Wait for Talos Cluster Ready ---
talos-ready:
@echo "Waiting for Talos Cluster to be ready..."
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l k8s-app=kube-scheduler --namespace=kube-system --timeout=180s; do echo "Waiting for kube-scheduler to be ready..."; sleep 5; done'
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l k8s-app=kube-controller-manager --namespace=kube-system --timeout=180s; do echo "Waiting for kube-controller-manager to be ready..."; sleep 5; done'
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l k8s-app=kube-apiserver --namespace=kube-system --timeout=180s; do echo "Waiting for kube-apiserver to be ready..."; sleep 5; done'
@echo "Talos Cluster is ready."
# --- Talos ---
talos: clean-all talos-cluster talos-ready wait-all-pods
@echo "Talos Cluster ready."
# ----------------------------------------------------------------------------------------------
# --- Kind Kubernetes Cluster ---
# ----------------------------------------------------------------------------------------------
# --- Kind Cluster ---
kind-cluster:
@echo "Creating Kind Cluster..."
@direnv allow
@mkdir -p ${HOME}/.kube .kube || true
@touch ${HOME}/.kube/config .kube/config || true
@chmod 600 ${HOME}/.kube/config .kube/config || true
@sudo docker volume create kargo-worker-n01
@sudo docker volume create kargo-worker-n02
@sudo docker volume create kargo-control-plane-n01
@sudo kind create cluster --wait 1m --retain --config=hack/kind.yaml
@sudo kind get clusters
@sudo kind get kubeconfig --name kargo | tee ${KUBE_CONFIG_FILE} 1>/dev/null
@sudo kind get kubeconfig --name kargo | tee ${HOME}/.kube/config 1>/dev/null
@sudo chown -R $(id -u):$(id -g) ${KUBE_CONFIG_FILE}
@pulumi config set kubernetes kind || true
@echo "Created Kind Cluster."
# --- Wait for Kind Cluster Ready ---
kind-ready:
@echo "Waiting for Kind Kubernetes API to be ready..."
@kubectl get all --all-namespaces --show-labels --kubeconfig ${KUBE_CONFIG_FILE} || sleep 5
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l component=kube-apiserver --namespace=kube-system --timeout=180s; do echo "Waiting for kube-apiserver to be ready..."; sleep 5; done'
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l component=kube-scheduler --namespace=kube-system --timeout=180s; do echo "Waiting for kube-scheduler to be ready..."; sleep 5; done'
@bash -c 'until kubectl --kubeconfig ${KUBE_CONFIG_FILE} wait --for=condition=Ready pod -l component=kube-controller-manager --namespace=kube-system --timeout=180s; do echo "Waiting for kube-controller-manager to be ready..."; sleep 5; done'
@echo "Kind Cluster is ready."
kind: login kind-cluster kind-ready
# ----------------------------------------------------------------------------------------------
# --- Maintenance ---
# ----------------------------------------------------------------------------------------------
# --- Cleanup ---
clean: login down
@echo "Cleaning up resources..."
@sudo kind delete cluster --name kargo \
|| echo "Kind cluster not found."
@sudo kind delete cluster --name kind \
|| echo "Kind cluster not found."
@sudo talosctl cluster destroy \
|| echo "Talos cluster not found."
@echo "Cleanup complete."
clean-all: clean
@echo "Performing extended cleanup..."
@sudo docker volume rm kargo-worker-n01 kargo-worker-n02 kargo-control-plane-n01 \
|| echo "Docker volumes not found."
@rm -rf Pulumi.*.yaml
@echo "Extended cleanup complete."
# --- GitHub Actions Testing ---
act:
@echo "Testing GitHub Workflows locally..."
@direnv allow
@act --container-options "--privileged" --rm \
--var GITHUB_TOKEN=${GITHUB_TOKEN} \
--var PULUMI_ACCESS_TOKEN=${PULUMI_ACCESS_TOKEN} \
| sed 's/${ESCAPED_PAT}/***PULUMI_ACCESS_TOKEN***/g'
@echo "GitHub Workflow Test Complete."
# --- Maintain Devcontainer ---
konductor:
@git submodule update --init .github/konductor
@git submodule update --remote --merge .github/konductor
@rsync -av .github/konductor/.devcontainer/* .devcontainer
@docker pull ghcr.io/containercraft/konductor:latest
@echo "Devcontainer updated."
# --- Testing ---
test-kind: kind pulumi-up
@echo "Kind test complete."
test-talos: talos pulumi-up
@echo "Talos test complete."
# --- Stop Codespaces ---
stop: clean
@echo "Stopping Codespaces..."
@gh codespace --codespace ${CODESPACE_NAME} stop
@echo "Codespaces stopped."
# --- Stop Codespaces ---
force-terminating-ns:
@kubectl proxy & \
PROXY_PID=$$! ;\
sleep 2 ;\
kubectl get namespaces --field-selector=status.phase=Terminating -o json | jq -r '.items[].metadata.name' | while read NAMESPACE ; do \
echo "Clearing finalizers for namespace $$NAMESPACE" ;\
kubectl get namespace $$NAMESPACE -o json | jq '.spec = {"finalizers":[]}' > temp-$$NAMESPACE.json ;\
curl -k -H "Content-Type: application/json" -X PUT --data-binary @temp-$$NAMESPACE.json 127.0.0.1:8001/api/v1/namespaces/$$NAMESPACE/finalize ;\
rm -f temp-$$NAMESPACE.json ;\
done ;\
kill $$PROXY_PID