## MinIO S3 Operator & Tenant Management
## HA S3-хранилище на базе MinIO

# Include common variables and functions
include common/Makefile

# MinIO configuration
# Using common namespace variables from common/Makefile
HELMFILE_OPERATOR := minio/helmfile-operator.yaml
HELMFILE_TENANT := minio/helmfile-tenant.yaml

.PHONY: minio-help
minio-help:
	@echo ""
	@echo "$(COLOR_BOLD)MinIO S3 Commands:$(COLOR_RESET)"
	@echo "  make minio-install-operator   - Install MinIO Operator and Console"
	@echo "  make minio-update-operator    - Update MinIO Operator"
	@echo "  make minio-uninstall-operator - Uninstall operator (keeps tenants)"
	@echo "  make minio-create-secret      - Create S3 credentials secret (interactive)"
	@echo "  make minio-update-secret      - Update S3 credentials secret (interactive)"
	@echo "  make minio-delete-secret      - Delete S3 credentials secret"
	@echo "  make minio-get-secret         - Get S3 credentials secret info"
	@echo "  make minio-create-tenant      - Create HA MinIO tenant (s3-public)"
	@echo "  make minio-update-tenant     - Update MinIO tenant configuration"
	@echo "  make minio-delete-tenant      - Delete MinIO tenant and all related resources (operator stays)"
	@echo "  make minio-enable-metrics     - Enable Prometheus metrics collection (apply ServiceMonitor)"
	@echo "  make minio-create-prometheus-token - Create Secret with bearer token for metrics authentication"
	@echo "  make minio-status             - Check MinIO operator and tenant status"
	@echo "  make minio-uninstall          - Uninstall MinIO operator and tenants"
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) Before installing, prepare nodes:"
	@echo "  cd ../.. && make k8s-prepare-nodes"

.PHONY: minio-install-operator
minio-install-operator: install-namespaces
	$(call print_info,Creating MinIO namespaces...)
	@$(KUBECTL) apply -f minio/manifests/tech-minio-operator.yaml
	@$(KUBECTL) apply -f minio/manifests/tech-minio-tenants.yaml
	$(call print_info,Installing MinIO Operator via helmfile...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$helmfilePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'minio', 'helmfile-operator.yaml')); Write-Host 'Using helmfile: ' $$helmfilePath; if (-not (Test-Path $$helmfilePath)) { Write-Host 'Error: Helmfile not found at: ' $$helmfilePath; exit 1 }; $$content = Get-Content $$helmfilePath -Raw; if ($$content -notmatch 'minio-operator') { Write-Host 'Error: Wrong helmfile content! Expected minio-operator but found:'; Get-Content $$helmfilePath | Select-Object -First 3; exit 1 }; $$env:KUBECONFIG = $$kubeconfig; helmfile -f \"$$helmfilePath\" sync"
else
	$(call run_helmfile,$(HELMFILE_OPERATOR),sync)
endif
	$(call print_success,MinIO Operator installed!)

.PHONY: minio-update-operator
minio-update-operator:
	$(call print_info,Updating MinIO Operator via helmfile...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$helmfilePath = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, 'minio', 'helmfile-operator.yaml')); if (-not (Test-Path $$helmfilePath)) { Write-Host 'Error: Helmfile not found at: ' $$helmfilePath; exit 1 }; $$env:KUBECONFIG = $$kubeconfig; helmfile -f \"$$helmfilePath\" sync"
else
	$(call run_helmfile,$(HELMFILE_OPERATOR),sync)
endif
	@$(KUBECTL) apply -f minio/manifests/networkpolicy.yaml
	@$(KUBECTL) apply -f minio/manifests/storageclass.yaml
	$(call print_success,MinIO Operator updated!)

.PHONY: minio-uninstall-operator
minio-uninstall-operator:
	$(call print_warning,This will uninstall MinIO Operator!)
	@echo "Note: MinIO tenants will NOT be deleted."
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Uninstalling operator...)
ifeq ($(DETECTED_OS),Windows)
	-@$(call run_helmfile,$(HELMFILE_OPERATOR),destroy) 2>nul || echo "Operator may already be uninstalled"
else
	-@$(call run_helmfile,$(HELMFILE_OPERATOR),destroy) || true
endif
	$(call print_success,Operator uninstalled. Tenants remain.)

.PHONY: minio-create-secret
minio-create-secret:
	$(call print_info,Creating secret s3-public-env-configuration in $(MINIO_TENANTS_NAMESPACE)...)
	@echo "$(COLOR_YELLOW)Enter MINIO_ROOT_USER:$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$user = Read-Host -Prompt '> '; Write-Host ''; Write-Host '$(COLOR_YELLOW)Enter MINIO_ROOT_PASSWORD:$(COLOR_RESET)'; $$passSecure = Read-Host -AsSecureString -Prompt '> '; $$passPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($$passSecure)); $$configEnv = \"export MINIO_ROOT_USER=$$user`nexport MINIO_ROOT_PASSWORD=$$passPlain\"; $$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(MINIO_TENANTS_NAMESPACE) delete secret s3-public-env-configuration --ignore-not-found=true 2>$$null; kubectl -n $(MINIO_TENANTS_NAMESPACE) create secret generic s3-public-env-configuration --from-literal=config.env=\"$$configEnv\""
else
	@read -p "> " user && \
		echo "$(COLOR_YELLOW)Enter MINIO_ROOT_PASSWORD:$(COLOR_RESET)" && \
		read -s -p "> " pass && echo "" && \
		configEnv="export MINIO_ROOT_USER=$$user$$'\n'export MINIO_ROOT_PASSWORD=$$pass" && \
		$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) delete secret s3-public-env-configuration --ignore-not-found=true 2>/dev/null || true && \
		$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) create secret generic s3-public-env-configuration --from-literal=config.env="$$configEnv"
endif
	$(call print_success,Secret created! Format: config.env with export statements)

.PHONY: minio-update-secret
minio-update-secret:
	$(call print_info,Updating secret s3-public-env-configuration in $(MINIO_TENANTS_NAMESPACE)...)
	@echo "$(COLOR_YELLOW)Enter MINIO_ROOT_USER:$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$user = Read-Host -Prompt '> '; Write-Host ''; Write-Host '$(COLOR_YELLOW)Enter MINIO_ROOT_PASSWORD:$(COLOR_RESET)'; $$passSecure = Read-Host -AsSecureString -Prompt '> '; $$passPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($$passSecure)); $$configEnv = \"export MINIO_ROOT_USER=$$user`nexport MINIO_ROOT_PASSWORD=$$passPlain\"; $$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(MINIO_TENANTS_NAMESPACE) delete secret s3-public-env-configuration --ignore-not-found=true 2>$$null; kubectl -n $(MINIO_TENANTS_NAMESPACE) create secret generic s3-public-env-configuration --from-literal=config.env=\"$$configEnv\""
else
	@read -p "> " user && \
		echo "$(COLOR_YELLOW)Enter MINIO_ROOT_PASSWORD:$(COLOR_RESET)" && \
		read -s -p "> " pass && echo "" && \
		configEnv="export MINIO_ROOT_USER=$$user$$'\n'export MINIO_ROOT_PASSWORD=$$pass" && \
		$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) delete secret s3-public-env-configuration --ignore-not-found=true 2>/dev/null || true && \
		$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) create secret generic s3-public-env-configuration --from-literal=config.env="$$configEnv"
endif
	$(call print_success,Secret updated! Format: config.env with export statements)

.PHONY: minio-delete-secret
minio-delete-secret:
	$(call print_warning,This will delete the s3-public-env-configuration secret!)
	@echo "Press Ctrl+C to cancel, or wait 5 seconds to continue..."
	$(call sleep_seconds,5)
	$(call print_info,Deleting secret s3-public-env-configuration...)
	-@$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) delete secret s3-public-env-configuration || true
	$(call print_success,Secret deleted!)

.PHONY: minio-get-secret
minio-get-secret:
	@echo ""
	@echo "$(COLOR_BOLD)=== MinIO Secret Info ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) get secret s3-public-env-configuration >/dev/null 2>&1 && \
		($(call print_success,Secret s3-public-env-configuration exists) && \
		 echo "$(COLOR_YELLOW)Secret contains: config.env$(COLOR_RESET)") || \
		($(call print_warning,Secret s3-public-env-configuration not found))
	@echo ""

.PHONY: minio-create-tenant
minio-create-tenant:
	$(call print_info,Applying MinIO resource policies...)
	@$(KUBECTL) apply -f minio/manifests/limitrange.yaml
	@$(KUBECTL) apply -f minio/manifests/resourcequota.yaml
	$(call print_info,Creating StorageClass for MinIO...)
	@$(KUBECTL) apply -f minio/manifests/storageclass.yaml
	$(call print_info,Creating MinIO tenant s3-public...)
	@$(KUBECTL) apply -f minio/manifests/minio/s3-public.yaml
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for tenant pods to be ready (this may take a few minutes)...$(COLOR_RESET)"
	$(call sleep_seconds,60)
	@$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) get pods -l v1.min.io/tenant=s3-public || true
	$(call print_success,MinIO tenant manifest applied!)

.PHONY: minio-update-tenant
minio-update-tenant:
	$(call print_info,Updating MinIO resource policies...)
	@$(KUBECTL) apply -f minio/manifests/limitrange.yaml
	@$(KUBECTL) apply -f minio/manifests/resourcequota.yaml
	$(call print_info,Updating MinIO tenant s3-public...)
	@$(KUBECTL) apply -f minio/manifests/minio/s3-public.yaml
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for tenant pods to be ready (this may take a few minutes)...$(COLOR_RESET)"
	$(call sleep_seconds,60)
	@$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) get pods -l v1.min.io/tenant=s3-public || true
	$(call print_success,MinIO tenant updated!)

.PHONY: minio-delete-tenant
minio-delete-tenant:
	$(call print_warning,This will delete MinIO tenant s3-public and ALL its data!)
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting MinIO tenant s3-public...)
	-@$(KUBECTL) delete tenant.minio.min.io s3-public -n $(MINIO_TENANTS_NAMESPACE) --wait=false || true
	$(call print_info,Waiting for tenant deletion to complete...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; $$maxIterations = 12; $$iteration = 0; while ($$iteration -lt $$maxIterations) { $$pods = kubectl -n $(MINIO_TENANTS_NAMESPACE) get pods -l v1.min.io/tenant=s3-public --no-headers 2>&1 | Out-String; if ($$LASTEXITCODE -ne 0 -or $$pods.Trim() -eq '') { break }; Start-Sleep -Seconds 5; $$iteration++ }"
else
	@for i in $$(seq 1 12); do \
		pods=$$($(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) get pods -l v1.min.io/tenant=s3-public --no-headers 2>&1); \
		if [ $$? -ne 0 ] || [ -z "$$pods" ]; then \
			break; \
		fi; \
		$(call sleep_seconds,5); \
	done
endif
	$(call print_info,Deleting PVCs for s3-public...)
	-@$(KUBECTL) delete pvc -n $(MINIO_TENANTS_NAMESPACE) -l v1.min.io/tenant=s3-public --ignore-not-found || true
ifeq ($(DETECTED_OS),Windows)
	@echo "Skipping bash script on Windows (PVCs should be deleted by kubectl command above)"
else
	@bash minio/scripts/delete-pvc.sh $(MINIO_TENANTS_NAMESPACE) $(KUBECONFIG) || true
endif
	$(call print_info,Deleting ingress for MinIO...)
	-@$(KUBECTL) delete ingress minio -n $(MINIO_TENANTS_NAMESPACE) --ignore-not-found || true
	$(call print_info,Cleaning up services...)
	-@$(KUBECTL) delete svc -n $(MINIO_TENANTS_NAMESPACE) -l v1.min.io/tenant=s3-public --ignore-not-found || true
	$(call print_success,MinIO tenant s3-public deleted! Operator remains installed.)

.PHONY: minio-status
minio-status:
	@echo ""
	@echo "$(COLOR_BOLD)=== MinIO Operator Status ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(MINIO_OPERATOR_NAMESPACE) get pods,svc
	@echo ""
	@echo "$(COLOR_BOLD)=== MinIO Tenants (CRs) ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) get tenants.minio.min.io || echo "No tenants found"
	@echo ""
	@echo "$(COLOR_BOLD)=== s3-public Pods ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(MINIO_TENANTS_NAMESPACE) get pods -l v1.min.io/tenant=s3-public -o wide || echo "Tenant s3-public not created yet"

.PHONY: minio-enable-metrics
minio-enable-metrics:
	$(call print_info,Checking for tech-monitoring namespace...)
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "\
		$$curDir = [System.IO.Directory]::GetCurrentDirectory(); \
		$$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); \
		$$env:KUBECONFIG = $$kubeconfig; \
		$$nsExists = kubectl get namespace tech-monitoring 2>&1; \
		if ($$LASTEXITCODE -ne 0) { \
			Write-Host 'Namespace tech-monitoring not found. Creating it...' -ForegroundColor Yellow; \
			kubectl apply -f monitoring/manifests/base/namespace.yaml; \
		} else { \
			Write-Host 'Namespace tech-monitoring exists.' -ForegroundColor Green; \
		}"
else
	@if ! $(KUBECTL) get namespace tech-monitoring >/dev/null 2>&1; then \
		echo "$(COLOR_YELLOW)Namespace tech-monitoring not found. Creating it...$(COLOR_RESET)"; \
		$(KUBECTL) apply -f monitoring/manifests/base/namespace.yaml; \
	else \
		echo "$(COLOR_GREEN)Namespace tech-monitoring exists.$(COLOR_RESET)"; \
	fi
endif
	$(call print_info,Applying ServiceMonitor for MinIO metrics...)
	@$(KUBECTL) apply -f monitoring/manifests/monitors/minio-servicemonitor.yaml
	$(call print_success,ServiceMonitor applied! Prometheus will start collecting metrics.)
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) MinIO v3 metrics require bearer token authentication."
	@echo "$(COLOR_YELLOW)Create the token secret with:$(COLOR_RESET) make minio-create-prometheus-token"

.PHONY: minio-create-prometheus-token
minio-create-prometheus-token:
	$(call print_info,Creating MinIO Prometheus bearer token secret...)
	@echo "$(COLOR_YELLOW)Enter the bearer token generated by 'mc admin prometheus generate':$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "\
		$$curDir = [System.IO.Directory]::GetCurrentDirectory(); \
		$$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); \
		$$env:KUBECONFIG = $$kubeconfig; \
		$$token = Read-Host -Prompt 'Bearer Token'; \
		if ([string]::IsNullOrWhiteSpace($$token)) { \
			Write-Host 'Error: Token cannot be empty' -ForegroundColor Red; \
			exit 1; \
		}; \
		kubectl -n tech-monitoring delete secret minio-prometheus-token --ignore-not-found=true 2>$$null; \
		kubectl -n tech-monitoring create secret generic minio-prometheus-token --from-literal=token=\"$$token\""
else
	@read -s -p "Bearer Token: " token && echo "" && \
		if [ -z "$$token" ]; then \
			echo "$(COLOR_RED)Error: Token cannot be empty$(COLOR_RESET)"; \
			exit 1; \
		fi && \
		$(KUBECTL) -n tech-monitoring delete secret minio-prometheus-token --ignore-not-found=true 2>/dev/null || true && \
		$(KUBECTL) -n tech-monitoring create secret generic minio-prometheus-token --from-literal=token="$$token"
endif
	$(call print_success,MinIO Prometheus token secret created!)
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) Prometheus will start collecting metrics after the secret is created."

.PHONY: minio-uninstall
minio-uninstall:
	$(call print_warning,This will delete ALL MinIO tenants and data!)
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting MinIO tenants...)
	-@$(KUBECTL) delete tenants.minio.min.io --all -n $(MINIO_TENANTS_NAMESPACE) || true
	$(call print_info,Uninstalling MinIO Operator...)
ifeq ($(DETECTED_OS),Windows)
	-@$(call run_helmfile,$(HELMFILE_OPERATOR),destroy) 2>nul || echo "Operator may already be uninstalled"
else
	-@$(call run_helmfile,$(HELMFILE_OPERATOR),destroy) || true
endif
	$(call print_success,MinIO uninstalled.)
