#!/usr/bin/env python3 # 2026-04-09 — v0.1.13: Strategy Recreate + preStop hook + liveness timeout fix import sys FILE = "/home/naeel/terra/sless/sqs-operator/internal/controller/queueservice_controller.go" with open(FILE, "r") as f: code = f.read() # === PATCH 1: Strategy Recreate === old_1 = "\t\t\t},\n\t\t\tTemplate: corev1.PodTemplateSpec{" new_1 = """\t\t\t}, \t\t\t// Recreate: старый pod убивается ДО создания нового. \t\t\t// H2 MVStore держит FileChannel.lock() на /data/elasticmq.mv.db — \t\t\t// при RollingUpdate два pod лезут в один PVC одновременно = ERR-SQS-06. \t\t\tStrategy: appsv1.DeploymentStrategy{ \t\t\t\tType: appsv1.RecreateDeploymentStrategyType, \t\t\t}, \t\t\tTemplate: corev1.PodTemplateSpec{""" count = code.count(old_1) if count != 1: print(f"FAIL patch 1: found {count} matches for Selector close + Template") sys.exit(1) code = code.replace(old_1, new_1, 1) print("PATCH 1 OK: Strategy Recreate") # === PATCH 2: terminationGracePeriodSeconds === old_2 = "\t\t\t\t\tSecurityContext: &corev1.PodSecurityContext{\n\t\t\t\t\t\tFSGroup: func() *int64 { v := int64(999); return &v }(),\n\t\t\t\t\t},\n\t\t\t\t\tContainers: func() []corev1.Container {" new_2 = """\t\t\t\t\tSecurityContext: &corev1.PodSecurityContext{ \t\t\t\t\t\tFSGroup: func() *int64 { v := int64(999); return &v }(), \t\t\t\t\t}, \t\t\t\t\t// 15 сек — достаточно для graceful shutdown JVM + H2 fsync. \t\t\t\t\tTerminationGracePeriodSeconds: func() *int64 { v := int64(15); return &v }(), \t\t\t\t\tContainers: func() []corev1.Container {""" count = code.count(old_2) if count != 1: print(f"FAIL patch 2: found {count} matches for SecurityContext + Containers") sys.exit(1) code = code.replace(old_2, new_2, 1) print("PATCH 2 OK: terminationGracePeriodSeconds 15") # === PATCH 3: LivenessProbe TimeoutSeconds=3 + preStop hook === old_3 = "\t\t\t\t\t\t\t\t\tInitialDelaySeconds: 5,\n\t\t\t\t\t\t\t\t\tPeriodSeconds: 10,\n\t\t\t\t\t\t\t\t\tFailureThreshold: 5,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}" new_3 = """\t\t\t\t\t\t\t\t\tInitialDelaySeconds: 5, \t\t\t\t\t\t\t\t\tPeriodSeconds: 10, \t\t\t\t\t\t\t\t\tTimeoutSeconds: 3, \t\t\t\t\t\t\t\t\tFailureThreshold: 5, \t\t\t\t\t\t\t\t}, \t\t\t\t\t\t\t\t// preStop: 3 сек на graceful shutdown H2 перед SIGTERM. \t\t\t\t\t\t\t\tLifecycle: &corev1.Lifecycle{ \t\t\t\t\t\t\t\t\tPreStop: &corev1.LifecycleHandler{ \t\t\t\t\t\t\t\t\t\tExec: &corev1.ExecAction{ \t\t\t\t\t\t\t\t\t\t\tCommand: []string{"sh", "-c", "sleep 3"}, \t\t\t\t\t\t\t\t\t\t}, \t\t\t\t\t\t\t\t\t}, \t\t\t\t\t\t\t\t}, \t\t\t\t\t\t\t}, \t\t\t\t\t\t}""" count = code.count(old_3) if count != 1: print(f"FAIL patch 3: found {count} matches for LivenessProbe block") sys.exit(1) code = code.replace(old_3, new_3, 1) print("PATCH 3 OK: timeoutSeconds=3 + preStop sleep 3") # === PATCH 4: version === if "0.1.12" in code: code = code.replace("0.1.12", "0.1.13") print("PATCH 4 OK: version -> 0.1.13") else: print("PATCH 4 SKIP: version string not found") with open(FILE, "w") as f: f.write(code) print("\nAll patches applied.")