26Y02n3

Young-Kyoo Kim·6일 전
import os
import glob
import re
import sys
import argparse  # ◀ [커맨드라인 인자 처리를 위한 모듈 추가]
import pandas as pd
import numpy as np
# ... 기존 openpyxl 및 minio 임포트 생략 ...

# ─── Main ─────────────────────────────────────────────────
def main():
    print("🚀 [Step6 개시] res_usage_ 계열 고도화 엑셀 리포터 엔진 가동...")
    
    # ─── 🎯 [요청 반영] --cluster Argument 파싱 레이어 구성 ───
    parser = argparse.ArgumentParser(description="Step6 리소스 정산 엑셀 마스터 빌더")
    parser.add_argument(
        "--cluster", 
        type=str, 
        choices=["COMPUTE", "STORAGE", "compute", "storage"],
        help="대상 클러스터 컨텍스트 명시 (COMPUTE 또는 STORAGE)"
    )
    args = parser.parse_args()
    
    # 1순위: --cluster 인자값, 2순위: CLUSTER_MODE 환경변수
    cluster_mode = args.cluster or os.getenv("CLUSTER_MODE", "")
    cluster_mode = cluster_mode.upper()  # 대문자 정형화
    
    if cluster_mode:
        print(f"🎯 클러스터 Argument/컨텍스트 고정 완료: [merged/{cluster_mode}/]")
        search_pattern = str(MERGED_DIR / cluster_mode / f"pareto_ns_{cluster_mode}_*.parquet")
    else:
        print("🔍 클러스터 미지정: merged/ 하위 모든 클러스터 서브폴더(*)를 자동 순회 탐색합니다.")
        search_pattern = str(MERGED_DIR / "*" / "pareto_ns_*.parquet")
        
    pareto_files = glob.glob(search_pattern)
    
    if not pareto_files:
        print(f"❌ 오류: 탐색된 파레토 가공원부(*.parquet) 파일이 없습니다. 타겟 경로를 확인하세요: {search_pattern}")
        return
        
    processed_count = 0
    for file_path in pareto_files:
        filename = os.path.basename(file_path)
        match = re.search(r"pareto_ns_(.*)_(.*)\.parquet", filename)
        if not match:
            continue
            
        infra_tag = match.group(1)   # 예: COMPUTE 또는 STORAGE
        date_tag  = match.group(2)   # 예: 20260702
        
        # 하위 클러스터 서브디렉토리 경로 명시적 조인
        p1 = MERGED_DIR / infra_tag / f"daily_enriched_{infra_tag}_{date_tag}.parquet"
        p2 = Path(file_path)
        p3 = MERGED_DIR / infra_tag / f"daily_ns_usage_{infra_tag}_{date_tag}.parquet"
        
        if not (p1.exists() and p3.exists()):
            print(f"⚠️  [세트 불완전] merged/{infra_tag}/ 하위에 쌍이 되는 가공 데이터가 유실되어 작업을 건너뜁니다.")
            continue
            
        print(f"\n" + "="*60)
        print(f"🔄 [서브폴더 파티션 검증 완료] Cluster: {infra_tag} | Date: {date_tag} 컴파일 가동")
        print("="*60)
        
        df_pod = pd.read_parquet(p1)
        df_ns = pd.read_parquet(p2)
        df_daily_ns = pd.read_parquet(p3)

        excel_name = f"res_usage_report_{infra_tag.lower()}_{date_tag}.xlsx"

        wb = Workbook()
        build_sheet_summary(wb, df_pod, df_ns, infra_tag)
        build_sheet_pareto(wb, df_ns, infra_tag)
        build_sheet_ns_daily(wb, df_daily_ns, infra_tag)
        build_sheet_cpu(wb, df_pod, infra_tag)
        build_sheet_memory(wb, df_pod, infra_tag)
        build_sheet_oom(wb, df_pod, infra_tag)
        build_sheet_violations(wb, df_pod, infra_tag)
        build_sheet_trends(wb, df_pod, infra_tag)
        build_sheet_workload(wb, df_pod, infra_tag)
        build_sheet_extra_charts(wb, infra_tag, date_tag)

        out_path = OUT_DIR / excel_name
        print(f"💾 openpyxl 스트림 디스크 저장 가동 중... ➡️ {out_path}")
        wb.save(out_path)
        print(f"📦 [로컬 컴파일 마감 완료]: {excel_name} ({out_path.stat().st_size/1024:.0f} KB)")

        # ─── 🪣 사내 MinIO AIStor 자동 배포 레이어 ───
        minio_endpoint   = os.getenv("MINIO_ENDPOINT")
        minio_access_key = os.getenv("MINIO_ACCESS_KEY")
        minio_secret_key = os.getenv("MINIO_SECRET_KEY")
        bucket_name      = os.getenv("MINIO_REPORT_BUCKET", "devops-test")

        if all([minio_endpoint, minio_access_key, minio_secret_key]):
            try:
                endpoint_clean = minio_endpoint.replace("http://", "").replace("https://", "")
                secure_flag = minio_endpoint.startswith("https://")
                
                minio_client = Minio(
                    endpoint_clean,
                    access_key=minio_access_key,
                    secret_key=minio_secret_key,
                    secure=secure_flag
                )
                
                if not minio_client.bucket_exists(bucket_name):
                    minio_client.make_bucket(bucket_name)
                    
                object_key = f"reports/{infra_tag.lower()}/{excel_name}"
                print(f"🪣  [오브젝트 스토리지 싱크] devops-test 버킷 배포 ➡️ MinIO://{object_key} 업로드 중...")
                minio_client.fput_file(bucket_name, object_key, str(out_path))
                print("🏁 === [전사 배포 마감 성공] 고도화 res_usage_ 마스터 엑셀 리포트 배포 자산화 완료 ===")
            except Exception as e:
                print(f"❌ [배포 에러] 사내 MinIO 원격 업로드 중 예외 발생: {str(e)}")
        else:
            print("⚠️ [안내] 접속 환경변수 생략으로 로컬 아카이빙 처리 후 해당 파티션을 마감합니다.")
            
        processed_count += 1
        
    print(f"\n🏁 === [전체 자동 매칭 빌드 완료] 총 {processed_count}개 세트 인프라 마스터 리포트 빌드 프로세스가 종결되었습니다. ===")

0개의 댓글