-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMakefile
More file actions
333 lines (303 loc) · 14.6 KB
/
Copy pathMakefile
File metadata and controls
333 lines (303 loc) · 14.6 KB
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# Makefile for Terraform Infrastructure as Code
# Run terraform commands with environment variables from .env file
#
# Usage:
# make plan ENV=cc # Plan for the cc environment (default)
# make apply ENV=env-prod # Apply for the env-prod environment
# export ENV=cc && make plan # Set ENV for a session
# Variables
SHELL := /bin/bash
ENV ?= cc
ENV_DIR := config/environments/$(ENV)
ENV_FILE := $(ENV_DIR)/.env
ARTIFACTS_DIR := artifacts/$(ENV)/terraform
PLAN_FILE := $(ARTIFACTS_DIR)/tfplan
TF_DIR := src
BACKEND_CONFIG := path=../artifacts/$(ENV)/terraform/terraform.tfstate
# Load .env and map clean variable names to Terraform's TF_VAR_ convention
# DNS credentials are collected into a single map variable (dns_credentials)
# so any combination of DNS provider variables works without Terraform changes.
LOAD_ENV = set -a && source ../$(ENV_FILE) && set +a && \
export TF_VAR_env_name=$(ENV) \
TF_VAR_dns_credentials='{"digitalocean_token":"'$${DIGITALOCEAN_TOKEN:-}'",'`\
`'"cloudflare_api_token":"'$${CLOUDFLARE_API_TOKEN:-}'",'`\
`'"aws_access_key_id":"'$${AWS_ACCESS_KEY_ID:-}'",'`\
`'"aws_secret_access_key":"'$${AWS_SECRET_ACCESS_KEY:-}'",'`\
`'"aws_region":"'$${AWS_REGION:-}'",'`\
`'"powerdns_api_url":"'$${POWERDNS_API_URL:-}'",'`\
`'"powerdns_api_key":"'$${POWERDNS_API_KEY:-}'",'`\
`'"dns_provider_credentials":"'$${DIGITALOCEAN_TOKEN:-}$${CLOUDFLARE_API_TOKEN:-}$${AWS_ACCESS_KEY_ID:-}$${POWERDNS_API_KEY:-}'"}' \
TF_VAR_oci_repo_username=$${OCI_REPO_USERNAME:-} \
TF_VAR_oci_repo_password=$${OCI_REPO_PASSWORD:-} \
TF_VAR_oci_proxy_username=$${OCI_PROXY_USERNAME:-} \
TF_VAR_oci_proxy_password=$${OCI_PROXY_PASSWORD:-} \
TF_VAR_minio_root_user=$${MINIO_ROOT_USER:-} \
TF_VAR_minio_root_password=$${MINIO_ROOT_PASSWORD:-} \
TF_VAR_harbor_admin_password=$${HARBOR_ADMIN_PASSWORD:-} \
TF_VAR_grafana_admin_password=$${GRAFANA_ADMIN_PASSWORD:-} \
TF_VAR_mysql_root_password=$${MYSQL_ROOT_PASSWORD:-} \
TF_VAR_mysql_central_ledger_password=$${MYSQL_CENTRAL_LEDGER_PASSWORD:-} \
TF_VAR_mysql_account_lookup_password=$${MYSQL_ACCOUNT_LOOKUP_PASSWORD:-} \
TF_VAR_mysql_oracle_msisdn_password=$${MYSQL_ORACLE_MSISDN_PASSWORD:-} \
TF_VAR_mongodb_root_password=$${MONGODB_ROOT_PASSWORD:-} \
TF_VAR_mongodb_app_password=$${MONGODB_APP_PASSWORD:-} \
TF_VAR_keycloak_db_password=$${KEYCLOAK_DB_PASSWORD:-} \
TF_VAR_kratos_db_password=$${KRATOS_DB_PASSWORD:-} \
TF_VAR_keto_db_password=$${KETO_DB_PASSWORD:-} \
TF_VAR_mcm_db_password=$${MCM_DB_PASSWORD:-} \
TF_VAR_hydra_db_password=$${HYDRA_DB_PASSWORD:-} \
TF_VAR_hub_admin_password=$${HUB_ADMIN_PASSWORD:-} \
TF_VAR_hub_admin_email=$${HUB_ADMIN_EMAIL:-} \
TF_VAR_hubop_oidc_secret=$${HUBOP_OIDC_SECRET:-} \
TF_VAR_mcm_oidc_client_secret=$${MCM_OIDC_CLIENT_SECRET:-} \
TF_VAR_role_assign_svc_secret=$${ROLE_ASSIGN_SVC_SECRET:-} \
TF_VAR_dfsp_oidc_client_secret=$${DFSP_OIDC_CLIENT_SECRET:-} \
TF_VAR_hub_participant_name=$${HUB_PARTICIPANT_NAME:-} \
TF_VAR_onboarding_funds_in=$${ONBOARDING_FUNDS_IN:-} \
TF_VAR_onboarding_net_debit_cap=$${ONBOARDING_NET_DEBIT_CAP:-} \
TF_VAR_backup_s3_access_key=$${BACKUP_S3_ACCESS_KEY:-} \
TF_VAR_backup_s3_secret_key=$${BACKUP_S3_SECRET_KEY:-} \
TF_VAR_smtp_host=$${SMTP_HOST:-} \
TF_VAR_smtp_port=$${SMTP_PORT:-587} \
TF_VAR_smtp_user=$${SMTP_USER:-} \
TF_VAR_smtp_password=$${SMTP_PASSWORD:-} \
TF_VAR_alert_email_from=$${ALERT_EMAIL_FROM:-grafana@example.invalid} \
TF_VAR_alert_email_to=$${ALERT_EMAIL_TO:-ops@example.invalid} \
TF_VAR_telegram_bot_token=$${TELEGRAM_BOT_TOKEN:-unset} \
TF_VAR_telegram_chat_id=$${TELEGRAM_CHAT_ID:-0} && \
export AWS_ACCESS_KEY_ID=$${AWS_ACCESS_KEY_ID:-unused} \
AWS_SECRET_ACCESS_KEY=$${AWS_SECRET_ACCESS_KEY:-unused}
# Placeholder kubeconfig — the alekc/kubectl provider validates (stats + loads)
# its config_path at plan time, before the real kubeconfig exists on fresh
# deploys. The placeholder content is never dialed: terraform rewrites the file
# during apply before any kubernetes/helm/kubectl provider is configured
# (see src/providers.tf).
KUBECONFIG_FILE := artifacts/$(ENV)/kubernetes/kubeconfig
define ENSURE_KUBECONFIG
mkdir -p artifacts/$(ENV)/kubernetes; \
if [ ! -f "$(KUBECONFIG_FILE)" ]; then \
printf '%s\n' \
'# Placeholder generated by make — overwritten by terraform apply' \
'apiVersion: v1' \
'kind: Config' \
'clusters:' \
'- cluster:' \
' server: https://127.0.0.1:1' \
' name: pending' \
'contexts:' \
'- context: {cluster: pending, user: pending}' \
' name: pending' \
'current-context: pending' \
'users:' \
'- name: pending' \
' user: {token: pending}' \
> "$(KUBECONFIG_FILE)"; \
echo "Seeded placeholder kubeconfig at $(KUBECONFIG_FILE) (replaced during apply)"; \
fi
endef
# Default target
.DEFAULT_GOAL := help
# GitOps artifact settings (override via env or command line)
GITOPS_DIR := gitops
OCI_REPO := $(shell grep -A4 'repo:' $(ENV_DIR)/config.yaml | grep 'url:' | head -1 | sed 's/.*url: *"*oci:\/\///' | sed 's/"*$$//')
GITOPS_VERSION ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo "latest")
# Phony targets (not files)
.PHONY: help init plan apply plan-apply apply-direct apply-force destroy destroy-fast clean validate fmt show list render render-thanos render-cilium push-gitops tag-gitops list-artifacts release
# Help target - displays available commands
help:
@echo "Available targets:"
@echo ""
@echo " ENV=<name> Select environment (default: cc)"
@echo " Reads config from config/environments/<name>/"
@echo " Stores state in artifacts/<name>/"
@echo ""
@echo "Main Commands:"
@echo " make plan - Create Terraform execution plan (saved to artifacts)"
@echo " make apply - Apply Terraform changes using saved plan"
@echo " make plan-apply - Create plan and apply immediately (prevents stale plan)"
@echo ""
@echo "Alternative Apply Commands:"
@echo " make apply-direct - Apply changes directly without plan (auto-approve)"
@echo " make apply-force - Force recreate plan and apply (alias for plan-apply)"
@echo ""
@echo "Destroy Commands:"
@echo " make destroy - Destroy all Terraform-managed infrastructure"
@echo " make destroy-fast - Fast destroy without refresh (when resources already gone)"
@echo ""
@echo "Rendering Commands:"
@echo " make render - Render all pre-rendered manifests (Jsonnet → YAML)"
@echo " make render-thanos - Render Thanos manifests only"
@echo " make render-cilium - Render Cilium bootstrap manifest (CILIUM_VERSION=$(CILIUM_VERSION))"
@echo ""
@echo "GitOps Commands:"
@echo " make push-gitops - Push gitops/ as OCI artifact (version=git SHA)"
@echo " make push-gitops GITOPS_VERSION=v1.0.0 - Push with explicit version"
@echo " make tag-gitops TAG=latest - Tag an existing artifact"
@echo " make release TAG=v0.3.0 - Git tag + push + OCI artifact push"
@echo " make list-artifacts - List published artifact versions"
@echo ""
@echo "Utility Commands:"
@echo " make validate - Validate Terraform configuration"
@echo " make fmt - Format Terraform files"
@echo " make show - Display current Terraform state"
@echo " make list - List all Terraform resources"
@echo " make clean - Remove artifacts and temporary files"
@echo ""
@echo "Examples:"
@echo " make plan ENV=cc # Plan Control Center"
@echo " make plan-apply ENV=env-prod # Plan + apply App Environment"
@echo " export ENV=cc && make plan # Set ENV for a session"
# Initialize Terraform
init:
@echo "Initializing Terraform (ENV=$(ENV))..."
@mkdir -p $(ARTIFACTS_DIR)
@$(ENSURE_KUBECONFIG)
@cd $(TF_DIR) && $(LOAD_ENV) && terraform init -upgrade -reconfigure \
-backend-config="$(BACKEND_CONFIG)"
# Validate Terraform configuration
validate:
@echo "Validating Terraform configuration..."
@cd $(TF_DIR) && $(LOAD_ENV) && terraform validate
# Format Terraform files
fmt:
@echo "Formatting Terraform files..."
@cd $(TF_DIR) && terraform fmt -recursive
# Create Terraform plan and save to artifacts
plan: init
@echo "Creating Terraform plan (ENV=$(ENV))..."
@mkdir -p $(ARTIFACTS_DIR)
@cd $(TF_DIR) && $(LOAD_ENV) && terraform plan -out=../$(PLAN_FILE)
@echo "Plan saved to $(PLAN_FILE)"
# Apply Terraform changes using saved plan
apply:
@if [ ! -f "$(PLAN_FILE)" ]; then \
echo "Error: Plan file not found. Run 'make plan ENV=$(ENV)' first."; \
exit 1; \
fi
@echo "Applying Terraform changes from saved plan (ENV=$(ENV))..."
@echo "Note: If you get 'stale plan' error, run 'make plan-apply ENV=$(ENV)' instead."
@cd $(TF_DIR) && $(LOAD_ENV) && terraform apply ../$(PLAN_FILE)
# Plan and apply in one step (prevents stale plan issues)
plan-apply: init
@echo "Creating and applying Terraform plan (ENV=$(ENV))..."
@mkdir -p $(ARTIFACTS_DIR)
@cd $(TF_DIR) && $(LOAD_ENV) && terraform plan -out=../$(PLAN_FILE)
@echo "Plan created. Applying changes..."
@cd $(TF_DIR) && $(LOAD_ENV) && terraform apply ../$(PLAN_FILE)
# Apply without plan (direct apply with auto-approve)
apply-direct: init
@echo "WARNING: Applying changes directly without saved plan..."
@cd $(TF_DIR) && $(LOAD_ENV) && terraform apply -auto-approve
# Force apply - recreate plan and apply immediately
apply-force: plan-apply
@echo "Force apply completed."
# Destroy infrastructure
destroy:
@echo "WARNING: This will destroy all Terraform-managed infrastructure (ENV=$(ENV))!"
@echo "Press Ctrl+C to cancel, or wait 5 seconds to continue..."
@sleep 5
@$(ENSURE_KUBECONFIG)
@cd $(TF_DIR) && $(LOAD_ENV) && terraform destroy -auto-approve
# Fast destroy without refresh (use when resources are already gone)
destroy-fast:
@echo "WARNING: Fast destroy without refresh - use when resources are already deleted!"
@echo "Press Ctrl+C to cancel, or wait 3 seconds to continue..."
@sleep 3
@$(ENSURE_KUBECONFIG)
@cd $(TF_DIR) && $(LOAD_ENV) && terraform destroy -auto-approve -refresh=false
# Clean up artifacts
clean:
@echo "Cleaning up artifacts..."
@rm -rf artifacts/
@echo "Artifacts removed."
# Show current Terraform state
show:
@cd $(TF_DIR) && $(LOAD_ENV) && terraform show
# List Terraform resources
list:
@cd $(TF_DIR) && $(LOAD_ENV) && terraform state list
# --------------------------------------------------------------------------
# Manifest Rendering (Jsonnet → YAML)
# --------------------------------------------------------------------------
# Cilium chart version for the Talos bootstrap manifest
# (override: make render-cilium CILIUM_VERSION=1.19.4)
CILIUM_VERSION ?= 1.19.4
CILIUM_MANIFEST := config/manifests/cilium-$(CILIUM_VERSION).yaml
# Render all components that need pre-rendering
render: render-thanos render-cilium
# Render Thanos manifests from kube-thanos Jsonnet
render-thanos:
@echo "Rendering Thanos manifests..."
@cd rendering/thanos && jb install && \
jsonnet -J vendor -m ../../gitops/cc-observability/thanos/ thanos.jsonnet && \
cd ../../gitops/cc-observability/thanos && \
for f in thanos-*; do [ -f "$$f" ] && [ "$${f##*.}" != "yaml" ] && yq -p json -o yaml "$$f" > "$$f.yaml" && rm "$$f"; done || true
@echo "Thanos manifests rendered to gitops/cc-observability/thanos/"
# Render the Cilium bootstrap manifest fetched by Talos extraManifests.
# Minimal values only — Flux reconciles the full config (gitops/talos/cilium/)
# after the cluster is up. Hubble stays disabled so no TLS Secrets are
# rendered into the committed file; the guard below enforces that.
render-cilium:
@echo "Rendering Cilium $(CILIUM_VERSION) bootstrap manifest..."
@mkdir -p config/manifests
@cat rendering/cilium/namespace.yaml > $(CILIUM_MANIFEST)
@helm template cilium cilium \
--repo https://helm.cilium.io/ \
--version $(CILIUM_VERSION) \
--namespace cilium \
-f rendering/cilium/values.yaml \
>> $(CILIUM_MANIFEST)
@if grep -q "^kind: Secret" $(CILIUM_MANIFEST); then \
rm $(CILIUM_MANIFEST); \
echo "ERROR: rendered manifest contains Secrets (private keys) — not writing it. Check hubble is disabled in rendering/cilium/values.yaml"; \
exit 1; \
fi
@echo "Rendered to $(CILIUM_MANIFEST)"
@echo "Reference in config/patches/talos/patch-cilium-install.yaml:"
@echo " https://raw.githubusercontent.com/kiswend/ml-deployment-toolkit/main/$(CILIUM_MANIFEST)"
# --------------------------------------------------------------------------
# GitOps OCI Artifact Management
# --------------------------------------------------------------------------
# Push gitops/ directory as OCI artifact
push-gitops:
@echo "Pushing gitops artifact to oci://$(OCI_REPO):$(GITOPS_VERSION)..."
@set -a && source $(ENV_FILE) && set +a && \
flux push artifact oci://$(OCI_REPO):$(GITOPS_VERSION) \
--path=./$(GITOPS_DIR) \
--source="$(shell git config --get remote.origin.url)" \
--revision="$(shell git rev-parse --short HEAD)" \
--creds="$$OCI_REPO_USERNAME:$$OCI_REPO_PASSWORD"
@echo "Tagging as latest..."
@set -a && source $(ENV_FILE) && set +a && \
flux tag artifact oci://$(OCI_REPO):$(GITOPS_VERSION) --tag=latest \
--creds="$$OCI_REPO_USERNAME:$$OCI_REPO_PASSWORD"
@echo "Pushed oci://$(OCI_REPO):$(GITOPS_VERSION) (also tagged latest)"
# Tag an existing artifact with an additional tag
tag-gitops:
@if [ -z "$(TAG)" ]; then echo "Usage: make tag-gitops TAG=v1.0.0"; exit 1; fi
@set -a && source $(ENV_FILE) && set +a && \
flux tag artifact oci://$(OCI_REPO):$(GITOPS_VERSION) --tag=$(TAG) \
--creds="$$OCI_REPO_USERNAME:$$OCI_REPO_PASSWORD"
@echo "Tagged oci://$(OCI_REPO):$(GITOPS_VERSION) as $(TAG)"
# Tag git and push OCI artifact
release:
@if [ -z "$(TAG)" ]; then echo "Usage: make release TAG=v0.3.0 [MSG=\"Release description\"]"; exit 1; fi
git tag -a $(TAG) -m "$(or $(MSG),Release $(TAG))"
git push origin $(TAG)
@echo "Pushing gitops artifact to oci://$(OCI_REPO):$(TAG)..."
@set -a && source $(ENV_FILE) && set +a && \
flux push artifact oci://$(OCI_REPO):$(TAG) \
--path=./$(GITOPS_DIR) \
--source="$(shell git config --get remote.origin.url)" \
--revision="$(TAG)@sha1:$(shell git rev-parse HEAD)" \
--creds="$$OCI_REPO_USERNAME:$$OCI_REPO_PASSWORD"
@set -a && source $(ENV_FILE) && set +a && \
flux tag artifact oci://$(OCI_REPO):$(TAG) --tag=latest \
--creds="$$OCI_REPO_USERNAME:$$OCI_REPO_PASSWORD"
@echo "Released $(TAG) — git tag pushed, OCI artifact pushed and tagged latest"
# List published artifact versions
list-artifacts:
@echo "Artifacts in oci://$(OCI_REPO):"
@set -a && source $(ENV_FILE) && set +a && \
flux list artifacts oci://$(OCI_REPO) \
--creds="$$OCI_REPO_USERNAME:$$OCI_REPO_PASSWORD"