## Redis Operator & Cluster Management
## HA Redis кластер через Opstree Redis Operator

# Include common variables and functions
include common/Makefile

# Redis configuration
# Using common namespace variables from common/Makefile
HELMFILE_OPERATOR := redis/helmfile-operator.yaml
HELMFILE_CLUSTER := redis/helmfile-cluster.yaml

.PHONY: redis-help
redis-help:
	@echo ""
	@echo "$(COLOR_BOLD)Redis Commands:$(COLOR_RESET)"
	@echo "  make redis-install-operator   - Install Opstree Redis Operator"
	@echo "  make redis-update-operator    - Update Opstree Redis Operator"
	@echo "  make redis-uninstall-operator - Uninstall operator (keeps clusters)"
	@echo "  make redis-create-secret     - Create Redis password secret (interactive)"
	@echo "  make redis-update-secret     - Update Redis password secret (interactive)"
	@echo "  make redis-delete-secret     - Delete Redis password secret"
	@echo "  make redis-get-secret        - Get Redis password secret info"
	@echo "  make redis-create-cluster     - Create HA Redis cluster (redis-cluster)"
	@echo "  make redis-update-cluster     - Update Redis cluster configuration"
	@echo "  make redis-delete-cluster     - Delete redis-cluster (keeps operator)"
	@echo "  make redis-install-insight    - Install RedisInsight UI"
	@echo "  make redis-status             - Check Redis operator and cluster status"
	@echo "  make redis-uninstall          - Uninstall Redis operator and clusters"
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) Before installing, prepare nodes:"
	@echo "  cd ../.. && make k8s-prepare-nodes"

.PHONY: redis-check-longhorn
redis-check-longhorn:
	$(call check_longhorn)

.PHONY: redis-install-operator
redis-install-operator: install-namespaces redis-check-longhorn
	$(call print_info,Creating Redis namespaces...)
	@$(KUBECTL) apply -f redis/manifests/tech-redis-operator.yaml
	@$(KUBECTL) apply -f redis/manifests/tech-redis-clusters.yaml
	$(call print_info,Applying Redis resource policies...)
	@$(KUBECTL) apply -f redis/manifests/limitrange.yaml
	@$(KUBECTL) apply -f redis/manifests/resourcequota.yaml
	@$(KUBECTL) apply -f redis/manifests/pdb.yaml
	@$(KUBECTL) apply -f redis/manifests/networkpolicy.yaml
	@$(KUBECTL) apply -f redis/manifests/storageclass.yaml
	$(call print_info,Installing Opstree Redis 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, 'redis', '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 'redis-operator') { Write-Host 'Error: Wrong helmfile content! Expected redis-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_info,Waiting for operator to be ready...)
ifeq ($(DETECTED_OS),Windows)
	@$(KUBECTL) -n $(REDIS_OPERATOR_NAMESPACE) rollout status deployment/redis-operator --timeout=5m 2>nul || echo "Deployment may not be ready yet"
else
	@$(KUBECTL) -n $(REDIS_OPERATOR_NAMESPACE) rollout status deployment/redis-operator --timeout=5m || true
endif
	$(call print_success,Redis Operator installed!)

.PHONY: redis-update-operator
redis-update-operator:
	$(call print_info,Updating Opstree Redis 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, 'redis', '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
	$(call print_info,Updating Redis resource policies...)
	@$(KUBECTL) apply -f redis/manifests/limitrange.yaml
	@$(KUBECTL) apply -f redis/manifests/resourcequota.yaml
	@$(KUBECTL) apply -f redis/manifests/pdb.yaml
	@$(KUBECTL) apply -f redis/manifests/networkpolicy.yaml
	@$(KUBECTL) apply -f redis/manifests/storageclass.yaml
	$(call print_info,Waiting for operator to be ready...)
ifeq ($(DETECTED_OS),Windows)
	@$(KUBECTL) -n $(REDIS_OPERATOR_NAMESPACE) rollout status deployment/redis-operator --timeout=5m 2>nul || echo "Deployment may not be ready yet"
else
	@$(KUBECTL) -n $(REDIS_OPERATOR_NAMESPACE) rollout status deployment/redis-operator --timeout=5m || true
endif
	$(call print_success,Redis Operator updated!)

.PHONY: redis-uninstall-operator
redis-uninstall-operator:
	$(call print_warning,This will uninstall Redis Operator!)
	@echo "Note: Redis clusters 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. Clusters remain.)

.PHONY: redis-create-secret
redis-create-secret:
	$(call print_info,Creating secret redis-cluster-secret in $(REDIS_CLUSTERS_NAMESPACE)...)
	@echo "$(COLOR_YELLOW)Enter Redis password:$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$pass = Read-Host -AsSecureString -Prompt '> '; $$passPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($$pass)); $$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(REDIS_CLUSTERS_NAMESPACE) delete secret redis-cluster-secret --ignore-not-found=true 2>$$null; kubectl -n $(REDIS_CLUSTERS_NAMESPACE) create secret generic redis-cluster-secret --from-literal=password=$$passPlain"
else
	@read -s -p "> " pass && \
		$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) delete secret redis-cluster-secret --ignore-not-found=true 2>/dev/null || true && \
		$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) create secret generic redis-cluster-secret --from-literal=password=$$pass
endif
	$(call print_success,Secret created!)

.PHONY: redis-update-secret
redis-update-secret:
	$(call print_info,Updating secret redis-cluster-secret in $(REDIS_CLUSTERS_NAMESPACE)...)
	@echo "$(COLOR_YELLOW)Enter Redis password:$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@powershell -NoProfile -Command "$$pass = Read-Host -AsSecureString -Prompt '> '; $$passPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($$pass)); $$curDir = [System.IO.Directory]::GetCurrentDirectory(); $$kubeconfig = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($$curDir, '$(KUBECONFIG_REL)')); $$env:KUBECONFIG = $$kubeconfig; kubectl -n $(REDIS_CLUSTERS_NAMESPACE) delete secret redis-cluster-secret --ignore-not-found=true 2>$$null; kubectl -n $(REDIS_CLUSTERS_NAMESPACE) create secret generic redis-cluster-secret --from-literal=password=$$passPlain"
else
	@read -s -p "> " pass && \
		$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) delete secret redis-cluster-secret --ignore-not-found=true 2>/dev/null || true && \
		$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) create secret generic redis-cluster-secret --from-literal=password=$$pass
endif
	$(call print_success,Secret updated!)

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

.PHONY: redis-get-secret
redis-get-secret:
	@echo ""
	@echo "$(COLOR_BOLD)=== Redis Secret Info ===$(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; $$result = kubectl -n $(REDIS_CLUSTERS_NAMESPACE) get secret redis-cluster-secret 2>&1; if ($$LASTEXITCODE -eq 0) { Write-Host '$(COLOR_GREEN)$(COLOR_BOLD)✓ Secret redis-cluster-secret exists$(COLOR_RESET)'; Write-Host '$(COLOR_YELLOW)Secret keys:$(COLOR_RESET)'; $$json = kubectl -n $(REDIS_CLUSTERS_NAMESPACE) get secret redis-cluster-secret -o json | ConvertFrom-Json; $$json.data.PSObject.Properties.Name | ForEach-Object { Write-Host $$_ } } else { Write-Host '$(COLOR_YELLOW)$(COLOR_BOLD)⚠ Secret redis-cluster-secret not found$(COLOR_RESET)' }"
else
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get secret redis-cluster-secret >/dev/null 2>&1 && \
		($(call print_success,Secret redis-cluster-secret exists) && \
		 echo "$(COLOR_YELLOW)Secret keys:$(COLOR_RESET)" && \
		 $(call get_secret_keys,$(REDIS_CLUSTERS_NAMESPACE),redis-cluster-secret)) || \
		($(call print_warning,Secret redis-cluster-secret not found))
endif
	@echo ""

.PHONY: redis-create-cluster
redis-create-cluster: redis-check-longhorn
	@echo ""
	@echo "$(COLOR_YELLOW)Note:$(COLOR_RESET) Make sure Redis password secret is created:"
	@echo "  make redis-create-secret"
	@echo ""
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get secret redis-cluster-secret || \
		($(call print_warning,Redis password secret not found!) && \
		 echo "$(COLOR_YELLOW)Please create secret first:$(COLOR_RESET)" && \
		 echo "  make redis-create-secret" && \
		 exit 1)
	$(call print_info,Applying Redis resource policies...)
	@$(KUBECTL) apply -f redis/manifests/default-deny-networkpolicy.yaml
	@$(KUBECTL) apply -f redis/manifests/limitrange.yaml
	@$(KUBECTL) apply -f redis/manifests/resourcequota.yaml
	@$(KUBECTL) apply -f redis/manifests/pdb.yaml
	@$(KUBECTL) apply -f redis/manifests/networkpolicy.yaml
	@$(KUBECTL) apply -f redis/manifests/networkpolicy-redisinsight.yaml
	$(call print_info,Creating StorageClass for Redis...)
	@$(KUBECTL) apply -f redis/manifests/storageclass.yaml
	$(call print_info,Creating Redis cluster redis-cluster...)
	@$(KUBECTL) apply -f redis/manifests/cluster/redis-operator/redis-cluster.yaml
	$(call print_info,Creating ServiceMonitor for Prometheus metrics...)
	@$(KUBECTL) apply -f redis/manifests/cluster/redis-operator/redis-servicemonitor.yaml || echo "ServiceMonitor may not be needed if Prometheus Operator is not installed"
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for cluster to be ready (this may take 3-5 minutes)...$(COLOR_RESET)"
	@echo "Monitor with: make redis-status"
	$(call sleep_seconds,60)
ifeq ($(DETECTED_OS),Windows)
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) wait --for=condition=ready pod -l redis.opstreelabs.in/cluster=redis-cluster --timeout=10m 2>nul || echo "Cluster may still be initializing"
else
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) wait --for=condition=ready pod -l redis.opstreelabs.in/cluster=redis-cluster --timeout=10m || true
endif
	$(call print_success,Redis cluster created!)

.PHONY: redis-update-cluster
redis-update-cluster:
	$(call print_info,Updating Redis resource policies...)
	@$(KUBECTL) apply -f redis/manifests/default-deny-networkpolicy.yaml
	@$(KUBECTL) apply -f redis/manifests/limitrange.yaml
	@$(KUBECTL) apply -f redis/manifests/resourcequota.yaml
	@$(KUBECTL) apply -f redis/manifests/pdb.yaml
	@$(KUBECTL) apply -f redis/manifests/networkpolicy.yaml
	@$(KUBECTL) apply -f redis/manifests/networkpolicy-redisinsight.yaml
	$(call print_info,Updating Redis cluster redis-cluster...)
	@$(KUBECTL) apply -f redis/manifests/cluster/redis-operator/redis-cluster.yaml
	@echo ""
	@echo "$(COLOR_YELLOW)Waiting for cluster to be ready (this may take 3-5 minutes)...$(COLOR_RESET)"
	@echo "Monitor with: make redis-status"
	$(call sleep_seconds,60)
ifeq ($(DETECTED_OS),Windows)
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) wait --for=condition=ready pod -l redis.opstreelabs.in/cluster=redis-cluster --timeout=10m 2>nul || echo "Cluster may still be updating"
else
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) wait --for=condition=ready pod -l redis.opstreelabs.in/cluster=redis-cluster --timeout=10m || true
endif
	$(call print_success,Redis cluster updated!)

.PHONY: redis-delete-cluster
redis-delete-cluster:
	$(call print_warning,This will delete the redis-cluster and its data!)
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting redis-cluster CR...)
ifeq ($(DETECTED_OS),Windows)
	-@$(KUBECTL) delete rediscluster redis-cluster -n $(REDIS_CLUSTERS_NAMESPACE) 2>nul || echo "Cluster may already be deleted"
	$(call print_info,Deleting redis-cluster PVCs (if any)...)
	-@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) delete pvc -l redis.opstreelabs.in/cluster=redis-cluster 2>nul || echo "PVCs may already be deleted"
else
	-@$(KUBECTL) delete rediscluster redis-cluster -n $(REDIS_CLUSTERS_NAMESPACE) || true
	$(call print_info,Deleting redis-cluster PVCs (if any)...)
	-@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) delete pvc -l redis.opstreelabs.in/cluster=redis-cluster || true
endif
	$(call print_success,redis-cluster deleted.)

.PHONY: redis-install-insight
redis-install-insight:
	$(call print_info,Installing RedisInsight...)
	@$(KUBECTL) apply -f redis/manifests/networkpolicy-redisinsight.yaml
	@$(KUBECTL) apply -f redis/manifests/cluster/redis-operator/redisinsight.yaml
	$(call print_info,Waiting for RedisInsight to be ready...)
ifeq ($(DETECTED_OS),Windows)
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) rollout status deployment/redisinsight --timeout=3m 2>nul || echo "Deployment may not be ready yet"
else
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) rollout status deployment/redisinsight --timeout=3m || true
endif
	$(call print_success,RedisInsight installed!)

.PHONY: redis-status
redis-status:
	@echo ""
	@echo "$(COLOR_BOLD)=== Redis Operator Status ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(REDIS_OPERATOR_NAMESPACE) get pods,svc
	@echo ""
	@echo "$(COLOR_BOLD)=== Redis Clusters (CRs) ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get redisclusters.redis.opstreelabs.in || echo "No clusters found"
	@echo ""
	@echo "$(COLOR_BOLD)=== redis-cluster Pods ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get pods -l redis.opstreelabs.in/cluster=redis-cluster -o wide || echo "Cluster redis-cluster not created yet"
	@echo ""
	@echo "$(COLOR_BOLD)=== redis-cluster Services ===$(COLOR_RESET)"
ifeq ($(DETECTED_OS),Windows)
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get svc -l redis.opstreelabs.in/cluster=redis-cluster 2>nul || echo "No services found"
else
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get svc -l redis.opstreelabs.in/cluster=redis-cluster || true
endif
	@echo ""
	@echo "$(COLOR_BOLD)=== RedisInsight ===$(COLOR_RESET)"
	@$(KUBECTL) -n $(REDIS_CLUSTERS_NAMESPACE) get pods,svc -l app=redisinsight || echo "RedisInsight not installed"
	@echo ""

.PHONY: redis-uninstall
redis-uninstall:
	$(call print_warning,This will delete ALL Redis clusters and data!)
	@echo "Press Ctrl+C to cancel, or wait 10 seconds to continue..."
	$(call sleep_seconds,10)
	$(call print_info,Deleting Redis clusters...)
ifeq ($(DETECTED_OS),Windows)
	-@$(KUBECTL) delete redisclusters.redis.opstreelabs.in --all -n $(REDIS_CLUSTERS_NAMESPACE) 2>nul || echo "Clusters may already be deleted"
	-@$(KUBECTL) delete redis.redis.opstreelabs.in --all -n $(REDIS_CLUSTERS_NAMESPACE) 2>nul || echo "Redis resources may already be deleted"
	-@$(KUBECTL) delete redisreplications.redis.opstreelabs.in --all -n $(REDIS_CLUSTERS_NAMESPACE) 2>nul || echo "Replications may already be deleted"
	$(call print_info,Uninstalling RedisInsight...)
	-@$(KUBECTL) delete -f redis/manifests/cluster/redis-operator/redisinsight.yaml 2>nul || echo "RedisInsight may already be deleted"
	$(call print_info,Uninstalling operator...)
	-@$(call run_helmfile,$(HELMFILE_OPERATOR),destroy) 2>nul || echo "Operator may already be uninstalled"
else
	-@$(KUBECTL) delete redisclusters.redis.opstreelabs.in --all -n $(REDIS_CLUSTERS_NAMESPACE) || true
	-@$(KUBECTL) delete redis.redis.opstreelabs.in --all -n $(REDIS_CLUSTERS_NAMESPACE) || true
	-@$(KUBECTL) delete redisreplications.redis.opstreelabs.in --all -n $(REDIS_CLUSTERS_NAMESPACE) || true
	$(call print_info,Uninstalling RedisInsight...)
	-@$(KUBECTL) delete -f redis/manifests/cluster/redis-operator/redisinsight.yaml || true
	$(call print_info,Uninstalling operator...)
	-@$(call run_helmfile,$(HELMFILE_OPERATOR),destroy) || true
endif
	$(call print_success,Redis uninstalled.)
