167 lines
5.6 KiB
Python
167 lines
5.6 KiB
Python
|
|
"""
|
||
|
|
GBS Application Build & Push Script (Python version)
|
||
|
|
Run from local Windows machine - handles SFTP upload + remote build + push.
|
||
|
|
|
||
|
|
Usage:
|
||
|
|
python build_push.py <jar-file> <app-name> <env-prefix> [version-suffix]
|
||
|
|
|
||
|
|
Example:
|
||
|
|
python build_push.py E:\\projects\\xxx\\target\\app.jar jjb-saas-safety-eval ota 1
|
||
|
|
|
||
|
|
Result image:
|
||
|
|
jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com/ali_img_ns/prod-aly-ota-dragon-jjb-saas-safety-eval:ota-20260626-1
|
||
|
|
"""
|
||
|
|
|
||
|
|
import paramiko
|
||
|
|
import sys
|
||
|
|
import os
|
||
|
|
import time
|
||
|
|
from datetime import datetime
|
||
|
|
|
||
|
|
# ---- Configuration ----
|
||
|
|
MASTER = "192.168.20.100"
|
||
|
|
SSH_USER = "root"
|
||
|
|
SSH_PASSWD = "Zcloud@zcloud100"
|
||
|
|
|
||
|
|
ACR_REGISTRY = "jjb-registry-registry.cn-hangzhou.cr.aliyuncs.com"
|
||
|
|
ACR_NAMESPACE = "ali_img_ns"
|
||
|
|
ACR_USER = "10952138@qq.com"
|
||
|
|
ACR_PASS = "idurCT!rIq9EzISD"
|
||
|
|
|
||
|
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
|
|
DOCKERFILE_PATH = os.path.join(SCRIPT_DIR, "Dockerfile")
|
||
|
|
|
||
|
|
|
||
|
|
def ssh_exec(client, cmd, timeout=600):
|
||
|
|
"""Execute SSH command and print results."""
|
||
|
|
print(f" > {cmd[:120]}{'...' if len(cmd) > 120 else ''}")
|
||
|
|
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
|
||
|
|
out = stdout.read().decode('utf-8', errors='replace')
|
||
|
|
err = stderr.read().decode('utf-8', errors='replace')
|
||
|
|
exit_code = stdout.channel.recv_exit_status()
|
||
|
|
if out.strip():
|
||
|
|
for line in out.strip().split('\n')[-10:]: # last 10 lines
|
||
|
|
print(f" {line}")
|
||
|
|
if err.strip():
|
||
|
|
important = [l for l in err.strip().split('\n')
|
||
|
|
if not any(x in l for x in ['Downloading', 'Downloaded', 'Extracting', 'Progress'])]
|
||
|
|
if important:
|
||
|
|
print(f" [stderr] {'; '.join(important[:5])}")
|
||
|
|
return out.strip(), err.strip(), exit_code
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
if len(sys.argv) < 4:
|
||
|
|
print(__doc__)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
jar_local = sys.argv[1]
|
||
|
|
app_name = sys.argv[2]
|
||
|
|
env_prefix = sys.argv[3]
|
||
|
|
version_suffix = sys.argv[4] if len(sys.argv) > 4 else "1"
|
||
|
|
|
||
|
|
date_tag = datetime.now().strftime("%Y%m%d")
|
||
|
|
image_tag = f"{env_prefix}-{date_tag}-{version_suffix}"
|
||
|
|
full_image = f"{ACR_REGISTRY}/{ACR_NAMESPACE}/prod-aly-{env_prefix}-dragon-{app_name}:{image_tag}"
|
||
|
|
|
||
|
|
if not os.path.exists(jar_local):
|
||
|
|
print(f"ERROR: JAR file not found: {jar_local}")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
jar_size_mb = os.path.getsize(jar_local) / 1024 / 1024
|
||
|
|
build_dir = f"/tmp/docker-build-{app_name}"
|
||
|
|
jar_name = os.path.basename(jar_local)
|
||
|
|
|
||
|
|
print("=" * 60)
|
||
|
|
print(f" GBS Docker Build & Push (Remote)")
|
||
|
|
print("=" * 60)
|
||
|
|
print(f" JAR: {jar_local} ({jar_size_mb:.1f} MB)")
|
||
|
|
print(f" App: {app_name}")
|
||
|
|
print(f" Tag: {image_tag}")
|
||
|
|
print(f" Image: {full_image}")
|
||
|
|
print(f" Target: {MASTER}")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
# ---- Connect ----
|
||
|
|
client = paramiko.SSHClient()
|
||
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||
|
|
client.connect(MASTER, username=SSH_USER, password=SSH_PASSWD, timeout=30)
|
||
|
|
print("\n[1/5] SSH connected")
|
||
|
|
|
||
|
|
# ---- Prepare remote dir ----
|
||
|
|
ssh_exec(client, f"rm -rf {build_dir} && mkdir -p {build_dir}/target")
|
||
|
|
|
||
|
|
# ---- Upload JAR ----
|
||
|
|
print(f"\n[2/5] Uploading JAR ({jar_size_mb:.1f} MB)...")
|
||
|
|
sftp = client.open_sftp()
|
||
|
|
remote_jar = f"{build_dir}/target/{jar_name}"
|
||
|
|
start = time.time()
|
||
|
|
last_pct = -1
|
||
|
|
|
||
|
|
def progress(transferred, total):
|
||
|
|
nonlocal last_pct
|
||
|
|
pct = int(transferred * 100 / total)
|
||
|
|
if pct >= last_pct + 10:
|
||
|
|
last_pct = pct
|
||
|
|
mb = transferred / 1024 / 1024
|
||
|
|
elapsed = time.time() - start
|
||
|
|
speed = mb / elapsed if elapsed > 0 else 0
|
||
|
|
print(f" {pct}% ({mb:.1f} MB) - {speed:.1f} MB/s")
|
||
|
|
|
||
|
|
sftp.put(jar_local, remote_jar, callback=progress)
|
||
|
|
elapsed = time.time() - start
|
||
|
|
print(f" Done in {elapsed:.1f}s ({jar_size_mb/elapsed:.1f} MB/s)")
|
||
|
|
sftp.close()
|
||
|
|
|
||
|
|
# ---- Upload Dockerfile ----
|
||
|
|
ssh_exec(client, f"cat > {build_dir}/Dockerfile", timeout=10)
|
||
|
|
with open(DOCKERFILE_PATH, 'r', encoding='utf-8') as f:
|
||
|
|
dockerfile_content = f.read()
|
||
|
|
stdin, stdout, stderr = client.exec_command(f"cat > {build_dir}/Dockerfile")
|
||
|
|
stdin.write(dockerfile_content)
|
||
|
|
stdin.channel.shutdown_write()
|
||
|
|
stdout.read()
|
||
|
|
|
||
|
|
# ---- Copy JDK into context ----
|
||
|
|
print("\n[3/5] Preparing build context...")
|
||
|
|
ssh_exec(client, f"cp -r /opt/jdk1.8.0_202 {build_dir}/", timeout=120)
|
||
|
|
ssh_exec(client, f"du -sh {build_dir}/")
|
||
|
|
|
||
|
|
# ---- Docker build ----
|
||
|
|
print("\n[4/5] Building Docker image...")
|
||
|
|
out, err, code = ssh_exec(client, f"docker build -t '{full_image}' {build_dir}", timeout=300)
|
||
|
|
if code != 0:
|
||
|
|
print("ERROR: Docker build failed!")
|
||
|
|
client.close()
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
# ---- Push to ACR ----
|
||
|
|
print("\n[5/5] Pushing to ACR...")
|
||
|
|
ssh_exec(client, f"echo '{ACR_PASS}' | docker login --username={ACR_USER} --password-stdin {ACR_REGISTRY}")
|
||
|
|
out, err, code = ssh_exec(client, f"docker push '{full_image}'", timeout=600)
|
||
|
|
if code != 0:
|
||
|
|
print("ERROR: Docker push failed!")
|
||
|
|
client.close()
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
# ---- Verify & Cleanup ----
|
||
|
|
ssh_exec(client, f"docker images | grep '{app_name}'")
|
||
|
|
ssh_exec(client, f"rm -rf {build_dir}")
|
||
|
|
client.close()
|
||
|
|
|
||
|
|
# ---- Summary ----
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print(" BUILD COMPLETE")
|
||
|
|
print("=" * 60)
|
||
|
|
print(f"\n Image Address:\n {full_image}\n")
|
||
|
|
print(f" K8s Deploy:\n"
|
||
|
|
f" /usr/bin/kubectl create deployment {app_name} \\\n"
|
||
|
|
f" --image={full_image} -n jjb-dragon --replicas=1\n")
|
||
|
|
print(f" /usr/bin/kubectl set image deployment/{app_name} \\\n"
|
||
|
|
f" {app_name}={full_image} -n jjb-dragon\n")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|