- 37개 파일 IP → zioinfo.co.kr 치환 (소스/매뉴얼/설정/하네스) - Manager DrConsole/NetworkConsole/CsapConsole 빌드 + /var/www/manager/ 배포 - 테스트: Manager HTTP 200, ITSM 신규 API 7개 전체 200 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
5.2 KiB
Python
125 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Deploy Webhook 서버에 guardia-itsm 배포 스텝 추가"""
|
|
import paramiko, time, sys
|
|
|
|
HOST='101.79.17.164'; USER='root'; PASS='1q2w3e!Q'
|
|
client = paramiko.SSHClient()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
client.connect(HOST, username=USER, password=PASS, timeout=15)
|
|
sftp = client.open_sftp()
|
|
|
|
def run(label, cmd, timeout=30):
|
|
print(f'[{label}]')
|
|
chan = client.get_transport().open_session()
|
|
chan.set_combine_stderr(True)
|
|
chan.exec_command(cmd)
|
|
start = time.time()
|
|
while not chan.exit_status_ready():
|
|
if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)); sys.stdout.flush()
|
|
if time.time()-start > timeout: break
|
|
time.sleep(0.3)
|
|
while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096))
|
|
sys.stdout.flush()
|
|
chan.recv_exit_status()
|
|
|
|
new_deploy_server = '''#!/usr/bin/env python3
|
|
"""
|
|
ZioInfo + GUARDiA CI/CD Webhook Server
|
|
포트: 9999
|
|
- zioinfo-web push → 홈페이지 빌드/배포
|
|
- guardia-itsm push → GUARDiA ITSM 재배포
|
|
"""
|
|
import http.server, subprocess, threading, json, hmac, hashlib, logging, os
|
|
|
|
SECRET = b"zioinfo-deploy-2026"
|
|
ZIOINFO_SRC = "/opt/zioinfo/src"
|
|
GUARDIA_SRC = "/opt/guardia/src"
|
|
LOG = "/var/log/zioinfo/deploy.log"
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s %(levelname)s %(message)s",
|
|
handlers=[logging.FileHandler(LOG), logging.StreamHandler()])
|
|
|
|
def deploy_zioinfo():
|
|
logging.info("=== zioinfo-web 배포 시작 ===")
|
|
steps = [
|
|
("git pull", ["git", "-C", ZIOINFO_SRC, "pull", "origin", "main"]),
|
|
("npm build", ["bash", "-c", f"cd {ZIOINFO_SRC}/frontend && npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps && npm run build"]),
|
|
("mvn package", ["bash", "-c", f"cd {ZIOINFO_SRC}/backend && /usr/bin/mvn clean package -DskipTests -q"]),
|
|
("deploy jar", ["bash", "-c", f"cp {ZIOINFO_SRC}/backend/target/zioinfo-web-*.jar /opt/zioinfo/app/app.jar"]),
|
|
("deploy static", ["bash", "-c", f"cp -r {ZIOINFO_SRC}/backend/src/main/resources/static/. /var/www/zioinfo/"]),
|
|
("restart", ["systemctl", "restart", "zioinfo"]),
|
|
]
|
|
for name, cmd in steps:
|
|
logging.info(f"[{name}] 실행 중...")
|
|
r = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
|
|
if r.returncode != 0:
|
|
logging.error(f"[{name}] 실패: {r.stderr[-300:]}")
|
|
return False
|
|
logging.info(f"[{name}] 완료")
|
|
logging.info("=== zioinfo-web 배포 완료 ===")
|
|
return True
|
|
|
|
def deploy_guardia():
|
|
logging.info("=== GUARDiA ITSM 배포 시작 ===")
|
|
steps = [
|
|
("git clone/pull", ["bash", "-c",
|
|
f"[ -d {GUARDIA_SRC}/.git ] && git -C {GUARDIA_SRC} pull origin main "
|
|
f"|| git clone http://zio:Zio%40Admin2026%21@localhost:3000/zio/guardia-itsm.git {GUARDIA_SRC}"]),
|
|
("rsync", ["bash", "-c",
|
|
f"rsync -a --exclude=__pycache__ --exclude=*.db --exclude=.git "
|
|
f"{GUARDIA_SRC}/ /opt/guardia/app/"]),
|
|
("pip install", ["/opt/guardia/venv/bin/pip", "install", "-r",
|
|
"/opt/guardia/app/requirements.txt", "-q"]),
|
|
("restart", ["systemctl", "restart", "guardia"]),
|
|
]
|
|
for name, cmd in steps:
|
|
logging.info(f"[{name}] 실행 중...")
|
|
r = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
|
|
if r.returncode != 0:
|
|
logging.error(f"[{name}] 실패: {r.stderr[-300:]}")
|
|
return False
|
|
logging.info(f"[{name}] 완료")
|
|
logging.info("=== GUARDiA ITSM 배포 완료 ===")
|
|
return True
|
|
|
|
class WebhookHandler(http.server.BaseHTTPRequestHandler):
|
|
def do_POST(self):
|
|
length = int(self.headers.get("Content-Length", 0))
|
|
body = self.rfile.read(length)
|
|
sig = self.headers.get("X-Gitea-Signature", "")
|
|
expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
|
|
if sig and not hmac.compare_digest(sig, expected):
|
|
self.send_response(403); self.end_headers(); return
|
|
self.send_response(202); self.end_headers()
|
|
self.wfile.write(b"Deploy queued")
|
|
# 어떤 저장소인지 판단
|
|
try:
|
|
payload = json.loads(body)
|
|
repo = payload.get("repository", {}).get("name", "")
|
|
except Exception:
|
|
repo = ""
|
|
if "guardia" in repo.lower():
|
|
threading.Thread(target=deploy_guardia, daemon=True).start()
|
|
else:
|
|
threading.Thread(target=deploy_zioinfo, daemon=True).start()
|
|
def log_message(self, fmt, *args):
|
|
logging.info(fmt % args)
|
|
|
|
if __name__ == "__main__":
|
|
os.makedirs("/var/log/zioinfo", exist_ok=True)
|
|
logging.info("ZioInfo + GUARDiA Deploy Webhook 서버 시작 (포트 9999)")
|
|
server = http.server.HTTPServer(("0.0.0.0", 9999), WebhookHandler)
|
|
server.serve_forever()
|
|
'''
|
|
|
|
with sftp.open('/opt/zioinfo/deploy_server.py', 'w') as f:
|
|
f.write(new_deploy_server)
|
|
sftp.close()
|
|
|
|
run('Deploy 서버 재시작', 'systemctl restart zioinfo-deploy && sleep 3 && systemctl is-active zioinfo-deploy')
|
|
run('Webhook 테스트', 'curl -s -X POST http://localhost:9999/ -d "{}" -w " HTTP %{http_code}"')
|
|
|
|
client.close()
|
|
print('완료: Deploy Webhook 서버 업데이트 (zioinfo + guardia 모두 지원)')
|