diff --git a/CLAUDE.md b/CLAUDE.md
index d1b452a..c33b9c6 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -186,6 +186,383 @@ QA Engineer
- **예시**: `kubectl exec -n phonebill-dev product-change-postgres-dev-postgresql-0 -c postgresql -- bash -c 'PGPASSWORD="$POSTGRES_POSTGRES_PASSWORD" psql -U postgres -d product_change_db -c "ALTER TABLE product_change.pc_product_change_history ALTER COLUMN customer_id TYPE VARCHAR(100);"'`
[가이드]
```
-$(cat claude/guide.md)
+# Clauding Guide
+최종 수정일시: 2025-11-18 20:10
+
+## 서비스기획 가이드
+- 서비스기획프롬프트
+ - 설명: 유저스토리 작성 등 서비스 기획을 위한 프롬프트 예시
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/prompt/02.think-prompt.md
+ - 파일명: think-prompt.md
+
+- 서비스기획가이드
+ - 설명: 서비스 기획 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/think/think-guide.md
+ - 파일명: think-guide.md
+
+---
+
+## 설계 가이드
+- 설계실행프롬프트
+ - 설명: 각 설계 단계 실행을 위한 프롬프트 모음
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/prompt/03.design-prompt.md
+ - 파일명: design-prompt.md
+
+- 공통설계원칙
+ - 설명: 모든 설계 시 적용할 공통설계원칙
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/common-principles.md
+ - 파일명: common-principles.md
+
+- UI/UX설계가이드
+ - 설명: UI/UX 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/uiux-design.md
+ - 파일명: uiux-design.md
+
+- 프로토타입작성가이드
+ - 설명: 프로토타입 작성 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/uiux-prototype.md
+ - 파일명: uiux-prototype.md
+
+- 클라우드아키텍처패턴선정가이드
+ - 설명: 클라우드 아키텍처 패턴 선정 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/architecture-patterns.md
+ - 파일명: architecture-patterns.md
+
+- 논리아키텍처설계가이드
+ - 설명: 논리 아키텍처 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/logical-architecture-design.md
+ - 파일명: logical-architecture-design.md
+
+- API설계가이드
+ - 설명: API 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/api-design.md
+ - 파일명: api-design.md
+
+- 외부시퀀스설계가이드
+ - 설명: 외부 시퀀스 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/sequence-outer-design.md
+ - 파일명: sequence-outer-design.md
+
+- 내부시퀀스설계 가이드
+ - 설명: 내부 시퀀스 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/sequence-inner-design.md
+ - 파일명: sequence-inner-design.md
+
+- 클래스설계가이드
+ - 설명: 클래스 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/class-design.md
+ - 파일명: class-design.md
+
+- 데이터설계가이드
+ - 설명: 데이터 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/data-design.md
+ - 파일명: data-design.md
+
+- HighLevel아키텍처정의가이드
+ - 설명: 상위수준 아키텍처 정의 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/architecture-highlevel.md
+ - 파일명: architecture-highlevel.md
+
+- 물리아키텍처설계가이드
+ - 설명: 물리 아키텍처 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/physical-architecture-design.md
+ - 파일명: physical-architecture-design.md
+
+- 프론트엔드설계가이드
+ - 설명: 프론트엔드 설계 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/design/frontend-design.md
+ - 파일명: frontend-design.md
+
+---
+
+## 개발 가이드
+- 개발실행프롬프트
+ - 설명: 각 개발 단계 실행을 위한 프롬프트 모음
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/prompt/04.develop-prompt.md
+ - 파일명: develop-prompt.md
+
+- 데이터베이스설치계획서가이드
+ - 설명: 데이터베이스 설치 방법 안내 요청 시 참조
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/database-plan.md
+ - 파일명: database-plan.md
+
+- 데이터베이스설치가이드
+ - 설명: 데이터베이스 설치 방법 안내 요청 시 참조
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/database-install.md
+ - 파일명: database-install.md
+
+- MQ설치게획서가이드
+ - 설명: Message Queue 설치 방법 안내 요청 시 참조
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/mq-plan.md
+ - 파일명: mq-plan.md
+
+- MQ설치가이드
+ - 설명: Message Queue 설치 방법 안내 요청 시 참조
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/mq-install.md
+ - 파일명: mq-install.md
+
+- 백엔드개발가이드
+ - 설명: 백엔드 개발 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/dev-backend.md
+ - 파일명: dev-backend.md
+
+- GradleWrapper생성가이드
+ - 설명: Gradle Wrapper 생성 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/gradle-wrapper.md
+ - 파일명: gradle-wrapper.md
+
+- 서비스실행프로파일작성가이드
+ - 설명: 백엔드 서비스 실행 프로파일 작성 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/make-run-profile.md
+ - 파일명: make-run-profile.md
+
+- 백엔드테스트가이드
+ - 설명: 백엔드 테스트 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/test-backend.md
+ - 파일명: test-backend.md
+
+- 프론트엔드개발가이드
+ - 설명: 프론트엔드 개발 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/develop/dev-frontend.md
+ - 파일명: dev-frontend.md
+
+---
+
+## 배포 가이드
+- 배포실행프롬프트
+ - 설명: 각 배포 단계 실행을 위한 프롬프트 모음
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/prompt/05.deploy-prompt.md
+ - 파일명: deploy-prompt.md
+- 백엔드컨테이너이미지작성가이드
+ - 설명: 백엔드 컨테이너 이미지 작성 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/build-image-back.md
+ - 파일명: build-image-back.md
+- 프론트엔드컨테이너이미지작성가이드
+ - 설명: 프론트엔드 컨테이너 이미지 작성 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/build-image-front.md
+ - 파일명: build-image-front.md
+- 백엔드컨테이너실행방법가이드
+ - 설명: 백엔드 컨테이너 실행방법 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/run-container-guide-back.md
+ - 파일명: run-container-guide-back.md
+- 프론트엔드컨테이너실행방법가이드
+ - 설명: 프론트엔드 컨테이너 실행방법 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/run-container-guide-front.md
+ - 파일명: run-container-guide-front.md
+- 백엔드배포가이드
+ - 설명: 백엔드 서비스를 쿠버네티스 클러스터에 배포하는 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-k8s-back.md
+ - 파일명: deploy-k8s-back.md
+- 프론트엔드배포가이드
+ - 설명: 프론트엔드 서비스를 쿠버네티스 클러스터에 배포하는 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-k8s-front.md
+ - 파일명: deploy-k8s-front.md
+- 백엔드Jenkins파이프라인작성가이드
+ - 설명: 백엔드 서비스를 Jenkins를 이용하여 CI/CD하는 배포 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-jenkins-cicd-back.md
+ - 파일명: deploy-jenkins-cicd-back.md
+- 프론트엔드Jenkins파이프라인작성가이드
+ - 설명: 프론트엔드 서비스를 Jenkins를 이용하여 CI/CD하는 배포 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-jenkins-cicd-front.md
+ - 파일명: deploy-jenkins-cicd-front.md
+- 백엔드GitHubActions파이프라인작성가이드
+ - 설명: 백엔드 서비스를 GitHub Actions를 이용하여 CI/CD하는 배포 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-actions-cicd-back.md
+ - 파일명: deploy-actions-cicd-back.md
+- 프론트엔드GitHubActions파이프라인작성가이드
+ - 설명: 프론트엔드 서비스를 GitHub Actions를 이용하여 CI/CD하는 배포 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-actions-cicd-front.md
+ - 파일명: deploy-actions-cicd-front.md
+- ArgoCD파이프라인준비가이드
+ - 설명: 프론트엔드/백엔드 서비스를 ArgoCD를 이용하여 CI와 CD를 분리하는 가이드
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/deploy/deploy-argocd-cicd.md
+ - 파일명: deploy-argocd-cicd.md
+
+## 참조 문서
+- 프로젝트지침템플릿
+ - 설명: 프로젝트 지침인 CLAUDE.md 파일 템플릿
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/references/instruction-template.md
+ - 파일명: instruction-template.md
+
+- 유저스토리작성방법
+ - 설명: 유저스토리 형식과 작성법
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/references/유저스토리작성방법.md
+ - 파일명: userstory-writing.md
+
+- 유저스토리예제
+ - 설명: 유저스토리 예제
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/samples/sample-%EC%9C%A0%EC%A0%80%EC%8A%A4%ED%86%A0%EB%A6%AC.md
+ - 파일명: sample-userstory.md
+
+- 클라우드아키텍처패턴요약표
+ - 설명: 클라우드 디자인 패턴 요약표
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/references/Cloud%20Design%20Patterns(%EA%B0%9C%EC%9A%94).md
+ - 파일명: cloud-design-patterns.md
+
+- HighLevel아키텍처정의서템플릿
+ - 설명: MSA 7대 컴포넌트별로 상위 수준의 아키텍처를 정의한 문서
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/references/highlevel-architecture-template.md
+ - 파일명: highlevel-architecture-template.md
+
+- 제품별버전가이드
+ - 설명: 개발언어, 개발 프레임워크, AI제품 등의 버전 참조를 위한 페이지 링크 제공
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/references/제품버전참조.md
+ - 파일명: version-link.md
+
+- 백킹서비스설치방법
+ - 설명: 데이터베이스, Message Queue 등 백킹서비스설치방법 설명
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/references/백킹서비스설치방법.md
+ - 파일명: backing-service-method.md
+
+---
+
+## 표준
+- 개발주석표준
+ - 설명: 개발 주석 표준
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/standards/standard_comment.md
+ - 파일명: standard_comment.md
+
+- 패키지구조표준
+ - 설명: 패키지 구조 표준과 설계 아키텍처 패턴(Layered, Clean, Hexagonal)별 예시
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/standards/standard_package_structure.md
+ - 파일명: standard_package_structure.md
+
+- 테스트코드표준
+ - 설명: 테스트 코드 작성 표준
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/standards/standard_testcode.md
+ - 파일명: standard_testcode.md
+
+---
+
+## 기술 도구
+- PlantUML문법검사가이드
+ - 설명: PlantUML 문법 검사하는 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/plantuml-guide.md
+ - 파일명: plantuml-guide.md
+
+- Mermaid문법검사가이드
+ - 설명: Mermaid 문법 검사하는 방법 안내
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/mermaid-guide.md
+ - 파일명: mermaid-guide.md
+
+- MCP동기화도구
+ - 설명: Window에서 Cloude Desktop의 MCP설정을 읽어 Claude Code에 MCP 서버를 동기화하는 툴
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/sync-mcp.md
+ - 파일명: sync-mcp.md
+
+- PlantUML문법검사기(Window)
+ - 설명: Window용 PlantUML 스크립트 문법 검사기
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/check-plantuml.ps1
+ - 파일명: check-plantuml.ps1
+
+- Mermaid문법검사기(Window)
+ - 설명: Window용 PlantUML 스크립트 문법 검사기
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/check-mermaid.ps1
+ - 파일명: check-mermaid.ps1
+
+- PlantUML문법검사기(Linux/Mac)
+ - 설명: Linux/Mac용 PlantUML 스크립트 문법 검사기
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/check-plantuml.sh
+ - 파일명: check-plantuml.sh
+
+- Mermaid문법검사기(Linux/Mac)
+ - 설명: Linux/Mac용 PlantUML 스크립트 문법 검사기
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/check-mermaid.sh
+ - 파일명: check-mermaid.sh
+
+- IntelliJ서비스실행기
+ - 설명: IntelliJ에 등록된 실행프로파일을 이용하여 서비스 실행
+ - URL: https://raw.githubusercontent.com/cna-bootcamp/clauding-guide/refs/heads/main/guides/tools/run-intellij-service-profile.py
+ - 파일명: run-intellij-service-profile.py
+
+---
+
+## 산출물 디렉토리
+- 유저스토리: design/userstory.md
+- UI/UX설계서: design/uiux/uiux.md
+- 스타일가이드: design/uiux/style-guide.md
+- 프로토타입: design/uiux/prototype/*.html
+- 아키텍처패턴: design/pattern/architecture-pattern.md
+- 논리아키텍처: design/backend/logical/*
+- API설계서: design/backend/api/*
+- API명세서: design/backend/api/spec/*
+- 외부시퀀스설계서: design/backend/sequence/outer/{플로우명}.puml
+- 내부시퀀스설계서: design/backend/sequence/inner/{service-name}-{flow-name}.puml
+- 클래스설계서: design/backend/class/*
+- 백엔드패키지구조도: 클래스설계 결과(design/backend/class/class.md)의 '패키지 구조도' 섹션
+- 데이터설계서: design/backend/database/*
+- HighLevel아키텍처정의서: design/high-level-architecture.md
+- 물리아키텍처: design/backend/physical/*
+- 데이터베이스설치계획서
+ - develop/database/plan/db-plan-{service-name}-dev.md
+ - develop/database/plan/db-plan-{service-name}-prod.md
+- 캐시설치계획서:
+ - develop/mq/mq-plan-dev.md
+ - develop/mq/mq-plan-prod.md
+- MQ설치계획서
+ - develop/database/plan/mq-plan-{service-name}-dev.md
+ - develop/database/plan/mq-plan-{service-name}-prod.md
+- 데이터베이스설치결과서
+ - develop/database/exec/db-exec-dev.md
+ - develop/database/exec/db-exec-prod.md
+- 캐시설치결과서
+ - develop/database/exec/cache-exec-{service-name}-dev.md
+ - develop/database/exec/cache-exec-{service-name}-prod.md
+- MQ설치결과서
+ - develop/mq/mq-exec-dev.md
+ - develop/mq/mq-exec-prod.md
+- 백엔드개발결과서: develop/dev/dev-backend.md
+- 백엔드테스트결과서: develop/dev/test-backend.md
+- 프론트엔드설계서: design/frontend/frontend-design.md
+
+## 프롬프트 약어
+### 역할 약어
+- "@archi": "--persona-architect"
+- "@front": "--persona-front"
+- "@back": "--persona-backend"
+- "@secu": "--persona-security"
+- "@qa": "--persona-qa"
+- "@refact": "--persona-refactor"
+- "@devops": "--persona-devops"
+- "@scribe": "--persona-scriber"
+
+### 작업 약어
+- "@complex-flag": --seq --c7 --uc --wave-mode auto --wave-strategy systematic --delegate auto
+
+- "@userstory": /sc:document @scribe @archi --think --wave-strategy systematic
+- "@uiux": /sc:design --think @front --uc --wave-mode auto --wave-strategy systematic
+- "@prototype": /sc:implement @front --answer-only
+- "@design-pattern": /sc:design @archi --think-hard @complex-flag
+- "@architecture": /sc:design @archi @back @refact --think-hard @complex-flag
+- "@plan": --plan --think
+- "@backing-service": /sc:implement @devops @back --think-hard @complex-flag
+- "@dev-backend": /sc:implement @back --think-hard @complex-flag
+- "@dev-front": /sc:implement @front --think-hard @complex-flag
+- "@test-backend": /sc:test @back @qa --think @complex-flag
+- "@test-api": /sc:test @back @qa --think 1) 소스 수정 후 컴파일하고 서버 시작 요청. 2) API경로와 DTO를 분석하여 정확하게 요청하여 테스트
+- "@run-back":
+ - 'IntelliJ서비스실행기'를 'tools' 디렉토리에 다운로드
+ - python 또는 python3 명령으로 백그라우드로 실행하고 결과 로그를 분석
+ nohup python3 tools/run-intellij-service-profile.py {service-name} > logs/{service-name}.log 2>&1 & echo "Started {service-name} with PID: $!"
+- "@test-front": /sc:test @front @qa --play --think @complex-flag
+- "@cicd": /sc:implement @devops --think @complex-flag
+- "@document": /sc:document --think @scribe @complex-flag
+- "@fix": /sc:troubleshoot --think @complex-flag
+- "@estimate": /sc:estimate --think-hard @complex-flag
+- "@improve": /sc:improve --think @complex-flag
+- "@analyze": /sc:analyze --think --seq
+- "@explain": /sc:explain --think --seq --answer-only
+
+### 파일 약어
+- "@error": debug/error.png파일을 의미함
+- "@info": debug/info.png파일을 의미함
+
+### 작업 단계 가이드 약어
+- "@think-help": "기획실행프롬프트 내용을 터미널에 출력"
+- "@design-help": "설계실행프롬프트 내용을 터미널에 출력"
+- "@develop-help": "개발실행프롬프트 내용을 터미널에 출력"
+- "@deploy-help": "배포실행프롬프트 내용을 터미널에 출력"
```
+
+
diff --git a/bill-service/.run/bill-service.run.xml b/bill-service/.run/bill-service.run.xml
index 5992e59..d09d59a 100644
--- a/bill-service/.run/bill-service.run.xml
+++ b/bill-service/.run/bill-service.run.xml
@@ -12,10 +12,10 @@
-
-
+
+
-
+
@@ -27,8 +27,8 @@
-
-
+
+
diff --git a/bill-service/src/main/resources/application.yml b/bill-service/src/main/resources/application.yml
index cc84bc7..82c02d0 100644
--- a/bill-service/src/main/resources/application.yml
+++ b/bill-service/src/main/resources/application.yml
@@ -25,9 +25,11 @@ spring:
leak-detection-threshold: 60000
# JPA 설정
jpa:
+ database-platform: org.hibernate.dialect.PostgreSQLDialect
show-sql: ${SHOW_SQL:true}
properties:
hibernate:
+ dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
use_sql_comments: true
connection:
diff --git a/deployment/cicd/Jenkinsfile b/deployment/cicd/Jenkinsfile
index 8ba01b8..75d2348 100644
--- a/deployment/cicd/Jenkinsfile
+++ b/deployment/cicd/Jenkinsfile
@@ -12,7 +12,7 @@ podTemplate(
slaveConnectTimeout: 300,
idleMinutes: 1,
activeDeadlineSeconds: 3600,
- podRetention: never(), // 파드 자동 정리 옵션: never(), onFailure(), always(), default()
+ podRetention: never(),
yaml: '''
spec:
terminationGracePeriodSeconds: 3
@@ -51,8 +51,8 @@ podTemplate(
]
),
containerTemplate(
- name: 'azure-cli',
- image: 'hiondal/azure-kubectl:latest',
+ name: 'kubectl',
+ image: 'bitnami/kubectl:latest',
command: 'cat',
ttyEnabled: true,
resourceRequestCpu: '200m',
@@ -63,14 +63,12 @@ podTemplate(
],
volumes: [
emptyDirVolume(mountPath: '/home/gradle/.gradle', memory: false),
- emptyDirVolume(mountPath: '/root/.azure', memory: false),
emptyDirVolume(mountPath: '/run/podman', memory: false)
]
) {
node(PIPELINE_ID) {
def props
- //def imageTag = getImageTag()
- def imageTag = "dg0500"
+ def imageTag = getImageTag()
def environment = params.ENVIRONMENT ?: 'dev'
def skipSonarQube = (params.SKIP_SONARQUBE?.toLowerCase() == 'true')
def services = ['api-gateway', 'user-service', 'bill-service', 'product-service', 'kos-mock']
@@ -81,15 +79,12 @@ podTemplate(
props = readProperties file: "deployment/cicd/config/deploy_env_vars_${environment}"
}
- stage("Setup AKS") {
- container('azure-cli') {
- withCredentials([azureServicePrincipal('azure-credentials')]) {
- sh """
- az login --service-principal -u \$AZURE_CLIENT_ID -p \$AZURE_CLIENT_SECRET -t \$AZURE_TENANT_ID
- az aks get-credentials --resource-group ${props.resource_group} --name ${props.cluster_name} --overwrite-existing
- kubectl create namespace phonebill-dg0500 --dry-run=client -o yaml | kubectl apply -f -
- """
- }
+ stage("Setup Kubernetes") {
+ container('kubectl') {
+ sh """
+ kubectl config use-context ${props.k8s_context} || echo "Context switch skipped"
+ kubectl create namespace ${props.namespace} --dry-run=client -o yaml | kubectl apply -f -
+ """
}
}
@@ -107,27 +102,36 @@ podTemplate(
echo "⏭️ Skipping SonarQube Analysis (SKIP_SONARQUBE=${params.SKIP_SONARQUBE})"
} else {
container('gradle') {
- withSonarQubeEnv('SonarQube') {
- // 각 서비스별 테스트 및 SonarQube 분석
- services.each { service ->
- sh """
- ./gradlew :${service}:test :${service}:jacocoTestReport :${service}:sonar \\
- -Dsonar.projectKey=phonebill-${service}-dg0500 \\
- -Dsonar.projectName=phonebill-${service}-dg0500 \\
- -Dsonar.java.binaries=build/classes/java/main \\
- -Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml \\
- -Dsonar.exclusions=**/config/**,**/entity/**,**/dto/**,**/*Application.class,**/exception/**
- """
- }
+ services.each { service ->
+ if (service != 'api-gateway') {
+ withSonarQubeEnv('SonarQube') {
+ echo "🔍 Starting SonarQube analysis for ${service}..."
- // Quality Gate 확인
- timeout(time: 10, unit: 'MINUTES') {
- def qg = waitForQualityGate()
- if (qg.status != 'OK') {
- error "Pipeline aborted due to quality gate failure: ${qg.status}"
+ sh """
+ ./gradlew :${service}:test :${service}:jacocoTestReport :${service}:sonar \\
+ -Dsonar.projectKey=phonebill-${service}-${environment} \\
+ -Dsonar.projectName=phonebill-${service}-${environment} \\
+ -Dsonar.java.binaries=build/classes/java/main \\
+ -Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml \\
+ -Dsonar.exclusions=**/config/**,**/entity/**,**/dto/**,**/*Application.class,**/exception/**
+ """
+
+ echo "✅ SonarQube analysis completed for ${service}"
+ }
+
+ timeout(time: 5, unit: 'MINUTES') {
+ echo "⏳ Waiting for Quality Gate result for ${service}..."
+ def qg = waitForQualityGate()
+ if (qg.status != 'OK') {
+ error "❌ Quality Gate failed for ${service}: ${qg.status}"
+ } else {
+ echo "✅ Quality Gate passed for ${service}"
+ }
}
}
}
+
+ echo "🎉 All services passed SonarQube Quality Gates!"
}
}
}
@@ -136,32 +140,23 @@ podTemplate(
timeout(time: 30, unit: 'MINUTES') {
container('podman') {
withCredentials([
- usernamePassword(
- credentialsId: 'acr-credentials',
- usernameVariable: 'ACR_USERNAME',
- passwordVariable: 'ACR_PASSWORD'
- ),
usernamePassword(
credentialsId: 'dockerhub-credentials',
usernameVariable: 'DOCKERHUB_USERNAME',
passwordVariable: 'DOCKERHUB_PASSWORD'
)
]) {
- // Docker Hub 로그인 (rate limit 해결)
sh "podman login docker.io --username \$DOCKERHUB_USERNAME --password \$DOCKERHUB_PASSWORD"
- // ACR 로그인
- sh "podman login acrdigitalgarage01.azurecr.io --username \$ACR_USERNAME --password \$ACR_PASSWORD"
-
services.each { service ->
sh """
podman build \\
--build-arg BUILD_LIB_DIR="${service}/build/libs" \\
--build-arg ARTIFACTORY_FILE="${service}.jar" \\
-f deployment/container/Dockerfile-backend \\
- -t acrdigitalgarage01.azurecr.io/phonebill/${service}:${environment}-${imageTag} .
+ -t docker.io/hiondal/${service}:${environment}-${imageTag} .
- podman push acrdigitalgarage01.azurecr.io/phonebill/${service}:${environment}-${imageTag}
+ podman push docker.io/hiondal/${service}:${environment}-${imageTag}
"""
}
}
@@ -170,9 +165,9 @@ podTemplate(
}
stage('Update Kustomize & Deploy') {
- container('azure-cli') {
+ container('kubectl') {
sh """
- # Kustomize 설치 (sudo 없이 사용자 디렉토리에 설치)
+ # Kustomize 설치
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
mkdir -p \$HOME/bin
mv kustomize \$HOME/bin/
@@ -181,12 +176,12 @@ podTemplate(
# 환경별 디렉토리로 이동
cd deployment/cicd/kustomize/overlays/${environment}
- # 서비스 목록 정의 (실제 서비스명으로 교체, 공백으로 구분)
+ # 서비스 목록 정의
services="api-gateway user-service bill-service product-service kos-mock"
# 이미지 태그 업데이트
for service in \$services; do
- \$HOME/bin/kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/\$service:${environment}-${imageTag}
+ \$HOME/bin/kustomize edit set image docker.io/hiondal/\$service:${environment}-${imageTag}
done
# 매니페스트 적용
@@ -195,17 +190,15 @@ podTemplate(
# 배포 상태 확인
echo "Waiting for deployments to be ready..."
for service in \$services; do
- kubectl -n phonebill-dg0500 wait --for=condition=available deployment/\$service --timeout=300s
+ kubectl -n ${props.namespace} wait --for=condition=available deployment/\$service --timeout=300s || echo "Timeout waiting for \$service"
done
"""
}
}
- // 파이프라인 완료 로그 (Scripted Pipeline 방식)
stage('Pipeline Complete') {
echo "🧹 Pipeline completed. Pod cleanup handled by Jenkins Kubernetes Plugin."
- // 성공/실패 여부 로깅
if (currentBuild.result == null || currentBuild.result == 'SUCCESS') {
echo "✅ Pipeline completed successfully!"
} else {
@@ -222,4 +215,4 @@ podTemplate(
echo "Pod will be terminated in 3 seconds due to terminationGracePeriodSeconds: 3"
}
}
-}
\ No newline at end of file
+}
diff --git a/deployment/cicd/Jenkinsfile_ArgoCD b/deployment/cicd/Jenkinsfile_ArgoCD
deleted file mode 100644
index 7c37bfa..0000000
--- a/deployment/cicd/Jenkinsfile_ArgoCD
+++ /dev/null
@@ -1,240 +0,0 @@
-def PIPELINE_ID = "${env.BUILD_NUMBER}"
-
-def getImageTag() {
- def dateFormat = new java.text.SimpleDateFormat('yyyyMMddHHmmss')
- def currentDate = new Date()
- return dateFormat.format(currentDate)
-}
-
-podTemplate(
- label: "${PIPELINE_ID}",
- serviceAccount: 'jenkins',
- slaveConnectTimeout: 300,
- idleMinutes: 1,
- activeDeadlineSeconds: 3600,
- podRetention: never(), // 파드 자동 정리 옵션: never(), onFailure(), always(), default()
- yaml: '''
- spec:
- terminationGracePeriodSeconds: 3
- restartPolicy: Never
- tolerations:
- - effect: NoSchedule
- key: dedicated
- operator: Equal
- value: cicd
- ''',
- containers: [
- containerTemplate(
- name: 'podman',
- image: "mgoltzsche/podman",
- ttyEnabled: true,
- command: 'cat',
- privileged: true,
- resourceRequestCpu: '500m',
- resourceRequestMemory: '2Gi',
- resourceLimitCpu: '2000m',
- resourceLimitMemory: '4Gi'
- ),
- containerTemplate(
- name: 'gradle',
- image: 'gradle:jdk21',
- ttyEnabled: true,
- command: 'cat',
- resourceRequestCpu: '500m',
- resourceRequestMemory: '1Gi',
- resourceLimitCpu: '1000m',
- resourceLimitMemory: '2Gi',
- envVars: [
- envVar(key: 'DOCKER_HOST', value: 'unix:///run/podman/podman.sock'),
- envVar(key: 'TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE', value: '/run/podman/podman.sock'),
- envVar(key: 'TESTCONTAINERS_RYUK_DISABLED', value: 'true')
- ]
- ),
- containerTemplate(
- name: 'azure-cli',
- image: 'hiondal/azure-kubectl:latest',
- command: 'cat',
- ttyEnabled: true,
- resourceRequestCpu: '200m',
- resourceRequestMemory: '512Mi',
- resourceLimitCpu: '500m',
- resourceLimitMemory: '1Gi'
- ),
- containerTemplate(
- name: 'git',
- image: 'alpine/git:latest',
- command: 'cat',
- ttyEnabled: true,
- resourceRequestCpu: '100m',
- resourceRequestMemory: '256Mi',
- resourceLimitCpu: '300m',
- resourceLimitMemory: '512Mi'
- )
- ],
- volumes: [
- emptyDirVolume(mountPath: '/home/gradle/.gradle', memory: false),
- emptyDirVolume(mountPath: '/root/.azure', memory: false),
- emptyDirVolume(mountPath: '/run/podman', memory: false)
- ]
-) {
- node(PIPELINE_ID) {
- def props
- def imageTag = "dg0500-"+getImageTag()
- def environment = params.ENVIRONMENT ?: 'dev'
- def skipSonarQube = (params.SKIP_SONARQUBE?.toLowerCase() == 'true')
- def services = ['api-gateway', 'user-service', 'bill-service', 'product-service', 'kos-mock']
-
- try {
- stage("Get Source") {
-
- checkout scm
- props = readProperties file: "deployment/cicd/config/deploy_env_vars_${environment}"
- }
-
-
- stage('Build') {
- container('gradle') {
- sh """
- chmod +x gradlew
- ./gradlew build -x test
- """
- }
- }
-
- stage('SonarQube Analysis & Quality Gate') {
- if (skipSonarQube) {
- echo "⏭️ Skipping SonarQube Analysis (SKIP_SONARQUBE=${params.SKIP_SONARQUBE})"
- } else {
- container('gradle') {
- // 각 서비스별로 개별적으로 SonarQube 분석 및 Quality Gate 확인
- services.each { service ->
- withSonarQubeEnv('SonarQube') {
- echo "🔍 Starting SonarQube analysis for ${service}..."
-
- // 서비스별 테스트 및 SonarQube 분석
- sh """
- ./gradlew :${service}:test :${service}:jacocoTestReport :${service}:sonar \\
- -Dsonar.projectKey=phonebill-${service}-dg0500 \\
- -Dsonar.projectName=phonebill-${service}-dg0500 \\
- -Dsonar.java.binaries=build/classes/java/main \\
- -Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml \\
- -Dsonar.exclusions=**/config/**,**/entity/**,**/dto/**,**/*Application.class,**/exception/**
- """
-
- echo "✅ SonarQube analysis completed for ${service}"
- }
-
- // 각 서비스별 Quality Gate 확인
- timeout(time: 5, unit: 'MINUTES') {
- echo "⏳ Waiting for Quality Gate result for ${service}..."
- def qg = waitForQualityGate()
- if (qg.status != 'OK') {
- error "❌ Quality Gate failed for ${service}: ${qg.status}"
- } else {
- echo "✅ Quality Gate passed for ${service}"
- }
- }
- }
-
- echo "🎉 All services passed SonarQube Quality Gates!"
- }
- }
- }
-
- stage('Build & Push Images') {
- timeout(time: 30, unit: 'MINUTES') {
- container('podman') {
- withCredentials([
- usernamePassword(
- credentialsId: 'acr-credentials',
- usernameVariable: 'ACR_USERNAME',
- passwordVariable: 'ACR_PASSWORD'
- ),
- usernamePassword(
- credentialsId: 'dockerhub-credentials',
- usernameVariable: 'DOCKERHUB_USERNAME',
- passwordVariable: 'DOCKERHUB_PASSWORD'
- )
- ]) {
- // Docker Hub 로그인 (rate limit 해결)
- sh "podman login docker.io --username \$DOCKERHUB_USERNAME --password \$DOCKERHUB_PASSWORD"
-
- // ACR 로그인
- sh "podman login acrdigitalgarage01.azurecr.io --username \$ACR_USERNAME --password \$ACR_PASSWORD"
-
- services.each { service ->
- sh """
- podman build \\
- --build-arg BUILD_LIB_DIR="${service}/build/libs" \\
- --build-arg ARTIFACTORY_FILE="${service}.jar" \\
- -f deployment/container/Dockerfile-backend \\
- -t acrdigitalgarage01.azurecr.io/phonebill/${service}:${environment}-${imageTag} .
-
- podman push acrdigitalgarage01.azurecr.io/phonebill/${service}:${environment}-${imageTag}
- """
- }
- }
- }
- }
- }
-
- stage('Update Manifest Repository') {
- container('git') {
- withCredentials([usernamePassword(
- credentialsId: 'github-credentials-dg0500',
- usernameVariable: 'GIT_USERNAME',
- passwordVariable: 'GIT_TOKEN'
- )]) {
- sh """
- # 매니페스트 레포지토리 클론
- REPO_URL=\$(echo "https://github.com/cna-bootcamp/phonebill-manifest.git" | sed 's|https://||')
- git clone https://\${GIT_USERNAME}:\${GIT_TOKEN}@\${REPO_URL} manifest-repo
- cd manifest-repo
-
- # 각 서비스별 이미지 태그 업데이트 (sed 명령 사용)
- services="api-gateway user-service bill-service product-service kos-mock"
- for service in \$services; do
- echo "Updating \$service image tag..."
- sed -i "s|image: acrdigitalgarage01.azurecr.io/phonebill/\$service:.*|image: acrdigitalgarage01.azurecr.io/phonebill/\$service:${environment}-${imageTag}|g" \\
- phonebill/kustomize/base/\$service/deployment.yaml
-
- # 변경 사항 확인
- echo "Updated \$service deployment.yaml:"
- grep "image: acrdigitalgarage01.azurecr.io/phonebill/\$service" phonebill/kustomize/base/\$service/deployment.yaml
- done
-
- # Git 설정 및 푸시
- git config user.name "Jenkins CI"
- git config user.email "jenkins@example.com"
- git add .
- git commit -m "🚀 Update phonebill ${environment} images to ${environment}-${imageTag}"
- git push origin main
-
- echo "✅ 매니페스트 업데이트 완료. ArgoCD가 자동으로 배포합니다."
- """
- }
- }
- }
-
- // 파이프라인 완료 로그 (Scripted Pipeline 방식)
- stage('Pipeline Complete') {
- echo "🧹 Pipeline completed. Pod cleanup handled by Jenkins Kubernetes Plugin."
-
- // 성공/실패 여부 로깅
- if (currentBuild.result == null || currentBuild.result == 'SUCCESS') {
- echo "✅ Pipeline completed successfully!"
- } else {
- echo "❌ Pipeline failed with result: ${currentBuild.result}"
- }
- }
-
- } catch (Exception e) {
- currentBuild.result = 'FAILURE'
- echo "❌ Pipeline failed with exception: ${e.getMessage()}"
- throw e
- } finally {
- echo "🧹 Cleaning up resources and preparing for pod termination..."
- echo "Pod will be terminated in 3 seconds due to terminationGracePeriodSeconds: 3"
- }
- }
-}
\ No newline at end of file
diff --git a/deployment/cicd/config/deploy_env_vars_dev b/deployment/cicd/config/deploy_env_vars_dev
index 5a49197..4ba0dc9 100644
--- a/deployment/cicd/config/deploy_env_vars_dev
+++ b/deployment/cicd/config/deploy_env_vars_dev
@@ -1,3 +1,4 @@
-# dev Environment Configuration
-resource_group=rg-digitalgarage-01
-cluster_name=aks-digitalgarage-01
\ No newline at end of file
+# Dev Environment Configuration
+# Minikube Remote 환경 설정
+k8s_context=minikube-remote
+namespace=phonebill
diff --git a/deployment/cicd/config/deploy_env_vars_prod b/deployment/cicd/config/deploy_env_vars_prod
index 53ee4a0..76bebbe 100644
--- a/deployment/cicd/config/deploy_env_vars_prod
+++ b/deployment/cicd/config/deploy_env_vars_prod
@@ -1,3 +1,4 @@
-# prod Environment Configuration
-resource_group=rg-digitalgarage-01
-cluster_name=aks-digitalgarage-01
\ No newline at end of file
+# Production Environment Configuration
+# Minikube Remote 환경 설정
+k8s_context=minikube-remote
+namespace=phonebill-prod
diff --git a/deployment/cicd/config/deploy_env_vars_staging b/deployment/cicd/config/deploy_env_vars_staging
index 5873b90..3ff8ab1 100644
--- a/deployment/cicd/config/deploy_env_vars_staging
+++ b/deployment/cicd/config/deploy_env_vars_staging
@@ -1,3 +1,4 @@
-# staging Environment Configuration
-resource_group=rg-digitalgarage-01
-cluster_name=aks-digitalgarage-01
\ No newline at end of file
+# Staging Environment Configuration
+# Minikube Remote 환경 설정
+k8s_context=minikube-remote
+namespace=phonebill-staging
diff --git a/deployment/cicd/jenkins-pipeline-guide.md b/deployment/cicd/jenkins-pipeline-guide.md
index 128112b..09c4841 100644
--- a/deployment/cicd/jenkins-pipeline-guide.md
+++ b/deployment/cicd/jenkins-pipeline-guide.md
@@ -1,181 +1,253 @@
-# phonebill Jenkins CI/CD 파이프라인 구축 가이드
+# Jenkins CI/CD 파이프라인 가이드
-## 📋 개요
+## 개요
+이 문서는 Phonebill 프로젝트의 Jenkins 기반 CI/CD 파이프라인 구축 및 운영 가이드입니다.
-본 가이드는 phonebill 프로젝트를 위한 Jenkins + Kustomize 기반 CI/CD 파이프라인 구축 방법을 제공합니다.
+## 프로젝트 정보
-### 프로젝트 정보
-- **시스템명**: phonebill
-- **서비스 목록**: api-gateway, user-service, bill-service, product-service, kos-mock
-- **JDK 버전**: 21
-- **Azure 환경**:
- - ACR: acrdigitalgarage01
- - 리소스 그룹: rg-digitalgarage-01
- - AKS 클러스터: aks-digitalgarage-01
- - 네임스페이스: phonebill-dg0500
+| 항목 | 값 |
+|------|-----|
+| 시스템명 | phonebill |
+| JDK 버전 | 21 |
+| Image Registry | docker.io |
+| Image Organization | hiondal |
+| K8s Context | minikube-remote |
+| Namespace | phonebill |
-## 🏗️ 파이프라인 아키텍처
+### 서비스 목록
+- api-gateway (포트: 8080)
+- user-service (포트: 8081)
+- bill-service (포트: 8082)
+- product-service (포트: 8083)
+- kos-mock (포트: 8084)
-### 주요 구성 요소
-- **빌드**: Gradle 기반 멀티모듈 빌드
-- **품질 검증**: SonarQube 분석 & Quality Gate
-- **컨테이너화**: Podman 기반 이미지 빌드
-- **배포**: Kustomize를 통한 환경별 배포
-- **인프라**: AKS (Azure Kubernetes Service)
+---
-### 환경별 설정
-| 환경 | Replicas | CPU Request | Memory Request | CPU Limit | Memory Limit |
-|------|----------|-------------|----------------|-----------|--------------|
-| dev | 1 | 256m | 256Mi | 1024m | 1024Mi |
-| staging | 2 | 512m | 512Mi | 2048m | 2048Mi |
-| prod | 3 | 1024m | 1024Mi | 4096m | 4096Mi |
+## 1. 사전 준비사항
-## 🚀 Jenkins 서버 환경 구성
-
-### 1. Jenkins 필수 플러그인 설치
-
-Jenkins 관리 > Plugin Manager에서 다음 플러그인들을 설치해주세요:
-
-```bash
-# Jenkins 필수 플러그인 목록
+### 1.1 Jenkins 필수 플러그인
+```
- Kubernetes
- Pipeline Utility Steps
- Docker Pipeline
- GitHub
- SonarQube Scanner
-- Azure Credentials
```
-### 2. Jenkins Credentials 등록
+### 1.2 Jenkins Credentials 등록
-**Manage Jenkins > Credentials > Add Credentials**에서 다음 인증 정보들을 등록해주세요:
+Jenkins 관리 > Credentials > Add Credentials에서 등록:
-#### Azure Service Principal
+#### Docker Hub Credentials
```
-Kind: Microsoft Azure Service Principal
-ID: azure-credentials
-Subscription ID: {구독ID}
-Client ID: {클라이언트ID}
-Client Secret: {클라이언트시크릿}
-Tenant ID: {테넌트ID}
-Azure Environment: Azure
+- Kind: Username with password
+- ID: dockerhub-credentials
+- Username: {DOCKERHUB_USERNAME}
+- Password: {DOCKERHUB_PASSWORD}
```
-#### ACR Credentials
+#### SonarQube Token (선택사항)
```
-Kind: Username with password
-ID: acr-credentials
-Username: acrdigitalgarage01
-Password: {ACR_PASSWORD}
+- Kind: Secret text
+- ID: sonarqube-token
+- Secret: {SonarQube 토큰}
```
-#### Docker Hub Credentials (Rate Limit 해결용)
+### 1.3 SonarQube 설정 (선택사항)
+Jenkins 관리 > Configure System > SonarQube servers:
```
-Kind: Username with password
-ID: dockerhub-credentials
-Username: {DOCKERHUB_USERNAME}
-Password: {DOCKERHUB_PASSWORD}
-참고: Docker Hub 무료 계정 생성 (https://hub.docker.com)
+- Name: SonarQube
+- Server URL: http://{SONARQUBE_URL}
+- Server authentication token: sonarqube-token (위에서 등록한 credential)
```
-#### SonarQube Token
-```
-Kind: Secret text
-ID: sonarqube-token
-Secret: {SonarQube토큰}
-```
+---
-## 📂 Kustomize 구조
+## 2. Kustomize 구조
+### 2.1 디렉토리 구조
```
-deployment/cicd/kustomize/
-├── base/
-│ ├── kustomization.yaml # Base 설정
-│ ├── common/ # 공통 리소스
-│ │ ├── cm-common.yaml
-│ │ ├── secret-common.yaml
-│ │ ├── secret-imagepull.yaml
-│ │ └── ingress.yaml
-│ ├── api-gateway/ # API Gateway 리소스
-│ │ ├── deployment.yaml
-│ │ ├── service.yaml
-│ │ └── cm-api-gateway.yaml
-│ ├── user-service/ # User Service 리소스
-│ │ ├── deployment.yaml
-│ │ ├── service.yaml
-│ │ ├── cm-user-service.yaml
-│ │ └── secret-user-service.yaml
-│ ├── bill-service/ # Bill Service 리소스
-│ │ ├── deployment.yaml
-│ │ ├── service.yaml
-│ │ ├── cm-bill-service.yaml
-│ │ └── secret-bill-service.yaml
-│ ├── product-service/ # Product Service 리소스
-│ │ ├── deployment.yaml
-│ │ ├── service.yaml
-│ │ ├── cm-product-service.yaml
-│ │ └── secret-product-service.yaml
-│ └── kos-mock/ # KOS Mock 리소스
-│ ├── deployment.yaml
-│ ├── service.yaml
-│ └── cm-kos-mock.yaml
-└── overlays/
- ├── dev/ # 개발 환경
+deployment/cicd/
+├── Jenkinsfile
+├── config/
+│ ├── deploy_env_vars_dev
+│ ├── deploy_env_vars_staging
+│ └── deploy_env_vars_prod
+├── scripts/
+│ ├── deploy.sh
+│ └── validate-resources.sh
+└── kustomize/
+ ├── base/
│ ├── kustomization.yaml
- │ ├── cm-common-patch.yaml
- │ ├── secret-common-patch.yaml
- │ ├── ingress-patch.yaml
- │ ├── deployment-*-patch.yaml (각 서비스별)
- │ └── secret-*-patch.yaml (Secret 보유 서비스)
- ├── staging/ # 스테이징 환경
- │ └── (dev와 동일한 구조)
- └── prod/ # 운영 환경
- └── (dev와 동일한 구조)
+ │ ├── common/
+ │ │ ├── cm-common.yaml
+ │ │ ├── secret-common.yaml
+ │ │ └── ingress.yaml
+ │ ├── api-gateway/
+ │ ├── user-service/
+ │ ├── bill-service/
+ │ ├── product-service/
+ │ └── kos-mock/
+ └── overlays/
+ ├── dev/
+ ├── staging/
+ └── prod/
```
-## 🔧 Jenkins Pipeline Job 생성
+### 2.2 환경별 설정 차이
-### 1. 새 Pipeline Job 생성
-1. Jenkins 대시보드에서 **New Item** 클릭
-2. **Pipeline** 선택하고 프로젝트명 입력
-3. **OK** 클릭
+| 항목 | dev | staging | prod |
+|------|-----|---------|------|
+| Namespace | phonebill | phonebill-staging | phonebill-prod |
+| Replicas | 1 | 2 | 3 |
+| CPU Requests | 256m | 512m | 1024m |
+| Memory Requests | 256Mi | 512Mi | 1024Mi |
+| CPU Limits | 1024m | 2048m | 4096m |
+| Memory Limits | 1024Mi | 2048Mi | 4096Mi |
+| DDL_AUTO | update | validate | validate |
+| SHOW_SQL | true | false | false |
+| SSL Redirect | false | true | true |
-### 2. Pipeline 설정
-#### General 탭
-- **Build Parameters** 추가:
- ```
- ENVIRONMENT: Choice Parameter
- Choices: dev, staging, prod
- Default: dev
+---
- IMAGE_TAG: String Parameter
- Default: latest
- Description: 이미지 태그 (기본값: latest)
+## 3. Jenkins Pipeline Job 생성
- SKIP_SONARQUBE: String Parameter
- Default: true
- Description: SonarQube 분석 건너뛰기 (true/false)
- ```
+### 3.1 New Item > Pipeline 선택
-#### Pipeline 탭
+### 3.2 Pipeline 설정
```
-Definition: Pipeline script from SCM
SCM: Git
-Repository URL: {Git저장소URL}
+Repository URL: {Git 저장소 URL}
Branch: main (또는 develop)
Script Path: deployment/cicd/Jenkinsfile
```
-## 📊 SonarQube 프로젝트 설정
+### 3.3 Pipeline Parameters 설정
+| 파라미터 | 타입 | 기본값 | 설명 |
+|----------|------|--------|------|
+| ENVIRONMENT | Choice | dev | 배포 환경 (dev/staging/prod) |
+| SKIP_SONARQUBE | String | true | SonarQube 분석 건너뛰기 (true/false) |
-### 1. 각 서비스별 SonarQube 프로젝트 생성
-- phonebill-api-gateway-{환경}
-- phonebill-user-service-{환경}
-- phonebill-bill-service-{환경}
-- phonebill-product-service-{환경}
-- phonebill-kos-mock-{환경}
+---
-### 2. Quality Gate 설정
+## 4. 파이프라인 스테이지
+
+### 4.1 Get Source
+- Git 저장소에서 소스 코드 체크아웃
+- 환경별 설정 파일 로드
+
+### 4.2 Setup Kubernetes
+- Kubernetes 컨텍스트 설정
+- 네임스페이스 생성
+
+### 4.3 Build
+- Gradle을 사용한 빌드 (테스트 제외)
+- `./gradlew build -x test`
+
+### 4.4 SonarQube Analysis & Quality Gate (선택사항)
+- SKIP_SONARQUBE=false일 때만 실행
+- 각 서비스별 테스트 및 코드 품질 분석
+- Quality Gate 통과 확인
+
+### 4.5 Build & Push Images
+- Podman을 사용한 컨테이너 이미지 빌드
+- Docker Hub로 이미지 푸시
+- 이미지 태그: `{환경}-{타임스탬프}`
+
+### 4.6 Update Kustomize & Deploy
+- Kustomize를 사용한 이미지 태그 업데이트
+- Kubernetes 매니페스트 적용
+- 배포 상태 확인
+
+---
+
+## 5. 배포 실행
+
+### 5.1 Jenkins 파이프라인 실행
+1. Jenkins > phonebill > Build with Parameters
+2. ENVIRONMENT 선택 (dev/staging/prod)
+3. SKIP_SONARQUBE 입력 (true 또는 false)
+4. Build 클릭
+
+### 5.2 수동 배포 (스크립트 사용)
+```bash
+# dev 환경 배포
+./deployment/cicd/scripts/deploy.sh dev latest
+
+# staging 환경 배포
+./deployment/cicd/scripts/deploy.sh staging v1.0.0
+
+# prod 환경 배포
+./deployment/cicd/scripts/deploy.sh prod v1.0.0
+```
+
+### 5.3 배포 상태 확인
+```bash
+# Pod 상태 확인
+kubectl get pods -n phonebill
+
+# 서비스 상태 확인
+kubectl get services -n phonebill
+
+# Ingress 상태 확인
+kubectl get ingress -n phonebill
+
+# 특정 Pod 로그 확인
+kubectl logs -f deployment/api-gateway -n phonebill
+```
+
+---
+
+## 6. 롤백
+
+### 6.1 이전 버전으로 롤백
+```bash
+# 특정 리비전으로 롤백
+kubectl rollout undo deployment/{서비스명} -n phonebill --to-revision=2
+
+# 롤백 상태 확인
+kubectl rollout status deployment/{서비스명} -n phonebill
+
+# 롤백 히스토리 확인
+kubectl rollout history deployment/{서비스명} -n phonebill
+```
+
+### 6.2 이미지 태그 기반 롤백
+```bash
+cd deployment/cicd/kustomize/overlays/{환경}
+
+# 이전 안정 버전 이미지 태그로 업데이트
+kustomize edit set image docker.io/hiondal/{서비스명}:{환경}-{이전태그}
+
+# 배포
+kubectl apply -k .
+```
+
+---
+
+## 7. 리소스 검증
+
+### 7.1 검증 스크립트 실행
+```bash
+./deployment/cicd/scripts/validate-resources.sh
+```
+
+### 7.2 Kustomize 빌드 테스트
+```bash
+# Base 빌드 테스트
+kubectl kustomize deployment/cicd/kustomize/base/
+
+# 환경별 빌드 테스트
+kubectl kustomize deployment/cicd/kustomize/overlays/dev/
+kubectl kustomize deployment/cicd/kustomize/overlays/staging/
+kubectl kustomize deployment/cicd/kustomize/overlays/prod/
+```
+
+---
+
+## 8. SonarQube 설정 (선택사항)
+
+### 8.1 Quality Gate 권장 설정
```
Coverage: >= 80%
Duplicated Lines: <= 3%
@@ -184,194 +256,56 @@ Reliability Rating: <= A
Security Rating: <= A
```
-## 🚀 배포 실행 방법
-
-### 1. Jenkins Pipeline 실행
-1. Jenkins > {프로젝트명} > **Build with Parameters** 클릭
-2. 파라미터 설정:
- - **ENVIRONMENT**: dev/staging/prod 선택
- - **IMAGE_TAG**: 이미지 태그 입력 (선택사항)
- - **SKIP_SONARQUBE**: SonarQube 분석 건너뛰려면 "true", 실행하려면 "false"
-3. **Build** 클릭
-
-### 2. 수동 배포 (스크립트 사용)
-```bash
-# 개발 환경 배포
-./deployment/cicd/scripts/deploy.sh dev 20241230120000
-
-# 스테이징 환경 배포
-./deployment/cicd/scripts/deploy.sh staging 20241230120000
-
-# 운영 환경 배포
-./deployment/cicd/scripts/deploy.sh prod 20241230120000
-```
-
-### 3. 배포 상태 확인
-```bash
-# Pod 상태 확인
-kubectl get pods -n phonebill-dg0500
-
-# 서비스 상태 확인
-kubectl get services -n phonebill-dg0500
-
-# Ingress 상태 확인
-kubectl get ingress -n phonebill-dg0500
-
-# 특정 서비스 로그 확인
-kubectl logs -f deployment/user-service -n phonebill-dg0500
-```
-
-## 🔍 리소스 검증
-
-### 리소스 검증 스크립트 실행
-```bash
-# 모든 Kustomize 리소스 검증
-./deployment/cicd/scripts/validate-resources.sh
-```
-
-### 수동 검증 명령어
-```bash
-# Base 검증
-kubectl kustomize deployment/cicd/kustomize/base/
-
-# 환경별 검증
-kubectl kustomize deployment/cicd/kustomize/overlays/dev/
-kubectl kustomize deployment/cicd/kustomize/overlays/staging/
-kubectl kustomize deployment/cicd/kustomize/overlays/prod/
-```
-
-## 🔄 롤백 방법
-
-### 1. Kubernetes 롤백
-```bash
-# 특정 버전으로 롤백
-kubectl rollout undo deployment/{서비스명} -n phonebill-dg0500 --to-revision=2
-
-# 롤백 상태 확인
-kubectl rollout status deployment/{서비스명} -n phonebill-dg0500
-```
-
-### 2. 이미지 태그 기반 롤백
-```bash
-# 이전 안정 버전 이미지 태그로 업데이트
-cd deployment/cicd/kustomize/overlays/{환경}
-kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/{서비스명}:{환경}-{이전태그}
-kubectl apply -k .
-```
-
-## 🎯 파이프라인 단계별 설명
-
-### 1. Get Source
-- Git 저장소에서 소스코드 체크아웃
-- 환경별 설정 파일 로드
-
-### 2. Setup AKS
-- Azure CLI를 통한 AKS 클러스터 연결
-- 네임스페이스 생성 (phonebill-dg0500)
-
-### 3. Build
-- Gradle을 통한 멀티모듈 빌드
-- 테스트는 SonarQube 단계에서 실행
-
-### 4. SonarQube Analysis & Quality Gate
-- 각 서비스별 개별 테스트 실행
-- JaCoCo 코드 커버리지 리포트 생성
-- SonarQube 정적 분석
-- Quality Gate 통과 검증
-
-### 5. Build & Push Images
-- Podman을 통한 컨테이너 이미지 빌드
-- 환경별 태그로 ACR에 푸시
-- 30분 타임아웃 설정
-
-### 6. Update Kustomize & Deploy
-- Kustomize를 통한 이미지 태그 업데이트
-- 환경별 매니페스트 적용
-- 배포 완료까지 대기 (5분 타임아웃)
-
-### 7. Pipeline Complete
-- 파이프라인 완료 상태 로깅
-- Pod 자동 정리 (3초 후 종료)
-
-## ⚠️ 주의사항
-
-### 1. 파드 자동 정리
-- 파이프라인 완료 시 에이전트 파드 자동 삭제
-- `podRetention: never()` 설정으로 즉시 정리
-- 리소스 절약을 위한 필수 설정
-
-### 2. 변수 참조 문법
-- Jenkins Groovy에서는 `${variable}` 사용
-- `\${variable}` 사용 시 "syntax error: bad substitution" 오류 발생
-
-### 3. 쉘 호환성
-- Jenkins 컨테이너 기본 쉘이 `/bin/sh`인 경우
-- Bash 배열 문법 `()` 미지원으로 공백 구분 문자열 사용
-
-### 4. 환경별 설정 차이점
-- **DEV**: SSL 리다이렉트 비활성화, 기본 도메인 사용
-- **STAGING/PROD**: SSL 리다이렉트 활성화, 사용자 정의 도메인, 인증서 설정
-
-## 🛠️ 트러블슈팅
-
-### 1. 빌드 실패
-```bash
-# Gradle 캐시 클리어
-./gradlew clean build
-
-# JDK 버전 확인
-java -version
-```
-
-### 2. 이미지 푸시 실패
-```bash
-# ACR 로그인 확인
-az acr login --name acrdigitalgarage01
-
-# Docker Hub rate limit 확인
-docker info | grep -i rate
-```
-
-### 3. 배포 실패
-```bash
-# 네임스페이스 확인
-kubectl get namespaces
-
-# 리소스 상태 확인
-kubectl describe deployment/{서비스명} -n phonebill-dg0500
-```
-
-### 4. SonarQube 분석 실패
-- SonarQube 서버 연결 상태 확인
-- 토큰 유효성 검증
-- Quality Gate 설정 확인
-
-## 📈 모니터링 및 로그
-
-### 1. Jenkins 빌드 히스토리
-- 각 단계별 실행 시간 추적
-- 실패 단계 및 원인 분석
-
-### 2. 애플리케이션 로그
-```bash
-# 실시간 로그 모니터링
-kubectl logs -f deployment/{서비스명} -n phonebill-dg0500
-
-# 특정 기간 로그 확인
-kubectl logs deployment/{서비스명} -n phonebill-dg0500 --since=1h
-```
-
-### 3. 성능 메트릭
-- Kubernetes 메트릭 서버 활용
-- 각 서비스별 리소스 사용량 모니터링
+### 8.2 SonarQube 프로젝트 생성
+각 서비스별로 다음 형식의 프로젝트 키로 생성:
+- `phonebill-user-service-dev`
+- `phonebill-user-service-staging`
+- `phonebill-user-service-prod`
---
-## 📞 지원
+## 9. 트러블슈팅
-문의사항이나 문제 발생 시:
-1. Jenkins 빌드 로그 확인
-2. Kubernetes 이벤트 확인: `kubectl get events -n phonebill-dg0500`
-3. 리소스 검증 스크립트 실행: `./deployment/cicd/scripts/validate-resources.sh`
+### 9.1 이미지 푸시 실패
+- Docker Hub 인증 정보 확인
+- Rate Limit 확인 (무료 계정 제한)
-**최운영/데옵스**: phonebill Jenkins CI/CD 파이프라인이 성공적으로 구축되었습니다! 🎉
\ No newline at end of file
+### 9.2 배포 실패
+```bash
+# Pod 이벤트 확인
+kubectl describe pod {POD_NAME} -n phonebill
+
+# Pod 로그 확인
+kubectl logs {POD_NAME} -n phonebill
+```
+
+### 9.3 Kustomize 빌드 실패
+- 리소스 파일 존재 여부 확인
+- YAML 문법 검증
+- `kubectl kustomize` 명령으로 디버깅
+
+### 9.4 SonarQube 연결 실패
+- SonarQube 서버 URL 확인
+- 인증 토큰 유효성 확인
+- 네트워크 연결 확인
+
+---
+
+## 10. 체크리스트
+
+### 사전 준비
+- [ ] Jenkins 필수 플러그인 설치 완료
+- [ ] Docker Hub Credentials 등록 완료
+- [ ] SonarQube Token 등록 완료 (선택)
+- [ ] Kubernetes 컨텍스트 설정 완료
+
+### 배포 전
+- [ ] 리소스 검증 스크립트 실행 완료
+- [ ] 환경별 설정 파일 확인 완료
+- [ ] Kustomize 빌드 테스트 완료
+
+### 배포 후
+- [ ] Pod 상태 확인 (Running)
+- [ ] 서비스 엔드포인트 확인
+- [ ] Ingress 접근 테스트
+- [ ] 로그 이상 여부 확인
diff --git a/deployment/cicd/kustomize/base/api-gateway/cm-api-gateway.yaml b/deployment/cicd/kustomize/base/api-gateway/cm-api-gateway.yaml
index aa83a94..ecfe4a3 100644
--- a/deployment/cicd/kustomize/base/api-gateway/cm-api-gateway.yaml
+++ b/deployment/cicd/kustomize/base/api-gateway/cm-api-gateway.yaml
@@ -1,10 +1,14 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-api-gateway
+ name: api-gateway-config
+
+ labels:
+ app: api-gateway
+ app.kubernetes.io/part-of: phonebill
data:
SERVER_PORT: "8080"
- BILL_SERVICE_URL: "http://bill-service"
- PRODUCT_SERVICE_URL: "http://product-service"
- USER_SERVICE_URL: "http://user-service"
- KOS_MOCK_URL: "http://kos-mock"
\ No newline at end of file
+ USER_SERVICE_URL: "http://user-service:8081"
+ BILL_SERVICE_URL: "http://bill-service:8082"
+ PRODUCT_SERVICE_URL: "http://product-service:8083"
+ KOS_MOCK_URL: "http://kos-mock:8084"
diff --git a/deployment/cicd/kustomize/base/api-gateway/deployment.yaml b/deployment/cicd/kustomize/base/api-gateway/deployment.yaml
index ceb7e8c..e6b92be 100644
--- a/deployment/cicd/kustomize/base/api-gateway/deployment.yaml
+++ b/deployment/cicd/kustomize/base/api-gateway/deployment.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
+
+ labels:
+ app: api-gateway
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,46 +16,40 @@ spec:
labels:
app: api-gateway
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: api-gateway
- image: acrdigitalgarage01.azurecr.io/phonebill/api-gateway:latest
+ image: docker.io/hiondal/api-gateway:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-api-gateway
+ name: api-gateway-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /health
- port: 8080
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /health
- port: 8080
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
- path: /health
+ path: /actuator/health/liveness
+ port: 8080
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/cicd/kustomize/base/api-gateway/service.yaml b/deployment/cicd/kustomize/base/api-gateway/service.yaml
index e1f6460..9491512 100644
--- a/deployment/cicd/kustomize/base/api-gateway/service.yaml
+++ b/deployment/cicd/kustomize/base/api-gateway/service.yaml
@@ -2,10 +2,16 @@ apiVersion: v1
kind: Service
metadata:
name: api-gateway
+
+ labels:
+ app: api-gateway
+ app.kubernetes.io/part-of: phonebill
spec:
+ type: ClusterIP
selector:
app: api-gateway
ports:
- - port: 80
+ - name: http
+ port: 8080
targetPort: 8080
- type: ClusterIP
+ protocol: TCP
diff --git a/deployment/cicd/kustomize/base/bill-service/cm-bill-service.yaml b/deployment/cicd/kustomize/base/bill-service/cm-bill-service.yaml
index 9281f36..21486ec 100644
--- a/deployment/cicd/kustomize/base/bill-service/cm-bill-service.yaml
+++ b/deployment/cicd/kustomize/base/bill-service/cm-bill-service.yaml
@@ -1,21 +1,16 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-bill-service
+ name: bill-service-config
+
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
data:
SERVER_PORT: "8082"
- DB_KIND: "postgresql"
+ DB_HOST: "inquiry-postgresql"
DB_PORT: "5432"
- DB_CONNECTION_TIMEOUT: "30000"
- DB_IDLE_TIMEOUT: "600000"
- DB_LEAK_DETECTION: "60000"
- DB_MAX_LIFETIME: "1800000"
- DB_MAX_POOL: "20"
- DB_MIN_IDLE: "5"
- KOS_BASE_URL: "http://kos-mock"
+ DB_NAME: "inquirydb"
REDIS_DATABASE: "1"
- REDIS_MAX_ACTIVE: "8"
- REDIS_MAX_IDLE: "8"
- REDIS_MAX_WAIT: "-1"
- REDIS_MIN_IDLE: "0"
- REDIS_TIMEOUT: "2000"
\ No newline at end of file
+ KOS_BASE_URL: "http://kos-mock:8084"
+ DDL_AUTO: "update"
diff --git a/deployment/cicd/kustomize/base/bill-service/deployment.yaml b/deployment/cicd/kustomize/base/bill-service/deployment.yaml
index 78a42dd..53e2f71 100644
--- a/deployment/cicd/kustomize/base/bill-service/deployment.yaml
+++ b/deployment/cicd/kustomize/base/bill-service/deployment.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: bill-service
+
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,48 +16,42 @@ spec:
labels:
app: bill-service
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: bill-service
- image: acrdigitalgarage01.azurecr.io/phonebill/bill-service:latest
+ image: docker.io/hiondal/bill-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8082
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-bill-service
+ name: bill-service-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
- secretRef:
- name: secret-bill-service
+ name: bill-service-db-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8082
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8082
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8082
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8082
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/cicd/kustomize/base/bill-service/secret-bill-service.yaml b/deployment/cicd/kustomize/base/bill-service/secret-bill-service.yaml
index caaa7cf..ebe83d7 100644
--- a/deployment/cicd/kustomize/base/bill-service/secret-bill-service.yaml
+++ b/deployment/cicd/kustomize/base/bill-service/secret-bill-service.yaml
@@ -1,10 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-bill-service
+ name: bill-service-db-secret
+
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "bill-inquiry-postgres-dev-postgresql"
- DB_NAME: "bill_inquiry_db"
- DB_USERNAME: "bill_inquiry_user"
- DB_PASSWORD: "BillUser2025@"
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/base/bill-service/service.yaml b/deployment/cicd/kustomize/base/bill-service/service.yaml
index 1e6373b..e491d02 100644
--- a/deployment/cicd/kustomize/base/bill-service/service.yaml
+++ b/deployment/cicd/kustomize/base/bill-service/service.yaml
@@ -2,10 +2,16 @@ apiVersion: v1
kind: Service
metadata:
name: bill-service
+
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
spec:
+ type: ClusterIP
selector:
app: bill-service
ports:
- - port: 80
+ - name: http
+ port: 8082
targetPort: 8082
- type: ClusterIP
\ No newline at end of file
+ protocol: TCP
diff --git a/deployment/cicd/kustomize/base/common/cm-common.yaml b/deployment/cicd/kustomize/base/common/cm-common.yaml
index 3c16172..87fe3f6 100644
--- a/deployment/cicd/kustomize/base/common/cm-common.yaml
+++ b/deployment/cicd/kustomize/base/common/cm-common.yaml
@@ -1,11 +1,14 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-common
+ name: phonebill-common-config
+
+ labels:
+ app.kubernetes.io/part-of: phonebill
data:
- CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill-dg0500.20.214.196.128.nip.io"
- JWT_ACCESS_TOKEN_VALIDITY: "18000000"
- JWT_REFRESH_TOKEN_VALIDITY: "86400000"
+ SPRING_PROFILES_ACTIVE: "prod"
+ REDIS_HOST: "cache-redis-master"
REDIS_PORT: "6379"
- SPRING_PROFILES_ACTIVE: "dev"
- DDL_AUTO: "update"
\ No newline at end of file
+ CORS_ALLOWED_ORIGINS: "http://localhost:3000,http://phonebill.72.155.72.236.nip.io"
+ SHOW_SQL: "false"
+ DDL_AUTO: "none"
diff --git a/deployment/cicd/kustomize/base/common/ingress.yaml b/deployment/cicd/kustomize/base/common/ingress.yaml
index da97115..9424e50 100644
--- a/deployment/cicd/kustomize/base/common/ingress.yaml
+++ b/deployment/cicd/kustomize/base/common/ingress.yaml
@@ -1,49 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: phonebill
+ name: phonebill-ingress
+
+ labels:
+ app.kubernetes.io/part-of: phonebill
annotations:
- kubernetes.io/ingress.class: nginx
- nginx.ingress.kubernetes.io/ssl-redirect: "false"
+ nginx.ingress.kubernetes.io/proxy-body-size: "50m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
spec:
ingressClassName: nginx
rules:
- - host: phonebill-dg0500-api.20.214.196.128.nip.io
+ - host: phonebill-api.72.155.72.236.nip.io
http:
paths:
- - path: /api/v1/auth
+ - path: /
pathType: Prefix
backend:
service:
- name: user-service
+ name: api-gateway
port:
- number: 80
- - path: /api/v1/users
- pathType: Prefix
- backend:
- service:
- name: user-service
- port:
- number: 80
- - path: /api/v1/bills
- pathType: Prefix
- backend:
- service:
- name: bill-service
- port:
- number: 80
- - path: /api/v1/products
- pathType: Prefix
- backend:
- service:
- name: product-service
- port:
- number: 80
- - path: /api/v1/kos
- pathType: Prefix
- backend:
- service:
- name: kos-mock
- port:
- number: 80
-
+ number: 8080
diff --git a/deployment/cicd/kustomize/base/common/secret-common.yaml b/deployment/cicd/kustomize/base/common/secret-common.yaml
index 53795ab..a23a737 100644
--- a/deployment/cicd/kustomize/base/common/secret-common.yaml
+++ b/deployment/cicd/kustomize/base/common/secret-common.yaml
@@ -1,9 +1,13 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-common
+ name: phonebill-common-secret
+
+ labels:
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ=="
- REDIS_HOST: "redis-cache-dev-master"
- REDIS_PASSWORD: "Redis2025Dev@"
\ No newline at end of file
+ # JWT Secret (최소 256비트 이상, HS256 알고리즘용)
+ JWT_SECRET: "EK1ZV7vROOXREXbYe/BCISdQq0Yklk9JtoA2v88ux1DBDc0bDGiRRxHeDSb7GHkDP9IUYHMVsBi4/1rS4OhfRg=="
+ # Redis 비밀번호 (비밀번호 없는 경우 빈 값)
+ REDIS_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/base/common/secret-imagepull.yaml b/deployment/cicd/kustomize/base/common/secret-imagepull.yaml
deleted file mode 100644
index 6bd576e..0000000
--- a/deployment/cicd/kustomize/base/common/secret-imagepull.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: phonebill
-type: kubernetes.io/dockerconfigjson
-stringData:
- .dockerconfigjson: |
- {
- "auths": {
- "acrdigitalgarage01.azurecr.io": {
- "username": "acrdigitalgarage01",
- "password": "+OY+rmOagorjWvQe/tTk6oqvnZI8SmNbY/Y2o5EDcY+ACRDCDbYk",
- "auth": "YWNyZGlnaXRhbGdhcmFnZTAxOitPWStybU9hZ29yald2UWUvdFRrNm9xdm5aSThTbU5iWS9ZMm81RURjWStBQ1JEQ0RiWWs="
- }
- }
- }
\ No newline at end of file
diff --git a/deployment/cicd/kustomize/base/kos-mock/cm-kos-mock.yaml b/deployment/cicd/kustomize/base/kos-mock/cm-kos-mock.yaml
index 3e55476..fc3f37a 100644
--- a/deployment/cicd/kustomize/base/kos-mock/cm-kos-mock.yaml
+++ b/deployment/cicd/kustomize/base/kos-mock/cm-kos-mock.yaml
@@ -1,6 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-kos-mock
+ name: kos-mock-config
+
+ labels:
+ app: kos-mock
+ app.kubernetes.io/part-of: phonebill
data:
- SERVER_PORT: "8084"
\ No newline at end of file
+ SERVER_PORT: "8084"
diff --git a/deployment/cicd/kustomize/base/kos-mock/deployment.yaml b/deployment/cicd/kustomize/base/kos-mock/deployment.yaml
index bd588f4..6912cfd 100644
--- a/deployment/cicd/kustomize/base/kos-mock/deployment.yaml
+++ b/deployment/cicd/kustomize/base/kos-mock/deployment.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: kos-mock
+
+ labels:
+ app: kos-mock
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,46 +16,40 @@ spec:
labels:
app: kos-mock
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: kos-mock
- image: acrdigitalgarage01.azurecr.io/phonebill/kos-mock:latest
+ image: docker.io/hiondal/kos-mock:latest
imagePullPolicy: Always
ports:
- containerPort: 8084
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-kos-mock
+ name: kos-mock-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8084
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8084
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8084
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8084
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/cicd/kustomize/base/kos-mock/service.yaml b/deployment/cicd/kustomize/base/kos-mock/service.yaml
index fdb5336..16d71ab 100644
--- a/deployment/cicd/kustomize/base/kos-mock/service.yaml
+++ b/deployment/cicd/kustomize/base/kos-mock/service.yaml
@@ -2,10 +2,16 @@ apiVersion: v1
kind: Service
metadata:
name: kos-mock
+
+ labels:
+ app: kos-mock
+ app.kubernetes.io/part-of: phonebill
spec:
+ type: ClusterIP
selector:
app: kos-mock
ports:
- - port: 80
+ - name: http
+ port: 8084
targetPort: 8084
- type: ClusterIP
\ No newline at end of file
+ protocol: TCP
diff --git a/deployment/cicd/kustomize/base/kustomization.yaml b/deployment/cicd/kustomize/base/kustomization.yaml
index 0da6c87..67327a9 100644
--- a/deployment/cicd/kustomize/base/kustomization.yaml
+++ b/deployment/cicd/kustomize/base/kustomization.yaml
@@ -8,7 +8,6 @@ resources:
# Common resources
- common/cm-common.yaml
- common/secret-common.yaml
- - common/secret-imagepull.yaml
- common/ingress.yaml
# api-gateway
@@ -44,13 +43,13 @@ commonLabels:
version: v1
images:
- - name: acrdigitalgarage01.azurecr.io/phonebill/api-gateway
+ - name: docker.io/hiondal/api-gateway
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/user-service
+ - name: docker.io/hiondal/user-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/bill-service
+ - name: docker.io/hiondal/bill-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/product-service
+ - name: docker.io/hiondal/product-service
+ newTag: latest
+ - name: docker.io/hiondal/kos-mock
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/kos-mock
- newTag: latest
\ No newline at end of file
diff --git a/deployment/cicd/kustomize/base/product-service/cm-product-service.yaml b/deployment/cicd/kustomize/base/product-service/cm-product-service.yaml
index 5a3893d..2c6db72 100644
--- a/deployment/cicd/kustomize/base/product-service/cm-product-service.yaml
+++ b/deployment/cicd/kustomize/base/product-service/cm-product-service.yaml
@@ -1,10 +1,16 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-product-service
+ name: product-service-config
+
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
data:
SERVER_PORT: "8083"
- DB_KIND: "postgresql"
+ DB_HOST: "change-postgresql"
DB_PORT: "5432"
- KOS_BASE_URL: "http://kos-mock"
- REDIS_DATABASE: "2"
\ No newline at end of file
+ DB_NAME: "changedb"
+ REDIS_DATABASE: "2"
+ KOS_BASE_URL: "http://kos-mock:8084"
+ DDL_AUTO: "update"
diff --git a/deployment/cicd/kustomize/base/product-service/deployment.yaml b/deployment/cicd/kustomize/base/product-service/deployment.yaml
index 0b463a3..b4ff532 100644
--- a/deployment/cicd/kustomize/base/product-service/deployment.yaml
+++ b/deployment/cicd/kustomize/base/product-service/deployment.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
+
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,48 +16,42 @@ spec:
labels:
app: product-service
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: product-service
- image: acrdigitalgarage01.azurecr.io/phonebill/product-service:latest
+ image: docker.io/hiondal/product-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8083
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-product-service
+ name: product-service-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
- secretRef:
- name: secret-product-service
+ name: product-service-db-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8083
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8083
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8083
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8083
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/cicd/kustomize/base/product-service/secret-product-service.yaml b/deployment/cicd/kustomize/base/product-service/secret-product-service.yaml
index e773ec9..e21ad4b 100644
--- a/deployment/cicd/kustomize/base/product-service/secret-product-service.yaml
+++ b/deployment/cicd/kustomize/base/product-service/secret-product-service.yaml
@@ -1,10 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-product-service
+ name: product-service-db-secret
+
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "product-change-postgres-dev-postgresql"
- DB_NAME: "product_change_db"
- DB_USERNAME: "product_change_user"
- DB_PASSWORD: "ProductUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/base/product-service/service.yaml b/deployment/cicd/kustomize/base/product-service/service.yaml
index b784a5d..4a77c8b 100644
--- a/deployment/cicd/kustomize/base/product-service/service.yaml
+++ b/deployment/cicd/kustomize/base/product-service/service.yaml
@@ -2,10 +2,16 @@ apiVersion: v1
kind: Service
metadata:
name: product-service
+
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
spec:
+ type: ClusterIP
selector:
app: product-service
ports:
- - port: 80
+ - name: http
+ port: 8083
targetPort: 8083
- type: ClusterIP
\ No newline at end of file
+ protocol: TCP
diff --git a/deployment/cicd/kustomize/base/user-service/cm-user-service.yaml b/deployment/cicd/kustomize/base/user-service/cm-user-service.yaml
index 4031913..ac4b8e4 100644
--- a/deployment/cicd/kustomize/base/user-service/cm-user-service.yaml
+++ b/deployment/cicd/kustomize/base/user-service/cm-user-service.yaml
@@ -1,11 +1,15 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-user-service
+ name: user-service-config
+
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
data:
SERVER_PORT: "8081"
- DB_KIND: "postgresql"
+ DB_HOST: "auth-postgresql"
DB_PORT: "5432"
- DDL_AUTO: "update"
+ DB_NAME: "authdb"
REDIS_DATABASE: "0"
- SHOW_SQL: "true"
\ No newline at end of file
+ DDL_AUTO: "update"
diff --git a/deployment/cicd/kustomize/base/user-service/deployment.yaml b/deployment/cicd/kustomize/base/user-service/deployment.yaml
index 2dbd2d4..7f39e0b 100644
--- a/deployment/cicd/kustomize/base/user-service/deployment.yaml
+++ b/deployment/cicd/kustomize/base/user-service/deployment.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
+
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,48 +16,42 @@ spec:
labels:
app: user-service
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: user-service
- image: acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
+ image: docker.io/hiondal/user-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8081
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-user-service
+ name: user-service-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
- secretRef:
- name: secret-user-service
+ name: user-service-db-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8081
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8081
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8081
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8081
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/cicd/kustomize/base/user-service/secret-user-service.yaml b/deployment/cicd/kustomize/base/user-service/secret-user-service.yaml
index 8424423..a75e1f9 100644
--- a/deployment/cicd/kustomize/base/user-service/secret-user-service.yaml
+++ b/deployment/cicd/kustomize/base/user-service/secret-user-service.yaml
@@ -1,10 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-user-service
+ name: user-service-db-secret
+
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "auth-postgres-dev-postgresql"
- DB_NAME: "phonebill_auth"
- DB_USERNAME: "auth_user"
- DB_PASSWORD: "AuthUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/base/user-service/service.yaml b/deployment/cicd/kustomize/base/user-service/service.yaml
index c9fb9cf..029298f 100644
--- a/deployment/cicd/kustomize/base/user-service/service.yaml
+++ b/deployment/cicd/kustomize/base/user-service/service.yaml
@@ -2,10 +2,16 @@ apiVersion: v1
kind: Service
metadata:
name: user-service
+
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
spec:
+ type: ClusterIP
selector:
app: user-service
ports:
- - port: 80
+ - name: http
+ port: 8081
targetPort: 8081
- type: ClusterIP
\ No newline at end of file
+ protocol: TCP
diff --git a/deployment/cicd/kustomize/overlays/dev/cm-common-patch.yaml b/deployment/cicd/kustomize/overlays/dev/cm-common-patch.yaml
index 3c16172..6336378 100644
--- a/deployment/cicd/kustomize/overlays/dev/cm-common-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/cm-common-patch.yaml
@@ -1,11 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-common
+ name: phonebill-common-config
+ labels:
+ app.kubernetes.io/part-of: phonebill
data:
- CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill-dg0500.20.214.196.128.nip.io"
- JWT_ACCESS_TOKEN_VALIDITY: "18000000"
- JWT_REFRESH_TOKEN_VALIDITY: "86400000"
- REDIS_PORT: "6379"
SPRING_PROFILES_ACTIVE: "dev"
- DDL_AUTO: "update"
\ No newline at end of file
+ REDIS_HOST: "cache-redis-master"
+ REDIS_PORT: "6379"
+ CORS_ALLOWED_ORIGINS: "http://localhost:3000,http://phonebill.72.155.72.236.nip.io"
+ SHOW_SQL: "true"
+ DDL_AUTO: "update"
diff --git a/deployment/cicd/kustomize/overlays/dev/deployment-api-gateway-patch.yaml b/deployment/cicd/kustomize/overlays/dev/deployment-api-gateway-patch.yaml
index c5278b1..a9eb12e 100644
--- a/deployment/cicd/kustomize/overlays/dev/deployment-api-gateway-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/deployment-api-gateway-patch.yaml
@@ -14,4 +14,4 @@ spec:
memory: "256Mi"
limits:
cpu: "1024m"
- memory: "1024Mi"
\ No newline at end of file
+ memory: "1024Mi"
diff --git a/deployment/cicd/kustomize/overlays/dev/deployment-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/deployment-bill-service-patch.yaml
index c67ce77..c17f70a 100644
--- a/deployment/cicd/kustomize/overlays/dev/deployment-bill-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/deployment-bill-service-patch.yaml
@@ -14,4 +14,4 @@ spec:
memory: "256Mi"
limits:
cpu: "1024m"
- memory: "1024Mi"
\ No newline at end of file
+ memory: "1024Mi"
diff --git a/deployment/cicd/kustomize/overlays/dev/deployment-kos-mock-patch.yaml b/deployment/cicd/kustomize/overlays/dev/deployment-kos-mock-patch.yaml
index 21a137c..2c36df1 100644
--- a/deployment/cicd/kustomize/overlays/dev/deployment-kos-mock-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/deployment-kos-mock-patch.yaml
@@ -14,4 +14,4 @@ spec:
memory: "256Mi"
limits:
cpu: "1024m"
- memory: "1024Mi"
\ No newline at end of file
+ memory: "1024Mi"
diff --git a/deployment/cicd/kustomize/overlays/dev/deployment-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/deployment-product-service-patch.yaml
index 7290636..be48b62 100644
--- a/deployment/cicd/kustomize/overlays/dev/deployment-product-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/deployment-product-service-patch.yaml
@@ -14,4 +14,4 @@ spec:
memory: "256Mi"
limits:
cpu: "1024m"
- memory: "1024Mi"
\ No newline at end of file
+ memory: "1024Mi"
diff --git a/deployment/cicd/kustomize/overlays/dev/deployment-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/deployment-user-service-patch.yaml
index c2fa8d4..903f0ad 100644
--- a/deployment/cicd/kustomize/overlays/dev/deployment-user-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/deployment-user-service-patch.yaml
@@ -14,4 +14,4 @@ spec:
memory: "256Mi"
limits:
cpu: "1024m"
- memory: "1024Mi"
\ No newline at end of file
+ memory: "1024Mi"
diff --git a/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml b/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml
index 8fb360e..30cd224 100644
--- a/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/ingress-patch.yaml
@@ -1,48 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: phonebill
+ name: phonebill-ingress
+ labels:
+ app.kubernetes.io/part-of: phonebill
annotations:
- kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/proxy-body-size: "50m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: nginx
rules:
- - host: phonebill-dg0500-api.20.214.196.128.nip.io
+ - host: phonebill-api.72.155.72.236.nip.io
http:
paths:
- - path: /api/v1/auth
+ - path: /
pathType: Prefix
backend:
service:
- name: user-service
+ name: api-gateway
port:
- number: 80
- - path: /api/v1/users
- pathType: Prefix
- backend:
- service:
- name: user-service
- port:
- number: 80
- - path: /api/v1/bills
- pathType: Prefix
- backend:
- service:
- name: bill-service
- port:
- number: 80
- - path: /api/v1/products
- pathType: Prefix
- backend:
- service:
- name: product-service
- port:
- number: 80
- - path: /api/v1/kos
- pathType: Prefix
- backend:
- service:
- name: kos-mock
- port:
- number: 80
\ No newline at end of file
+ number: 8080
diff --git a/deployment/cicd/kustomize/overlays/dev/kustomization.yaml b/deployment/cicd/kustomize/overlays/dev/kustomization.yaml
index 974e023..7e7e5d0 100644
--- a/deployment/cicd/kustomize/overlays/dev/kustomization.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/kustomization.yaml
@@ -1,16 +1,27 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
-namespace: phonebill-dg0500
+namespace: phonebill
resources:
- ../../base
patches:
+ # Common patches
- path: cm-common-patch.yaml
target:
kind: ConfigMap
- name: cm-common
+ name: phonebill-common-config
+ - path: secret-common-patch.yaml
+ target:
+ kind: Secret
+ name: phonebill-common-secret
+ - path: ingress-patch.yaml
+ target:
+ kind: Ingress
+ name: phonebill-ingress
+
+ # Deployment patches
- path: deployment-api-gateway-patch.yaml
target:
kind: Deployment
@@ -31,35 +42,29 @@ patches:
target:
kind: Deployment
name: kos-mock
- - path: ingress-patch.yaml
- target:
- kind: Ingress
- name: phonebill
- - path: secret-common-patch.yaml
- target:
- kind: Secret
- name: secret-common
+
+ # Service Secret patches
- path: secret-user-service-patch.yaml
target:
kind: Secret
- name: secret-user-service
+ name: user-service-db-secret
- path: secret-bill-service-patch.yaml
target:
kind: Secret
- name: secret-bill-service
+ name: bill-service-db-secret
- path: secret-product-service-patch.yaml
target:
kind: Secret
- name: secret-product-service
+ name: product-service-db-secret
images:
- - name: acrdigitalgarage01.azurecr.io/phonebill/api-gateway
+ - name: docker.io/hiondal/api-gateway
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/user-service
+ - name: docker.io/hiondal/user-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/bill-service
+ - name: docker.io/hiondal/bill-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/product-service
+ - name: docker.io/hiondal/product-service
+ newTag: latest
+ - name: docker.io/hiondal/kos-mock
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/kos-mock
- newTag: latest
\ No newline at end of file
diff --git a/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml
index caaa7cf..b69a9d5 100644
--- a/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/secret-bill-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-bill-service
+ name: bill-service-db-secret
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "bill-inquiry-postgres-dev-postgresql"
- DB_NAME: "bill_inquiry_db"
- DB_USERNAME: "bill_inquiry_user"
- DB_PASSWORD: "BillUser2025@"
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml
index 53795ab..20bf82c 100644
--- a/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/secret-common-patch.yaml
@@ -1,9 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-common
+ name: phonebill-common-secret
+ labels:
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ=="
- REDIS_HOST: "redis-cache-dev-master"
- REDIS_PASSWORD: "Redis2025Dev@"
\ No newline at end of file
+ JWT_SECRET: "EK1ZV7vROOXREXbYe/BCISdQq0Yklk9JtoA2v88ux1DBDc0bDGiRRxHeDSb7GHkDP9IUYHMVsBi4/1rS4OhfRg=="
+ REDIS_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml
index e773ec9..3ecf261 100644
--- a/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/secret-product-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-product-service
+ name: product-service-db-secret
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "product-change-postgres-dev-postgresql"
- DB_NAME: "product_change_db"
- DB_USERNAME: "product_change_user"
- DB_PASSWORD: "ProductUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml
index 8424423..f0f984c 100644
--- a/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/dev/secret-user-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-user-service
+ name: user-service-db-secret
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "auth-postgres-dev-postgresql"
- DB_NAME: "phonebill_auth"
- DB_USERNAME: "auth_user"
- DB_PASSWORD: "AuthUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/cicd/kustomize/overlays/prod/cm-common-patch.yaml b/deployment/cicd/kustomize/overlays/prod/cm-common-patch.yaml
index eea116d..316f727 100644
--- a/deployment/cicd/kustomize/overlays/prod/cm-common-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/cm-common-patch.yaml
@@ -1,11 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-common
+ name: phonebill-common-config
+ labels:
+ app.kubernetes.io/part-of: phonebill
data:
- CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill-dg0500.20.214.196.128.nip.io"
- JWT_ACCESS_TOKEN_VALIDITY: "3600000"
- JWT_REFRESH_TOKEN_VALIDITY: "43200000"
- REDIS_PORT: "6379"
SPRING_PROFILES_ACTIVE: "prod"
- DDL_AUTO: "validate"
\ No newline at end of file
+ REDIS_HOST: "cache-redis-master"
+ REDIS_PORT: "6379"
+ CORS_ALLOWED_ORIGINS: "https://phonebill.example.com"
+ SHOW_SQL: "false"
+ DDL_AUTO: "validate"
diff --git a/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml b/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml
index 95ee1a4..551c926 100644
--- a/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/ingress-patch.yaml
@@ -1,9 +1,14 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: phonebill
+ name: phonebill-ingress
+ labels:
+ app.kubernetes.io/part-of: phonebill
annotations:
- kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/proxy-body-size: "50m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
@@ -16,38 +21,10 @@ spec:
- host: phonebill.example.com
http:
paths:
- - path: /api/v1/auth
+ - path: /
pathType: Prefix
backend:
service:
- name: user-service
+ name: api-gateway
port:
- number: 80
- - path: /api/v1/users
- pathType: Prefix
- backend:
- service:
- name: user-service
- port:
- number: 80
- - path: /api/v1/bills
- pathType: Prefix
- backend:
- service:
- name: bill-service
- port:
- number: 80
- - path: /api/v1/products
- pathType: Prefix
- backend:
- service:
- name: product-service
- port:
- number: 80
- - path: /api/v1/kos
- pathType: Prefix
- backend:
- service:
- name: kos-mock
- port:
- number: 80
\ No newline at end of file
+ number: 8080
diff --git a/deployment/cicd/kustomize/overlays/prod/kustomization.yaml b/deployment/cicd/kustomize/overlays/prod/kustomization.yaml
index 974e023..28b0863 100644
--- a/deployment/cicd/kustomize/overlays/prod/kustomization.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/kustomization.yaml
@@ -1,16 +1,27 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
-namespace: phonebill-dg0500
+namespace: phonebill-prod
resources:
- ../../base
patches:
+ # Common patches
- path: cm-common-patch.yaml
target:
kind: ConfigMap
- name: cm-common
+ name: phonebill-common-config
+ - path: secret-common-patch.yaml
+ target:
+ kind: Secret
+ name: phonebill-common-secret
+ - path: ingress-patch.yaml
+ target:
+ kind: Ingress
+ name: phonebill-ingress
+
+ # Deployment patches
- path: deployment-api-gateway-patch.yaml
target:
kind: Deployment
@@ -31,35 +42,29 @@ patches:
target:
kind: Deployment
name: kos-mock
- - path: ingress-patch.yaml
- target:
- kind: Ingress
- name: phonebill
- - path: secret-common-patch.yaml
- target:
- kind: Secret
- name: secret-common
+
+ # Service Secret patches
- path: secret-user-service-patch.yaml
target:
kind: Secret
- name: secret-user-service
+ name: user-service-db-secret
- path: secret-bill-service-patch.yaml
target:
kind: Secret
- name: secret-bill-service
+ name: bill-service-db-secret
- path: secret-product-service-patch.yaml
target:
kind: Secret
- name: secret-product-service
+ name: product-service-db-secret
images:
- - name: acrdigitalgarage01.azurecr.io/phonebill/api-gateway
+ - name: docker.io/hiondal/api-gateway
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/user-service
+ - name: docker.io/hiondal/user-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/bill-service
+ - name: docker.io/hiondal/bill-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/product-service
+ - name: docker.io/hiondal/product-service
+ newTag: latest
+ - name: docker.io/hiondal/kos-mock
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/kos-mock
- newTag: latest
\ No newline at end of file
diff --git a/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml
index caaa7cf..3d64645 100644
--- a/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/secret-bill-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-bill-service
+ name: bill-service-db-secret
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "bill-inquiry-postgres-dev-postgresql"
- DB_NAME: "bill_inquiry_db"
- DB_USERNAME: "bill_inquiry_user"
- DB_PASSWORD: "BillUser2025@"
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "PROD_DB_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml
index 53795ab..c2e7edb 100644
--- a/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/secret-common-patch.yaml
@@ -1,9 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-common
+ name: phonebill-common-secret
+ labels:
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ=="
- REDIS_HOST: "redis-cache-dev-master"
- REDIS_PASSWORD: "Redis2025Dev@"
\ No newline at end of file
+ JWT_SECRET: "PROD_JWT_SECRET_REPLACE_WITH_SECURE_VALUE"
+ REDIS_PASSWORD: "PROD_REDIS_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml
index e773ec9..d571924 100644
--- a/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/secret-product-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-product-service
+ name: product-service-db-secret
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "product-change-postgres-dev-postgresql"
- DB_NAME: "product_change_db"
- DB_USERNAME: "product_change_user"
- DB_PASSWORD: "ProductUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "PROD_DB_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml
index 8424423..2cf1d3e 100644
--- a/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/prod/secret-user-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-user-service
+ name: user-service-db-secret
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "auth-postgres-dev-postgresql"
- DB_NAME: "phonebill_auth"
- DB_USERNAME: "auth_user"
- DB_PASSWORD: "AuthUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "PROD_DB_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/staging/cm-common-patch.yaml b/deployment/cicd/kustomize/overlays/staging/cm-common-patch.yaml
index d3604e0..97e1bda 100644
--- a/deployment/cicd/kustomize/overlays/staging/cm-common-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/cm-common-patch.yaml
@@ -1,11 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: cm-common
+ name: phonebill-common-config
+ labels:
+ app.kubernetes.io/part-of: phonebill
data:
- CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill-dg0500.20.214.196.128.nip.io"
- JWT_ACCESS_TOKEN_VALIDITY: "18000000"
- JWT_REFRESH_TOKEN_VALIDITY: "86400000"
- REDIS_PORT: "6379"
SPRING_PROFILES_ACTIVE: "staging"
- DDL_AUTO: "validate"
\ No newline at end of file
+ REDIS_HOST: "cache-redis-master"
+ REDIS_PORT: "6379"
+ CORS_ALLOWED_ORIGINS: "https://phonebill-staging.example.com"
+ SHOW_SQL: "false"
+ DDL_AUTO: "validate"
diff --git a/deployment/cicd/kustomize/overlays/staging/deployment-api-gateway-patch.yaml b/deployment/cicd/kustomize/overlays/staging/deployment-api-gateway-patch.yaml
index b8f0f64..dac2bcf 100644
--- a/deployment/cicd/kustomize/overlays/staging/deployment-api-gateway-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/deployment-api-gateway-patch.yaml
@@ -14,4 +14,4 @@ spec:
memory: "512Mi"
limits:
cpu: "2048m"
- memory: "2048Mi"
\ No newline at end of file
+ memory: "2048Mi"
diff --git a/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml b/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml
index ba8d07b..7cc3bf5 100644
--- a/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/ingress-patch.yaml
@@ -1,11 +1,16 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: phonebill
+ name: phonebill-ingress
+ labels:
+ app.kubernetes.io/part-of: phonebill
annotations:
- kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/proxy-body-size: "50m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
- cert-manager.io/cluster-issuer: "letsencrypt-prod"
+ cert-manager.io/cluster-issuer: "letsencrypt-staging"
spec:
ingressClassName: nginx
tls:
@@ -16,38 +21,10 @@ spec:
- host: phonebill-staging.example.com
http:
paths:
- - path: /api/v1/auth
+ - path: /
pathType: Prefix
backend:
service:
- name: user-service
+ name: api-gateway
port:
- number: 80
- - path: /api/v1/users
- pathType: Prefix
- backend:
- service:
- name: user-service
- port:
- number: 80
- - path: /api/v1/bills
- pathType: Prefix
- backend:
- service:
- name: bill-service
- port:
- number: 80
- - path: /api/v1/products
- pathType: Prefix
- backend:
- service:
- name: product-service
- port:
- number: 80
- - path: /api/v1/kos
- pathType: Prefix
- backend:
- service:
- name: kos-mock
- port:
- number: 80
\ No newline at end of file
+ number: 8080
diff --git a/deployment/cicd/kustomize/overlays/staging/kustomization.yaml b/deployment/cicd/kustomize/overlays/staging/kustomization.yaml
index 974e023..bb8ae59 100644
--- a/deployment/cicd/kustomize/overlays/staging/kustomization.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/kustomization.yaml
@@ -1,16 +1,27 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
-namespace: phonebill-dg0500
+namespace: phonebill-staging
resources:
- ../../base
patches:
+ # Common patches
- path: cm-common-patch.yaml
target:
kind: ConfigMap
- name: cm-common
+ name: phonebill-common-config
+ - path: secret-common-patch.yaml
+ target:
+ kind: Secret
+ name: phonebill-common-secret
+ - path: ingress-patch.yaml
+ target:
+ kind: Ingress
+ name: phonebill-ingress
+
+ # Deployment patches
- path: deployment-api-gateway-patch.yaml
target:
kind: Deployment
@@ -31,35 +42,29 @@ patches:
target:
kind: Deployment
name: kos-mock
- - path: ingress-patch.yaml
- target:
- kind: Ingress
- name: phonebill
- - path: secret-common-patch.yaml
- target:
- kind: Secret
- name: secret-common
+
+ # Service Secret patches
- path: secret-user-service-patch.yaml
target:
kind: Secret
- name: secret-user-service
+ name: user-service-db-secret
- path: secret-bill-service-patch.yaml
target:
kind: Secret
- name: secret-bill-service
+ name: bill-service-db-secret
- path: secret-product-service-patch.yaml
target:
kind: Secret
- name: secret-product-service
+ name: product-service-db-secret
images:
- - name: acrdigitalgarage01.azurecr.io/phonebill/api-gateway
+ - name: docker.io/hiondal/api-gateway
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/user-service
+ - name: docker.io/hiondal/user-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/bill-service
+ - name: docker.io/hiondal/bill-service
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/product-service
+ - name: docker.io/hiondal/product-service
+ newTag: latest
+ - name: docker.io/hiondal/kos-mock
newTag: latest
- - name: acrdigitalgarage01.azurecr.io/phonebill/kos-mock
- newTag: latest
\ No newline at end of file
diff --git a/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml
index caaa7cf..265eb46 100644
--- a/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/secret-bill-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-bill-service
+ name: bill-service-db-secret
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "bill-inquiry-postgres-dev-postgresql"
- DB_NAME: "bill_inquiry_db"
- DB_USERNAME: "bill_inquiry_user"
- DB_PASSWORD: "BillUser2025@"
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "STAGING_DB_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml
index 53795ab..9143b04 100644
--- a/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/secret-common-patch.yaml
@@ -1,9 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-common
+ name: phonebill-common-secret
+ labels:
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ=="
- REDIS_HOST: "redis-cache-dev-master"
- REDIS_PASSWORD: "Redis2025Dev@"
\ No newline at end of file
+ JWT_SECRET: "STAGING_JWT_SECRET_REPLACE_WITH_SECURE_VALUE"
+ REDIS_PASSWORD: "STAGING_REDIS_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml
index e773ec9..c4a5141 100644
--- a/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/secret-product-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-product-service
+ name: product-service-db-secret
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "product-change-postgres-dev-postgresql"
- DB_NAME: "product_change_db"
- DB_USERNAME: "product_change_user"
- DB_PASSWORD: "ProductUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "STAGING_DB_PASSWORD"
diff --git a/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml b/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml
index 8424423..8d3de11 100644
--- a/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml
+++ b/deployment/cicd/kustomize/overlays/staging/secret-user-service-patch.yaml
@@ -1,10 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
- name: secret-user-service
+ name: user-service-db-secret
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
type: Opaque
stringData:
- DB_HOST: "auth-postgres-dev-postgresql"
- DB_NAME: "phonebill_auth"
- DB_USERNAME: "auth_user"
- DB_PASSWORD: "AuthUser2025@"
\ No newline at end of file
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "STAGING_DB_PASSWORD"
diff --git a/deployment/cicd/scripts/deploy.sh b/deployment/cicd/scripts/deploy.sh
index 14817da..c5863de 100755
--- a/deployment/cicd/scripts/deploy.sh
+++ b/deployment/cicd/scripts/deploy.sh
@@ -4,40 +4,35 @@ set -e
ENVIRONMENT=${1:-dev}
IMAGE_TAG=${2:-latest}
-echo "🚀 Starting deployment for environment: $ENVIRONMENT with image tag: $IMAGE_TAG"
+echo "🚀 Deploying to ${ENVIRONMENT} environment with tag ${IMAGE_TAG}..."
+
+# 환경별 설정 파일 로드
+source "$(dirname "$0")/../config/deploy_env_vars_${ENVIRONMENT}"
# 환경별 이미지 태그 업데이트
-cd deployment/cicd/kustomize/overlays/${ENVIRONMENT}
+cd "$(dirname "$0")/../kustomize/overlays/${ENVIRONMENT}"
-# 서비스 목록 (공백으로 구분)
+# 서비스 목록
services="api-gateway user-service bill-service product-service kos-mock"
-echo "📦 Updating image tags for services: $services"
-
# 각 서비스 이미지 태그 업데이트
for service in $services; do
- echo " - Updating $service to ${ENVIRONMENT}-${IMAGE_TAG}"
- kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/$service:${ENVIRONMENT}-${IMAGE_TAG}
+ echo "📦 Updating image tag for ${service}..."
+ kustomize edit set image docker.io/hiondal/$service:${ENVIRONMENT}-${IMAGE_TAG}
done
-echo "🔧 Applying Kubernetes manifests..."
# 배포 실행
+echo "📋 Applying Kustomize manifests..."
kubectl apply -k .
-echo "⏳ Waiting for deployments to be ready..."
# 배포 상태 확인
+echo "⏳ Waiting for deployments to be ready..."
for service in $services; do
- echo " - Checking rollout status for $service"
- kubectl rollout status deployment/$service -n phonebill-dg0500 --timeout=300s
+ echo " Checking ${service}..."
+ kubectl rollout status deployment/$service -n ${namespace} --timeout=300s || echo " ⚠️ Timeout waiting for ${service}"
done
echo "✅ Deployment completed successfully!"
echo ""
-echo "📊 Current deployment status:"
-kubectl get pods -n phonebill-dg0500 -o wide
-echo ""
-echo "🌐 Service endpoints:"
-kubectl get services -n phonebill-dg0500
-echo ""
-echo "🔗 Ingress information:"
-kubectl get ingress -n phonebill-dg0500
\ No newline at end of file
+echo "📊 Current status:"
+kubectl get pods -n ${namespace}
diff --git a/deployment/cicd/scripts/validate-resources.sh b/deployment/cicd/scripts/validate-resources.sh
index 76b95ae..9d710b8 100755
--- a/deployment/cicd/scripts/validate-resources.sh
+++ b/deployment/cicd/scripts/validate-resources.sh
@@ -1,14 +1,13 @@
#!/bin/bash
-# Base 리소스 누락 검증 스크립트 (phonebill 전용)
+# Base 리소스 누락 검증 스크립트
-echo "🔍 phonebill Base 리소스 누락 검증 시작..."
+echo "🔍 Phonebill Base 리소스 누락 검증 시작..."
BASE_DIR="deployment/cicd/kustomize/base"
MISSING_RESOURCES=0
-REQUIRED_FILES=("deployment.yaml" "service.yaml")
-OPTIONAL_FILES=("cm-" "secret-")
# 1. 각 서비스 디렉토리의 파일 확인
+echo ""
echo "1. 서비스 디렉토리별 파일 목록:"
for dir in $BASE_DIR/*/; do
if [ -d "$dir" ] && [[ $(basename "$dir") != "common" ]]; then
@@ -16,24 +15,33 @@ for dir in $BASE_DIR/*/; do
echo "=== $service ==="
# 필수 파일 확인
- for required in "${REQUIRED_FILES[@]}"; do
- if [ -f "$dir$required" ]; then
- echo " ✅ $required"
- else
- echo " ❌ MISSING REQUIRED: $required"
- ((MISSING_RESOURCES++))
- fi
- done
+ if [ -f "$dir/deployment.yaml" ]; then
+ echo " ✅ deployment.yaml"
+ else
+ echo " ❌ MISSING REQUIRED: deployment.yaml"
+ ((MISSING_RESOURCES++))
+ fi
- # 선택적 파일 확인
- for optional in "${OPTIONAL_FILES[@]}"; do
- files=($(ls "$dir"$optional*".yaml" 2>/dev/null))
- if [ ${#files[@]} -gt 0 ]; then
- for file in "${files[@]}"; do
- echo " ✅ $(basename "$file")"
- done
- fi
- done
+ if [ -f "$dir/service.yaml" ]; then
+ echo " ✅ service.yaml"
+ else
+ echo " ❌ MISSING REQUIRED: service.yaml"
+ ((MISSING_RESOURCES++))
+ fi
+
+ # ConfigMap 확인
+ if ls "$dir"cm-*.yaml 1> /dev/null 2>&1; then
+ for file in "$dir"cm-*.yaml; do
+ echo " ✅ $(basename "$file")"
+ done
+ fi
+
+ # Secret 확인
+ if ls "$dir"secret-*.yaml 1> /dev/null 2>&1; then
+ for file in "$dir"secret-*.yaml; do
+ echo " ✅ $(basename "$file")"
+ done
+ fi
echo ""
fi
done
@@ -42,15 +50,11 @@ done
echo "2. Common 리소스 확인:"
COMMON_DIR="$BASE_DIR/common"
if [ -d "$COMMON_DIR" ]; then
- common_files=($(ls "$COMMON_DIR"/*.yaml 2>/dev/null))
- if [ ${#common_files[@]} -gt 0 ]; then
- for file in "${common_files[@]}"; do
+ for file in "$COMMON_DIR"/*.yaml; do
+ if [ -f "$file" ]; then
echo " ✅ common/$(basename "$file")"
- done
- else
- echo " ❌ Common 디렉토리에 YAML 파일이 없습니다"
- ((MISSING_RESOURCES++))
- fi
+ fi
+ done
else
echo " ❌ Common 디렉토리가 없습니다"
((MISSING_RESOURCES++))
@@ -61,9 +65,8 @@ echo ""
echo "3. kustomization.yaml 리소스 검증:"
if [ -f "$BASE_DIR/kustomization.yaml" ]; then
while IFS= read -r line; do
- # resources 섹션의 YAML 파일 경로 추출
if [[ $line =~ ^[[:space:]]*-[[:space:]]*([^#]+\.yaml)[[:space:]]*$ ]]; then
- resource_path=$(echo "${BASH_REMATCH[1]}" | xargs) # 공백 제거
+ resource_path=$(echo "${BASH_REMATCH[1]}" | xargs)
full_path="$BASE_DIR/$resource_path"
if [ -f "$full_path" ]; then
echo " ✅ $resource_path"
@@ -125,4 +128,4 @@ else
echo " - Secret: secret-{서비스명}.yaml"
echo "4. 다시 검증: ./scripts/validate-resources.sh"
exit 1
-fi
\ No newline at end of file
+fi
diff --git a/deployment/container/Dockerfile-backend b/deployment/container/Dockerfile-backend
index 66d7f45..b03a59a 100644
--- a/deployment/container/Dockerfile-backend
+++ b/deployment/container/Dockerfile-backend
@@ -5,13 +5,14 @@ ARG ARTIFACTORY_FILE
COPY ${BUILD_LIB_DIR}/${ARTIFACTORY_FILE} app.jar
# Run stage
-FROM eclipse-temurin:21-jre
+FROM eclipse-temurin:21-jre-alpine
ENV USERNAME=k8s
ENV ARTIFACTORY_HOME=/home/${USERNAME}
ENV JAVA_OPTS=""
# Add a non-root user
-RUN adduser --system --group ${USERNAME} && \
+RUN addgroup -S ${USERNAME} && \
+ adduser -S -G ${USERNAME} ${USERNAME} && \
mkdir -p ${ARTIFACTORY_HOME} && \
chown ${USERNAME}:${USERNAME} ${ARTIFACTORY_HOME}
@@ -22,4 +23,4 @@ RUN chown ${USERNAME}:${USERNAME} app.jar
USER ${USERNAME}
ENTRYPOINT [ "sh", "-c" ]
-CMD ["java ${JAVA_OPTS} -jar app.jar"]
\ No newline at end of file
+CMD ["java ${JAVA_OPTS} -jar app.jar"]
diff --git a/deployment/container/build-image.md b/deployment/container/build-image.md
index 952fbb2..b10d2e0 100644
--- a/deployment/container/build-image.md
+++ b/deployment/container/build-image.md
@@ -1,48 +1,37 @@
-# 백엔드 컨테이너 이미지 빌드 결과서
+# 백엔드 컨테이너 이미지 작성 결과서
-## 작업 개요
-- **작업일시**: 2025-01-10
-- **작업자**: 최운영/데옵스
-- **작업 목표**: 백엔드 마이크로서비스들의 컨테이너 이미지 생성
+## 개요
+본 문서는 phonebill 프로젝트의 백엔드 마이크로서비스들의 컨테이너 이미지 빌드 과정과 결과를 기록합니다.
-## 빌드 대상 서비스
-총 5개의 백엔드 서비스에 대한 컨테이너 이미지를 생성했습니다.
+## 대상 서비스
+| 서비스명 | 설명 |
+|---------|------|
+| api-gateway | API Gateway 서비스 |
+| user-service | 사용자 인증/관리 서비스 |
+| bill-service | 요금 조회 서비스 |
+| product-service | 상품 변경 서비스 |
+| kos-mock | KOS 목업 서비스 |
-1. **api-gateway**: API Gateway 서비스
-2. **user-service**: 사용자 관리 서비스
-3. **bill-service**: 요금 조회 서비스
-4. **product-service**: 상품 변경 서비스
-5. **kos-mock**: KOS 시스템 목업 서비스
+## Dockerfile 구성
-## 사전 작업
-
-### 1. 서비스별 bootJar 설정 추가
-각 서비스의 build.gradle 파일에 일관된 JAR 파일명 설정을 추가했습니다.
-
-```gradle
-bootJar {
- archiveFileName = '{서비스명}.jar'
-}
-```
-
-### 2. Dockerfile 생성
-`deployment/container/Dockerfile-backend` 파일을 생성했습니다.
+**파일 위치**: `deployment/container/Dockerfile-backend`
```dockerfile
# Build stage
-FROM openjdk:23-oraclelinux8 AS builder
+FROM eclipse-temurin:21-jdk AS builder
ARG BUILD_LIB_DIR
ARG ARTIFACTORY_FILE
COPY ${BUILD_LIB_DIR}/${ARTIFACTORY_FILE} app.jar
# Run stage
-FROM openjdk:23-slim
+FROM eclipse-temurin:21-jre-alpine
ENV USERNAME=k8s
ENV ARTIFACTORY_HOME=/home/${USERNAME}
ENV JAVA_OPTS=""
# Add a non-root user
-RUN adduser --system --group ${USERNAME} && \
+RUN addgroup -S ${USERNAME} && \
+ adduser -S -G ${USERNAME} ${USERNAME} && \
mkdir -p ${ARTIFACTORY_HOME} && \
chown ${USERNAME}:${USERNAME} ${ARTIFACTORY_HOME}
@@ -56,136 +45,99 @@ ENTRYPOINT [ "sh", "-c" ]
CMD ["java ${JAVA_OPTS} -jar app.jar"]
```
-### 3. 서비스별 빌드
-모든 서비스에 대해 Gradle 빌드를 수행했습니다.
+### Dockerfile 특징
+- **멀티스테이지 빌드**: 빌드와 실행 환경 분리로 이미지 크기 최적화
+- **베이스 이미지**: Eclipse Temurin 21 JRE Alpine (경량화)
+- **보안**: 비루트 사용자(k8s)로 실행
+- **유연성**: `JAVA_OPTS` 환경변수로 JVM 옵션 설정 가능
+## 빌드 과정
+
+### 1. Gradle 빌드 (JAR 파일 생성)
```bash
-./gradlew api-gateway:clean api-gateway:bootJar
-./gradlew user-service:clean user-service:bootJar
-./gradlew bill-service:clean bill-service:bootJar
-./gradlew product-service:clean product-service:bootJar
-./gradlew kos-mock:clean kos-mock:bootJar
+./gradlew clean build -x test
```
-## 컨테이너 이미지 빌드
+### 2. 컨테이너 이미지 빌드
+각 서비스별로 아래 명령을 실행합니다:
-각 서비스별로 다음 명령어를 사용하여 컨테이너 이미지를 빌드했습니다.
-
-### API Gateway
```bash
DOCKER_FILE=deployment/container/Dockerfile-backend
-service=api-gateway
+# api-gateway
docker build \
--platform linux/amd64 \
- --build-arg BUILD_LIB_DIR="${service}/build/libs" \
- --build-arg ARTIFACTORY_FILE="${service}.jar" \
+ --build-arg BUILD_LIB_DIR="api-gateway/build/libs" \
+ --build-arg ARTIFACTORY_FILE="api-gateway.jar" \
-f ${DOCKER_FILE} \
- -t ${service}:latest .
-```
-
-### User Service
-```bash
-DOCKER_FILE=deployment/container/Dockerfile-backend
-service=user-service
+ -t api-gateway:latest .
+# user-service
docker build \
--platform linux/amd64 \
- --build-arg BUILD_LIB_DIR="${service}/build/libs" \
- --build-arg ARTIFACTORY_FILE="${service}.jar" \
+ --build-arg BUILD_LIB_DIR="user-service/build/libs" \
+ --build-arg ARTIFACTORY_FILE="user-service.jar" \
-f ${DOCKER_FILE} \
- -t ${service}:latest .
-```
-
-### Bill Service
-```bash
-DOCKER_FILE=deployment/container/Dockerfile-backend
-service=bill-service
+ -t user-service:latest .
+# bill-service
docker build \
--platform linux/amd64 \
- --build-arg BUILD_LIB_DIR="${service}/build/libs" \
- --build-arg ARTIFACTORY_FILE="${service}.jar" \
+ --build-arg BUILD_LIB_DIR="bill-service/build/libs" \
+ --build-arg ARTIFACTORY_FILE="bill-service.jar" \
-f ${DOCKER_FILE} \
- -t ${service}:latest .
-```
-
-### Product Service
-```bash
-DOCKER_FILE=deployment/container/Dockerfile-backend
-service=product-service
+ -t bill-service:latest .
+# product-service
docker build \
--platform linux/amd64 \
- --build-arg BUILD_LIB_DIR="${service}/build/libs" \
- --build-arg ARTIFACTORY_FILE="${service}.jar" \
+ --build-arg BUILD_LIB_DIR="product-service/build/libs" \
+ --build-arg ARTIFACTORY_FILE="product-service.jar" \
-f ${DOCKER_FILE} \
- -t ${service}:latest .
-```
-
-### KOS Mock Service
-```bash
-DOCKER_FILE=deployment/container/Dockerfile-backend
-service=kos-mock
+ -t product-service:latest .
+# kos-mock
docker build \
--platform linux/amd64 \
- --build-arg BUILD_LIB_DIR="${service}/build/libs" \
- --build-arg ARTIFACTORY_FILE="${service}.jar" \
+ --build-arg BUILD_LIB_DIR="kos-mock/build/libs" \
+ --build-arg ARTIFACTORY_FILE="kos-mock.jar" \
-f ${DOCKER_FILE} \
- -t ${service}:latest .
+ -t kos-mock:latest .
```
## 빌드 결과
-### 성공적으로 생성된 이미지들
+### 생성된 이미지 목록
+| 이미지명 | 태그 | 크기 | 상태 |
+|---------|------|------|------|
+| api-gateway | latest | 158MB | ✅ 성공 |
+| user-service | latest | 205MB | ✅ 성공 |
+| bill-service | latest | 214MB | ✅ 성공 |
+| product-service | latest | 220MB | ✅ 성공 |
+| kos-mock | latest | 201MB | ✅ 성공 |
-| 서비스명 | 이미지 태그 | 이미지 ID | 크기 | 생성 시간 |
-|---------|------------|-----------|------|----------|
-| api-gateway | latest | 5f4a2a5527b8 | 329MB | 3분 전 |
-| user-service | latest | a8a85ba0b703 | 376MB | 2분 전 |
-| bill-service | latest | b77190090a40 | 385MB | 1분 전 |
-| product-service | latest | 5a6fba790ca3 | 392MB | 1분 전 |
-| kos-mock | latest | 3f5878cf2f1e | 372MB | 35초 전 |
-
-### 이미지 검증 명령어 실행 결과
+### 이미지 확인 명령
```bash
-$ docker images | grep -E "(api-gateway|user-service|bill-service|product-service|kos-mock)"
-kos-mock latest 3f5878cf2f1e 35 seconds ago 372MB
-product-service latest 5a6fba790ca3 About a minute ago 392MB
-bill-service latest b77190090a40 About a minute ago 385MB
-user-service latest a8a85ba0b703 2 minutes ago 376MB
-api-gateway latest 5f4a2a5527b8 3 minutes ago 329MB
+docker images | grep -E "api-gateway|user-service|bill-service|product-service|kos-mock"
```
-## 빌드 특징
+## 이미지 레지스트리 푸시 (선택)
-### 멀티 스테이지 빌드
-- **Build Stage**: OpenJDK 23-oraclelinux8 사용하여 JAR 파일 복사
-- **Runtime Stage**: OpenJDK 23-slim 사용하여 경량화된 실행 환경 구성
+Azure Container Registry에 푸시하는 경우:
+```bash
+REGISTRY=docker.io
+PROJECT=hiondal
+TAG=latest
-### 보안 강화
-- 비루트 사용자 `k8s` 생성 및 사용
-- 적절한 파일 소유권 및 권한 설정
-- 최소 권한 원칙 적용
+# 로그인
+az acr login --name acrdigitalgarage01
-### 플랫폼 호환성
-- `--platform linux/amd64` 옵션으로 AMD64 아키텍처 지원
-- 쿠버네티스 클러스터 배포에 적합한 형태
+# 태그 및 푸시
+for service in api-gateway user-service bill-service product-service kos-mock; do
+ docker tag ${service}:latest ${REGISTRY}/${PROJECT}/${service}:${TAG}
+ docker push ${REGISTRY}/${PROJECT}/${service}:${TAG}
+done
+```
-## 다음 단계
-
-1. **컨테이너 레지스트리 푸시**: ACR 또는 Docker Hub에 이미지 푸시
-2. **쿠버네티스 매니페스트 작성**: Deployment, Service 등 K8s 리소스 정의
-3. **헬름 차트 작성**: 패키지 관리를 위한 Helm 차트 구성
-4. **CI/CD 파이프라인 통합**: 자동화된 빌드 및 배포 파이프라인 구축
-
-## 주요 성과
-
-✅ **모든 백엔드 서비스 컨테이너화 완료** (5개 서비스)
-✅ **멀티 스테이지 빌드로 최적화된 이미지** (평균 360MB)
-✅ **보안 강화된 컨테이너 구성** (비루트 사용자)
-✅ **일관된 빌드 프로세스** (표준화된 Dockerfile)
-✅ **쿠버네티스 배포 준비 완료**
-
-모든 백엔드 서비스들이 성공적으로 컨테이너화되었으며, 프로덕션 환경 배포를 위한 준비가 완료되었습니다.
\ No newline at end of file
+## 작성일
+2025-11-27
diff --git a/deployment/container/run-container-guide.md b/deployment/container/run-container-guide.md
index 173cfdd..050a03b 100644
--- a/deployment/container/run-container-guide.md
+++ b/deployment/container/run-container-guide.md
@@ -1,328 +1,326 @@
-# 백엔드 컨테이너 실행 가이드
+# 백엔드 컨테이너 실행 가이드 (로컬 환경)
-## 1. 시스템 정보
-- **시스템명**: phonebill
-- **서비스 목록**:
- - api-gateway (포트: 8080)
- - user-service (포트: 8081)
- - bill-service (포트: 8082)
- - product-service (포트: 8083)
- - kos-mock (포트: 8084)
+## 개요
+본 문서는 phonebill 프로젝트의 백엔드 마이크로서비스들을 로컬 환경에서 Docker 컨테이너로 실행하는 방법을 안내합니다.
-## 2. VM 접속 방법
+## 실행 정보
+| 항목 | 값 |
+|------|-----|
+| Image Registry | docker.io |
+| 시스템명 | phonebill |
+| 실행 환경 | 로컬 (localhost) |
-### Windows 사용자
-1. **Windows Terminal** 실행
-2. 아래 명령어 순서대로 실행:
+## 대상 서비스
+| 서비스명 | 포트 | 설명 |
+|---------|------|------|
+| kos-mock | 8084 | KOS 목업 서비스 |
+| user-service | 8081 | 사용자 인증/관리 서비스 |
+| bill-service | 8082 | 요금 조회 서비스 |
+| product-service | 8083 | 상품 변경 서비스 |
+| api-gateway | 8080 | API Gateway |
+## 사전 준비 사항
+
+### 1. Docker 설치 확인
```bash
-# Private Key 파일 권한 설정 (최초 1회만)
-chmod 400 ~/home/bastion-dg0500
-
-# VM 접속
-ssh -i ~/home/bastion-dg0500 azureuser@4.230.5.6
+docker --version
```
-### Linux/Mac 사용자
-1. **터미널** 실행
-2. 아래 명령어 순서대로 실행:
+### 2. 백킹 서비스 실행 확인
+컨테이너 실행 전 아래 백킹 서비스가 실행 중이어야 합니다:
+- **PostgreSQL** (auth-db: 15432, bill-inquiry-db: 25432, product-change-db: 35432)
+- **Redis** (16379)
+백킹 서비스 실행 상태 확인:
```bash
-# Private Key 파일 권한 설정 (최초 1회만)
-chmod 400 ~/home/bastion-dg0500
-
-# VM 접속
-ssh -i ~/home/bastion-dg0500 azureuser@4.230.5.6
+docker ps | grep -E "postgres|redis"
```
-## 3. 컨테이너 이미지 준비
+## 어플리케이션 빌드 및 컨테이너 이미지 생성
-### 3.1 이미지 빌드 (로컬에서 수행)
-먼저 로컬에서 이미지를 빌드해야 합니다. 아래 가이드를 참고하여 수행하세요:
-```bash
-# 이미지 빌드 가이드 확인
-cat deployment/container/build-image.md
-```
-
-### 3.2 Azure Container Registry 로그인
-ACR 인증 정보를 확인하고 Docker 로그인을 수행합니다:
+`deployment/container/build-image.md` 파일을 참조하여 이미지를 빌드합니다.
```bash
-# ACR 인증 정보 확인
-az acr credential show --name acrdigitalgarage01
+# Gradle 빌드
+./gradlew clean build -x test
-# 출력 예시:
-# {
-# "passwords": [
-# {
-# "name": "password",
-# "value": "실제암호"
-# }
-# ],
-# "username": "acrdigitalgarage01"
-# }
-
-# Docker 로그인 (위에서 확인한 username과 password 사용)
-docker login acrdigitalgarage01.azurecr.io -u acrdigitalgarage01 -p 실제암호
+# 이미지 빌드 예시 (api-gateway)
+docker build \
+ --platform linux/amd64 \
+ --build-arg BUILD_LIB_DIR="api-gateway/build/libs" \
+ --build-arg ARTIFACTORY_FILE="api-gateway.jar" \
+ -f deployment/container/Dockerfile-backend \
+ -t api-gateway:latest .
```
-### 3.3 이미지 Push (로컬에서 수행)
-각 서비스별로 이미지를 태깅하고 푸시합니다:
+## Docker Hub 로그인 (선택)
+이미지를 Docker Hub에 푸시하려면 로그인이 필요합니다:
+```bash
+docker login docker.io -u {Docker Hub ID} -p {암호}
+```
+
+## 이미지 태그 및 푸시 (선택)
+
+Docker Hub에 이미지를 푸시하는 경우:
+```bash
+# 태그
+docker tag api-gateway:latest docker.io/hiondal/api-gateway:latest
+
+# 푸시
+docker push docker.io/hiondal/api-gateway:latest
+```
+
+---
+
+## 컨테이너 실행
+
+> **중요**: 서비스 간 의존성이 있으므로 아래 순서대로 실행하세요.
+> 1. kos-mock → 2. user-service → 3. bill-service → 4. product-service → 5. api-gateway
+
+### 1. kos-mock 실행
+```bash
+docker run -d --name kos-mock --rm \
+ -p 8084:8084 \
+ -e SERVER_PORT=8084 \
+ -e SPRING_PROFILES_ACTIVE=dev \
+ kos-mock:latest
+```
+
+### 2. user-service 실행
+```bash
+docker run -d --name user-service --rm \
+ -p 8081:8081 \
+ -e SERVER_PORT=8081 \
+ -e SPRING_PROFILES_ACTIVE=dev \
+ -e CORS_ALLOWED_ORIGINS=http://localhost:3000 \
+ -e DB_HOST=localhost \
+ -e DB_PORT=15432 \
+ -e DB_NAME=authdb \
+ -e DB_USERNAME=unicorn \
+ -e DB_PASSWORD='P@ssw0rd$' \
+ -e DB_KIND=postgresql \
+ -e DDL_AUTO=update \
+ -e SHOW_SQL=true \
+ -e REDIS_HOST=host.docker.internal \
+ -e REDIS_PORT=16379 \
+ -e REDIS_PASSWORD='P@ssw0rd$' \
+ -e REDIS_DATABASE=0 \
+ -e JWT_SECRET='nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==' \
+ -e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
+ -e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
+ user-service:latest
+```
+
+### 3. bill-service 실행
+```bash
+docker run -d --name bill-service --rm \
+ -p 8082:8082 \
+ -e SERVER_PORT=8082 \
+ -e SPRING_PROFILES_ACTIVE=dev \
+ -e CORS_ALLOWED_ORIGINS=http://localhost:3000 \
+ -e DB_HOST=host.docker.internal \
+ -e DB_PORT=25432 \
+ -e DB_NAME=inquirydb \
+ -e DB_USERNAME=unicorn \
+ -e DB_PASSWORD='P@ssw0rd$' \
+ -e DB_KIND=postgresql \
+ -e DB_MAX_POOL=20 \
+ -e DB_MIN_IDLE=5 \
+ -e DB_CONNECTION_TIMEOUT=30000 \
+ -e DB_IDLE_TIMEOUT=600000 \
+ -e DB_MAX_LIFETIME=1800000 \
+ -e DB_LEAK_DETECTION=60000 \
+ -e REDIS_HOST=host.docker.internal \
+ -e REDIS_PORT=16379 \
+ -e REDIS_PASSWORD='P@ssw0rd$' \
+ -e REDIS_DATABASE=1 \
+ -e REDIS_TIMEOUT=2000 \
+ -e REDIS_MAX_ACTIVE=8 \
+ -e REDIS_MAX_IDLE=8 \
+ -e REDIS_MIN_IDLE=0 \
+ -e REDIS_MAX_WAIT=-1 \
+ -e KOS_BASE_URL=http://host.docker.internal:8084 \
+ -e JWT_SECRET='nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==' \
+ -e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
+ -e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
+ -e LOG_FILE_NAME=logs/bill-service.log \
+ bill-service:latest
+```
+
+### 4. product-service 실행
+```bash
+docker run -d --name product-service --rm \
+ -p 8083:8083 \
+ -e SERVER_PORT=8083 \
+ -e SPRING_PROFILES_ACTIVE=dev \
+ -e CORS_ALLOWED_ORIGINS=http://localhost:3000 \
+ -e DB_HOST=host.docker.internal \
+ -e DB_PORT=35432 \
+ -e DB_NAME=changedb \
+ -e DB_USERNAME=unicorn \
+ -e DB_PASSWORD='P@ssw0rd$' \
+ -e DB_KIND=postgresql \
+ -e DDL_AUTO=update \
+ -e REDIS_HOST=host.docker.internal \
+ -e REDIS_PORT=16379 \
+ -e REDIS_PASSWORD='P@ssw0rd$' \
+ -e REDIS_DATABASE=2 \
+ -e KOS_BASE_URL=http://host.docker.internal:8084 \
+ -e KOS_MOCK_ENABLED=true \
+ -e KOS_CLIENT_ID=product-service-dev \
+ -e KOS_API_KEY=dev-api-key \
+ -e JWT_SECRET='nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==' \
+ -e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
+ -e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
+ product-service:latest
+```
+
+### 5. api-gateway 실행
+```bash
+docker run -d --name api-gateway --rm \
+ -p 8080:8080 \
+ -e SERVER_PORT=8080 \
+ -e SPRING_PROFILES_ACTIVE=dev \
+ -e CORS_ALLOWED_ORIGINS=http://localhost:3000 \
+ -e USER_SERVICE_URL=http://host.docker.internal:8081 \
+ -e BILL_SERVICE_URL=http://host.docker.internal:8082 \
+ -e PRODUCT_SERVICE_URL=http://host.docker.internal:8083 \
+ -e KOS_MOCK_URL=http://host.docker.internal:8084 \
+ -e JWT_SECRET='nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==' \
+ -e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
+ -e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
+ api-gateway:latest
+```
+
+---
+
+## 실행 확인
+
+### 컨테이너 실행 상태 확인
+```bash
+docker ps | grep -E "api-gateway|user-service|bill-service|product-service|kos-mock"
+```
+
+### 예상 결과
+```
+CONTAINER ID IMAGE PORTS NAMES
+xxxxxxxxxxxx api-gateway:latest 0.0.0.0:8080->8080/tcp api-gateway
+xxxxxxxxxxxx product-service:latest 0.0.0.0:8083->8083/tcp product-service
+xxxxxxxxxxxx bill-service:latest 0.0.0.0:8082->8082/tcp bill-service
+xxxxxxxxxxxx user-service:latest 0.0.0.0:8081->8081/tcp user-service
+xxxxxxxxxxxx kos-mock:latest 0.0.0.0:8084->8084/tcp kos-mock
+```
+
+### 서비스 헬스체크
```bash
# API Gateway
-docker tag api-gateway:latest acrdigitalgarage01.azurecr.io/phonebill/api-gateway:latest
-docker push acrdigitalgarage01.azurecr.io/phonebill/api-gateway:latest
+curl http://localhost:8080/actuator/health
# User Service
-docker tag user-service:latest acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
-docker push acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
+curl http://localhost:8081/actuator/health
# Bill Service
-docker tag bill-service:latest acrdigitalgarage01.azurecr.io/phonebill/bill-service:latest
-docker push acrdigitalgarage01.azurecr.io/phonebill/bill-service:latest
+curl http://localhost:8082/actuator/health
# Product Service
-docker tag product-service:latest acrdigitalgarage01.azurecr.io/phonebill/product-service:latest
-docker push acrdigitalgarage01.azurecr.io/phonebill/product-service:latest
+curl http://localhost:8083/actuator/health
# KOS Mock
-docker tag kos-mock:latest acrdigitalgarage01.azurecr.io/phonebill/kos-mock:latest
-docker push acrdigitalgarage01.azurecr.io/phonebill/kos-mock:latest
+curl http://localhost:8084/actuator/health
```
-## 4. 컨테이너 실행 (VM에서 수행)
-
-### 4.1 KOS Mock 서비스 실행
+### 로그 확인
```bash
-SERVER_PORT=8084
-
-docker run -d --name kos-mock --rm -p ${SERVER_PORT}:${SERVER_PORT} \
--e SERVER_PORT=8084 \
--e SPRING_PROFILES_ACTIVE=dev \
-acrdigitalgarage01.azurecr.io/phonebill/kos-mock:latest
+docker logs -f api-gateway
+docker logs -f user-service
+docker logs -f bill-service
+docker logs -f product-service
+docker logs -f kos-mock
```
-### 4.2 User Service 실행
+---
+
+## 컨테이너 중지
+
+### 개별 서비스 중지
```bash
-SERVER_PORT=8081
-
-docker run -d --name user-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
--e CORS_ALLOWED_ORIGINS="http://localhost:3000,http://4.230.5.6:3000" \
--e DB_HOST=20.249.70.6 \
--e DB_KIND=postgresql \
--e DB_NAME=phonebill_auth \
--e DB_PASSWORD=AuthUser2025! \
--e DB_PORT=5432 \
--e DB_USERNAME=auth_user \
--e DDL_AUTO=update \
--e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
--e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
--e JWT_SECRET="nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" \
--e REDIS_DATABASE=0 \
--e REDIS_HOST=20.249.193.103 \
--e REDIS_PASSWORD=Redis2025Dev! \
--e REDIS_PORT=6379 \
--e SERVER_PORT=8081 \
--e SHOW_SQL=true \
--e SPRING_PROFILES_ACTIVE=dev \
-acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
-```
-
-### 4.3 Bill Service 실행
-```bash
-SERVER_PORT=8082
-
-docker run -d --name bill-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
--e CORS_ALLOWED_ORIGINS="http://localhost:3000,http://4.230.5.6:3000" \
--e DB_CONNECTION_TIMEOUT=30000 \
--e DB_HOST=20.249.175.46 \
--e DB_IDLE_TIMEOUT=600000 \
--e DB_KIND=postgresql \
--e DB_LEAK_DETECTION=60000 \
--e DB_MAX_LIFETIME=1800000 \
--e DB_MAX_POOL=20 \
--e DB_MIN_IDLE=5 \
--e DB_NAME=bill_inquiry_db \
--e DB_PASSWORD=BillUser2025! \
--e DB_PORT=5432 \
--e DB_USERNAME=bill_inquiry_user \
--e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
--e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
--e JWT_SECRET="nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" \
--e KOS_BASE_URL=http://4.230.5.6:8084 \
--e LOG_FILE_NAME=logs/bill-service.log \
--e REDIS_DATABASE=1 \
--e REDIS_HOST=20.249.193.103 \
--e REDIS_MAX_ACTIVE=8 \
--e REDIS_MAX_IDLE=8 \
--e REDIS_MAX_WAIT=-1 \
--e REDIS_MIN_IDLE=0 \
--e REDIS_PASSWORD=Redis2025Dev! \
--e REDIS_PORT=6379 \
--e REDIS_TIMEOUT=2000 \
--e SERVER_PORT=8082 \
--e SPRING_PROFILES_ACTIVE=dev \
-acrdigitalgarage01.azurecr.io/phonebill/bill-service:latest
-```
-
-### 4.4 Product Service 실행
-```bash
-SERVER_PORT=8083
-
-docker run -d --name product-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
--e CORS_ALLOWED_ORIGINS="http://localhost:3000,http://4.230.5.6:3000" \
--e DB_HOST=20.249.107.185 \
--e DB_KIND=postgresql \
--e DB_NAME=product_change_db \
--e DB_PASSWORD=ProductUser2025! \
--e DB_PORT=5432 \
--e DB_USERNAME=product_change_user \
--e DDL_AUTO=update \
--e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
--e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
--e JWT_SECRET="nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" \
--e KOS_API_KEY=dev-api-key \
--e KOS_BASE_URL=http://4.230.5.6:8084 \
--e KOS_CLIENT_ID=product-service-dev \
--e KOS_MOCK_ENABLED=true \
--e REDIS_DATABASE=2 \
--e REDIS_HOST=20.249.193.103 \
--e REDIS_PASSWORD=Redis2025Dev! \
--e REDIS_PORT=6379 \
--e SERVER_PORT=8083 \
--e SPRING_PROFILES_ACTIVE=dev \
-acrdigitalgarage01.azurecr.io/phonebill/product-service:latest
-```
-
-### 4.5 API Gateway 실행
-```bash
-SERVER_PORT=8080
-
-docker run -d --name api-gateway --rm -p ${SERVER_PORT}:${SERVER_PORT} \
--e BILL_SERVICE_URL=http://4.230.5.6:8082 \
--e CORS_ALLOWED_ORIGINS="http://localhost:3000,http://4.230.5.6:3000" \
--e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
--e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
--e JWT_SECRET="nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" \
--e KOS_MOCK_URL=http://4.230.5.6:8084 \
--e PRODUCT_SERVICE_URL=http://4.230.5.6:8083 \
--e SERVER_PORT=8080 \
--e SPRING_PROFILES_ACTIVE=dev \
--e USER_SERVICE_URL=http://4.230.5.6:8081 \
-acrdigitalgarage01.azurecr.io/phonebill/api-gateway:latest
-```
-
-## 5. 컨테이너 실행 확인
-
-전체 서비스가 정상적으로 실행되었는지 확인:
-
-```bash
-# 모든 서비스 확인
-docker ps | grep -E "(api-gateway|user-service|bill-service|product-service|kos-mock)"
-
-# 개별 서비스 확인
-docker ps | grep api-gateway
-docker ps | grep user-service
-docker ps | grep bill-service
-docker ps | grep product-service
-docker ps | grep kos-mock
-```
-
-## 6. 서비스 접속 테스트
-
-각 서비스의 헬스체크 엔드포인트로 정상 동작을 확인:
-
-```bash
-# API Gateway
-curl http://4.230.5.6:8080/actuator/health
-
-# User Service
-curl http://4.230.5.6:8081/actuator/health
-
-# Bill Service
-curl http://4.230.5.6:8082/actuator/health
-
-# Product Service
-curl http://4.230.5.6:8083/actuator/health
-
-# KOS Mock
-curl http://4.230.5.6:8084/actuator/health
-```
-
-## 7. 재배포 방법
-
-### 7.1 컨테이너 이미지 재생성 (로컬에서 수행)
-```bash
-# 이미지 재빌드
-/deploy-build-image-back
-```
-
-### 7.2 컨테이너 이미지 푸시 (로컬에서 수행)
-특정 서비스만 재배포하는 경우:
-```bash
-# 예: user-service 재배포
-docker tag user-service:latest acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
-docker push acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
-```
-
-### 7.3 컨테이너 재시작 (VM에서 수행)
-```bash
-# 1. 기존 컨테이너 중지
+docker stop api-gateway
+docker stop product-service
+docker stop bill-service
docker stop user-service
-
-# 2. 컨테이너 이미지 삭제 (캐시 갱신을 위해)
-docker rmi acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
-
-# 3. 새 이미지로 컨테이너 재실행
-SERVER_PORT=8081
-
-docker run -d --name user-service --rm -p ${SERVER_PORT}:${SERVER_PORT} \
--e CORS_ALLOWED_ORIGINS="http://localhost:3000,http://4.230.5.6:3000" \
--e DB_HOST=20.249.70.6 \
--e DB_KIND=postgresql \
--e DB_NAME=phonebill_auth \
--e DB_PASSWORD=AuthUser2025! \
--e DB_PORT=5432 \
--e DB_USERNAME=auth_user \
--e DDL_AUTO=update \
--e JWT_ACCESS_TOKEN_VALIDITY=18000000 \
--e JWT_REFRESH_TOKEN_VALIDITY=86400000 \
--e JWT_SECRET="nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ==" \
--e REDIS_DATABASE=0 \
--e REDIS_HOST=20.249.193.103 \
--e REDIS_PASSWORD=Redis2025Dev! \
--e REDIS_PORT=6379 \
--e SERVER_PORT=8081 \
--e SHOW_SQL=true \
--e SPRING_PROFILES_ACTIVE=dev \
-acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
+docker stop kos-mock
```
-## 8. 전체 서비스 재시작 스크립트
-
-모든 서비스를 한번에 재시작하려면:
-
+### 전체 서비스 중지
```bash
-# 모든 컨테이너 중지
-docker stop api-gateway user-service bill-service product-service kos-mock
-
-# 모든 이미지 삭제
-docker rmi acrdigitalgarage01.azurecr.io/phonebill/api-gateway:latest
-docker rmi acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
-docker rmi acrdigitalgarage01.azurecr.io/phonebill/bill-service:latest
-docker rmi acrdigitalgarage01.azurecr.io/phonebill/product-service:latest
-docker rmi acrdigitalgarage01.azurecr.io/phonebill/kos-mock:latest
-
-# 컨테이너 재실행 (위의 4.1 ~ 4.5 단계 순서대로 실행)
+docker stop api-gateway product-service bill-service user-service kos-mock
```
-## 주의사항
+---
-1. **실행 순서**: KOS Mock → User Service → Bill Service → Product Service → API Gateway 순서로 실행하는 것을 권장합니다.
+## 재배포 방법
-2. **CORS 설정**: 프론트엔드에서 접근할 수 있도록 VM IP(4.230.5.6:3000)가 CORS_ALLOWED_ORIGINS에 포함되어 있습니다.
+### 1. 소스 수정 후 로컬에서 푸시
+```bash
+git add .
+git commit -m "수정 내용"
+git push
+```
-3. **로그 확인**: 컨테이너 로그는 `docker logs [컨테이너명]` 명령으로 확인할 수 있습니다.
+### 2. 소스 내려받기
+```bash
+cd ~/home/workspace/phonebill
+git pull
+```
-4. **네트워크**: 모든 서비스는 localhost로 서로 통신하도록 설정되어 있습니다.
\ No newline at end of file
+### 3. 컨테이너 이미지 재생성
+`deployment/container/build-image.md` 파일을 참조하여 이미지를 다시 빌드합니다.
+
+### 4. 이미지 푸시 (Docker Hub 사용 시)
+```bash
+docker tag api-gateway:latest docker.io/phonebill/api-gateway:latest
+docker push docker.io/phonebill/api-gateway:latest
+```
+
+### 5. 컨테이너 중지
+```bash
+docker stop api-gateway
+```
+
+### 6. 기존 이미지 삭제 (선택)
+```bash
+docker rmi api-gateway:latest
+```
+
+### 7. 컨테이너 재실행
+위의 "컨테이너 실행" 섹션의 명령어를 다시 실행합니다.
+
+---
+
+## 문제 해결
+
+### 1. 컨테이너가 시작되지 않는 경우
+```bash
+# 로그 확인
+docker logs api-gateway
+
+# 컨테이너 상태 확인
+docker ps -a | grep api-gateway
+```
+
+### 2. 서비스 간 통신 오류
+- `host.docker.internal`이 올바르게 설정되었는지 확인
+- 방화벽 설정 확인
+- 백킹 서비스(DB, Redis) 실행 상태 확인
+
+### 3. 포트 충돌
+```bash
+# 사용 중인 포트 확인
+lsof -i :8080
+```
+
+---
+
+## 작성일
+2025-11-27
diff --git a/deployment/k8s/api-gateway/cm-api-gateway.yaml b/deployment/k8s/api-gateway/cm-api-gateway.yaml
deleted file mode 100644
index aa83a94..0000000
--- a/deployment/k8s/api-gateway/cm-api-gateway.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: cm-api-gateway
-data:
- SERVER_PORT: "8080"
- BILL_SERVICE_URL: "http://bill-service"
- PRODUCT_SERVICE_URL: "http://product-service"
- USER_SERVICE_URL: "http://user-service"
- KOS_MOCK_URL: "http://kos-mock"
\ No newline at end of file
diff --git a/deployment/k8s/bill-service/cm-bill-service.yaml b/deployment/k8s/bill-service/cm-bill-service.yaml
deleted file mode 100644
index 9281f36..0000000
--- a/deployment/k8s/bill-service/cm-bill-service.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: cm-bill-service
-data:
- SERVER_PORT: "8082"
- DB_KIND: "postgresql"
- DB_PORT: "5432"
- DB_CONNECTION_TIMEOUT: "30000"
- DB_IDLE_TIMEOUT: "600000"
- DB_LEAK_DETECTION: "60000"
- DB_MAX_LIFETIME: "1800000"
- DB_MAX_POOL: "20"
- DB_MIN_IDLE: "5"
- KOS_BASE_URL: "http://kos-mock"
- REDIS_DATABASE: "1"
- REDIS_MAX_ACTIVE: "8"
- REDIS_MAX_IDLE: "8"
- REDIS_MAX_WAIT: "-1"
- REDIS_MIN_IDLE: "0"
- REDIS_TIMEOUT: "2000"
\ No newline at end of file
diff --git a/deployment/k8s/bill-service/secret-bill-service.yaml b/deployment/k8s/bill-service/secret-bill-service.yaml
deleted file mode 100644
index caaa7cf..0000000
--- a/deployment/k8s/bill-service/secret-bill-service.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: secret-bill-service
-type: Opaque
-stringData:
- DB_HOST: "bill-inquiry-postgres-dev-postgresql"
- DB_NAME: "bill_inquiry_db"
- DB_USERNAME: "bill_inquiry_user"
- DB_PASSWORD: "BillUser2025@"
diff --git a/deployment/k8s/bill-service/service.yaml b/deployment/k8s/bill-service/service.yaml
deleted file mode 100644
index 1e6373b..0000000
--- a/deployment/k8s/bill-service/service.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: bill-service
-spec:
- selector:
- app: bill-service
- ports:
- - port: 80
- targetPort: 8082
- type: ClusterIP
\ No newline at end of file
diff --git a/deployment/k8s/common/cm-common.yaml b/deployment/k8s/common/cm-common.yaml
deleted file mode 100644
index 3c16172..0000000
--- a/deployment/k8s/common/cm-common.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: cm-common
-data:
- CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill-dg0500.20.214.196.128.nip.io"
- JWT_ACCESS_TOKEN_VALIDITY: "18000000"
- JWT_REFRESH_TOKEN_VALIDITY: "86400000"
- REDIS_PORT: "6379"
- SPRING_PROFILES_ACTIVE: "dev"
- DDL_AUTO: "update"
\ No newline at end of file
diff --git a/deployment/k8s/common/ingress.yaml b/deployment/k8s/common/ingress.yaml
deleted file mode 100644
index da97115..0000000
--- a/deployment/k8s/common/ingress.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: phonebill
- annotations:
- kubernetes.io/ingress.class: nginx
- nginx.ingress.kubernetes.io/ssl-redirect: "false"
-spec:
- ingressClassName: nginx
- rules:
- - host: phonebill-dg0500-api.20.214.196.128.nip.io
- http:
- paths:
- - path: /api/v1/auth
- pathType: Prefix
- backend:
- service:
- name: user-service
- port:
- number: 80
- - path: /api/v1/users
- pathType: Prefix
- backend:
- service:
- name: user-service
- port:
- number: 80
- - path: /api/v1/bills
- pathType: Prefix
- backend:
- service:
- name: bill-service
- port:
- number: 80
- - path: /api/v1/products
- pathType: Prefix
- backend:
- service:
- name: product-service
- port:
- number: 80
- - path: /api/v1/kos
- pathType: Prefix
- backend:
- service:
- name: kos-mock
- port:
- number: 80
-
diff --git a/deployment/k8s/common/secret-common.yaml b/deployment/k8s/common/secret-common.yaml
deleted file mode 100644
index 53795ab..0000000
--- a/deployment/k8s/common/secret-common.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: secret-common
-type: Opaque
-stringData:
- JWT_SECRET: "nwe5Yo9qaJ6FBD/Thl2/j6/SFAfNwUorAY1ZcWO2KI7uA4bmVLOCPxE9hYuUpRCOkgV2UF2DdHXtqHi3+BU/ecbz2zpHyf/720h48UbA3XOMYOX1sdM+dQ=="
- REDIS_HOST: "redis-cache-dev-master"
- REDIS_PASSWORD: "Redis2025Dev@"
\ No newline at end of file
diff --git a/deployment/k8s/common/secret-imagepull.yaml b/deployment/k8s/common/secret-imagepull.yaml
deleted file mode 100644
index 6bd576e..0000000
--- a/deployment/k8s/common/secret-imagepull.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: phonebill
-type: kubernetes.io/dockerconfigjson
-stringData:
- .dockerconfigjson: |
- {
- "auths": {
- "acrdigitalgarage01.azurecr.io": {
- "username": "acrdigitalgarage01",
- "password": "+OY+rmOagorjWvQe/tTk6oqvnZI8SmNbY/Y2o5EDcY+ACRDCDbYk",
- "auth": "YWNyZGlnaXRhbGdhcmFnZTAxOitPWStybU9hZ29yald2UWUvdFRrNm9xdm5aSThTbU5iWS9ZMm81RURjWStBQ1JEQ0RiWWs="
- }
- }
- }
\ No newline at end of file
diff --git a/deployment/k8s/configmaps/api-gateway-config.yaml b/deployment/k8s/configmaps/api-gateway-config.yaml
new file mode 100644
index 0000000..feb3661
--- /dev/null
+++ b/deployment/k8s/configmaps/api-gateway-config.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: api-gateway-config
+ namespace: phonebill
+ labels:
+ app: api-gateway
+ app.kubernetes.io/part-of: phonebill
+data:
+ SERVER_PORT: "8080"
+ USER_SERVICE_URL: "http://user-service:8081"
+ BILL_SERVICE_URL: "http://bill-service:8082"
+ PRODUCT_SERVICE_URL: "http://product-service:8083"
+ KOS_MOCK_URL: "http://kos-mock:8084"
diff --git a/deployment/k8s/configmaps/bill-service-config.yaml b/deployment/k8s/configmaps/bill-service-config.yaml
new file mode 100644
index 0000000..5a2b8de
--- /dev/null
+++ b/deployment/k8s/configmaps/bill-service-config.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: bill-service-config
+ namespace: phonebill
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
+data:
+ SERVER_PORT: "8082"
+ DB_HOST: "inquiry-postgresql"
+ DB_PORT: "5432"
+ DB_NAME: "inquirydb"
+ REDIS_DATABASE: "1"
+ KOS_BASE_URL: "http://kos-mock:8084"
+ DDL_AUTO: "update"
diff --git a/deployment/k8s/configmaps/common-config.yaml b/deployment/k8s/configmaps/common-config.yaml
new file mode 100644
index 0000000..d570940
--- /dev/null
+++ b/deployment/k8s/configmaps/common-config.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: phonebill-common-config
+ namespace: phonebill
+ labels:
+ app.kubernetes.io/part-of: phonebill
+data:
+ SPRING_PROFILES_ACTIVE: "prod"
+ REDIS_HOST: "cache-redis-master"
+ REDIS_PORT: "6379"
+ CORS_ALLOWED_ORIGINS: "http://localhost:3000,http://phonebill.72.155.72.236.nip.io"
+ SHOW_SQL: "false"
+ DDL_AUTO: "none"
diff --git a/deployment/k8s/configmaps/kos-mock-config.yaml b/deployment/k8s/configmaps/kos-mock-config.yaml
new file mode 100644
index 0000000..5f7a829
--- /dev/null
+++ b/deployment/k8s/configmaps/kos-mock-config.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: kos-mock-config
+ namespace: phonebill
+ labels:
+ app: kos-mock
+ app.kubernetes.io/part-of: phonebill
+data:
+ SERVER_PORT: "8084"
diff --git a/deployment/k8s/configmaps/product-service-config.yaml b/deployment/k8s/configmaps/product-service-config.yaml
new file mode 100644
index 0000000..ee82361
--- /dev/null
+++ b/deployment/k8s/configmaps/product-service-config.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: product-service-config
+ namespace: phonebill
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
+data:
+ SERVER_PORT: "8083"
+ DB_HOST: "change-postgresql"
+ DB_PORT: "5432"
+ DB_NAME: "changedb"
+ REDIS_DATABASE: "2"
+ KOS_BASE_URL: "http://kos-mock:8084"
+ DDL_AUTO: "update"
diff --git a/deployment/k8s/configmaps/user-service-config.yaml b/deployment/k8s/configmaps/user-service-config.yaml
new file mode 100644
index 0000000..afbc488
--- /dev/null
+++ b/deployment/k8s/configmaps/user-service-config.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: user-service-config
+ namespace: phonebill
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
+data:
+ SERVER_PORT: "8081"
+ DB_HOST: "auth-postgresql"
+ DB_PORT: "5432"
+ DB_NAME: "authdb"
+ REDIS_DATABASE: "0"
+ DDL_AUTO: "update"
diff --git a/deployment/k8s/delete-all.sh b/deployment/k8s/delete-all.sh
new file mode 100755
index 0000000..c728743
--- /dev/null
+++ b/deployment/k8s/delete-all.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Minikube 백엔드 서비스 삭제 스크립트
+# 작성자: 최운영(데옵스)
+# 작성일: 2025-11-29
+
+set -e
+
+NAMESPACE=phonebill
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+echo "=============================================="
+echo " PhoneBill Backend - 리소스 삭제"
+echo "=============================================="
+echo ""
+
+read -p "⚠️ $NAMESPACE 네임스페이스의 모든 리소스를 삭제하시겠습니까? (y/N): " -n 1 -r
+echo
+if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ echo "삭제를 취소합니다."
+ exit 0
+fi
+
+echo ""
+echo "[1/5] Ingress 삭제..."
+kubectl delete -f "$SCRIPT_DIR/ingress/" --ignore-not-found=true || true
+
+echo ""
+echo "[2/5] Services 삭제..."
+kubectl delete -f "$SCRIPT_DIR/services/" --ignore-not-found=true || true
+
+echo ""
+echo "[3/5] Deployments 삭제..."
+kubectl delete -f "$SCRIPT_DIR/deployments/" --ignore-not-found=true || true
+
+echo ""
+echo "[4/5] ConfigMaps 삭제..."
+kubectl delete -f "$SCRIPT_DIR/configmaps/" --ignore-not-found=true || true
+
+echo ""
+echo "[5/5] Secrets 삭제..."
+kubectl delete -f "$SCRIPT_DIR/secrets/" --ignore-not-found=true || true
+
+echo ""
+echo "=============================================="
+echo " 삭제 완료!"
+echo "=============================================="
+echo ""
+echo "📦 남은 리소스 확인:"
+kubectl get all -n $NAMESPACE 2>/dev/null || echo "리소스 없음"
+echo ""
diff --git a/deployment/k8s/deploy-all.sh b/deployment/k8s/deploy-all.sh
new file mode 100755
index 0000000..30256a2
--- /dev/null
+++ b/deployment/k8s/deploy-all.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+# Minikube 백엔드 서비스 원클릭 배포 스크립트
+# 작성자: 최운영(데옵스)
+# 작성일: 2025-11-29
+
+set -e
+
+NAMESPACE=phonebill
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+echo "=============================================="
+echo " PhoneBill Backend - Minikube 배포 시작"
+echo "=============================================="
+
+# 1. Kubernetes Context 확인
+echo ""
+echo "[1/7] Kubernetes Context 확인..."
+CURRENT_CONTEXT=$(kubectl config current-context)
+echo "현재 Context: $CURRENT_CONTEXT"
+
+if [[ "$CURRENT_CONTEXT" != "minikube-remote" ]]; then
+ echo "⚠️ 경고: 현재 Context가 minikube-remote가 아닙니다."
+ read -p "계속 진행하시겠습니까? (y/N): " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ echo "배포를 취소합니다."
+ exit 1
+ fi
+fi
+
+# 2. Namespace 생성
+echo ""
+echo "[2/7] Namespace 생성..."
+kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f -
+kubectl config set-context --current --namespace=$NAMESPACE
+
+# 3. Secrets 적용
+echo ""
+echo "[3/7] Secrets 적용..."
+kubectl apply -f "$SCRIPT_DIR/secrets/"
+
+# 4. ConfigMaps 적용
+echo ""
+echo "[4/7] ConfigMaps 적용..."
+kubectl apply -f "$SCRIPT_DIR/configmaps/"
+
+# 5. Deployments 적용
+echo ""
+echo "[5/7] Deployments 적용..."
+kubectl apply -f "$SCRIPT_DIR/deployments/"
+
+# 6. Services 적용
+echo ""
+echo "[6/7] Services 적용..."
+kubectl apply -f "$SCRIPT_DIR/services/"
+
+# 7. Ingress 적용
+echo ""
+echo "[7/7] Ingress 적용..."
+kubectl apply -f "$SCRIPT_DIR/ingress/"
+
+# 배포 상태 대기
+echo ""
+echo "=============================================="
+echo " 배포 상태 확인 중..."
+echo "=============================================="
+
+for service in api-gateway user-service bill-service product-service kos-mock; do
+ echo ""
+ echo "⏳ $service 배포 대기 중..."
+ kubectl rollout status deployment/$service -n $NAMESPACE --timeout=180s || {
+ echo "❌ $service 배포 실패"
+ kubectl describe deployment/$service -n $NAMESPACE
+ exit 1
+ }
+ echo "✅ $service 배포 완료"
+done
+
+# 최종 상태 출력
+echo ""
+echo "=============================================="
+echo " 배포 완료!"
+echo "=============================================="
+echo ""
+echo "📦 Pods 상태:"
+kubectl get pods -n $NAMESPACE
+echo ""
+echo "🔗 Services:"
+kubectl get svc -n $NAMESPACE
+echo ""
+echo "🌐 Ingress:"
+kubectl get ingress -n $NAMESPACE
+echo ""
+echo "=============================================="
+echo " 접속 방법"
+echo "=============================================="
+echo ""
+echo "API Gateway Ingress Host:"
+echo " phonebill-api.72.155.72.236.nip.io"
+echo ""
+echo "Health Check:"
+echo " curl http://phonebill-api.72.155.72.236.nip.io/actuator/health"
+echo ""
diff --git a/deployment/k8s/deploy-k8s-guide.md b/deployment/k8s/deploy-k8s-guide.md
deleted file mode 100644
index c239b18..0000000
--- a/deployment/k8s/deploy-k8s-guide.md
+++ /dev/null
@@ -1,313 +0,0 @@
-# 통신요금 관리 서비스 백엔드 Kubernetes 배포 가이드
-
-## 📋 배포 개요
-
-**시스템명**: phonebill
-**네임스페이스**: phonebill-dev
-**ACR명**: acrdigitalgarage01
-**k8s명**: aks-digitalgarage-01
-**파드수**: 1개 (각 서비스)
-**리소스**: CPU 256m/1024m, 메모리 256Mi/1024Mi
-
-## 🎯 배포 대상 서비스
-
-| 서비스명 | 포트 | 엔드포인트 |
-|---------|------|-----------|
-| api-gateway | 8080 | Gateway 및 라우팅 |
-| user-service | 8081 | /api/v1/auth, /api/v1/users |
-| bill-service | 8082 | /api/v1/bills |
-| product-service | 8083 | /api/v1/products |
-| kos-mock | 8084 | /api/v1/kos |
-
-## 📋 배포 전 검증 결과
-
-### ✅ 검증 완료 항목
-- 객체이름 네이밍룰 준수
-- Secret에서 stringData 사용
-- JWT_SECRET 실행 프로파일 값 적용
-- Image 경로 올바른 형식
-- Service/Ingress 포트 매핑 일치 (80번)
-- Controller @RequestMapping 기반 path 설정
-- 보안 환경변수 Secret 분리
-- REDIS_DATABASE 서비스별 구분 (0,1,2)
-- envFrom 사용으로 환경변수 주입
-- 실행 프로파일 전체 환경변수 매핑 완료
-
-### ✅ 배포 전 확인 완료 사항
-모든 환경 정보가 확인되어 매니페스트 파일에 반영 완료되었습니다:
-
-1. **✅ Ingress Controller External IP**: `20.214.196.128`
-2. **✅ ACR 인증 정보**: `acrdigitalgarage01` / 실제 패스워드 적용
-3. **✅ Redis Service**: `redis-cache-dev-master`
-4. **✅ Database Services**:
- - User Service: `auth-postgres-dev-postgresql`
- - Bill Service: `bill-inquiry-postgres-dev-postgresql`
- - Product Service: `product-change-postgres-dev-postgresql`
-
-## 🔧 사전 확인 방법
-
-### 1. Azure 로그인 상태 확인
-```bash
-az account show
-```
-
-### 2. AKS Credential 확인
-```bash
-kubectl cluster-info
-```
-
-### 3. 네임스페이스 존재 확인
-```bash
-kubectl get ns phonebill-dev
-```
-
-### 4. Ingress Controller External IP 확인 ✅
-```bash
-kubectl get svc ingress-nginx-controller -n ingress-nginx
-```
-**확인 완료**: EXTERNAL-IP = `20.214.196.128`
-
-### 5. ACR 인증 정보 확인 ✅
-```bash
-# USERNAME 확인
-USERNAME=$(az acr credential show -n acrdigitalgarage01 --query "username" -o tsv)
-echo $USERNAME
-
-# PASSWORD 확인
-PASSWORD=$(az acr credential show -n acrdigitalgarage01 --query "passwords[0].value" -o tsv)
-echo $PASSWORD
-```
-**확인 완료**: USERNAME = `acrdigitalgarage01`, PASSWORD = 실제 값 적용
-
-### 6. Redis Service 이름 확인 ✅
-```bash
-kubectl get svc -n phonebill-dev | grep redis
-```
-**확인 완료**: `redis-cache-dev-master` (ClusterIP)
-
-### 7. Database Service 이름 확인 ✅
-```bash
-# 각 서비스별 DB 확인
-kubectl get svc -n phonebill-dev | grep auth
-kubectl get svc -n phonebill-dev | grep bill
-kubectl get svc -n phonebill-dev | grep product
-```
-**확인 완료**:
-- User Service: `auth-postgres-dev-postgresql`
-- Bill Service: `bill-inquiry-postgres-dev-postgresql`
-- Product Service: `product-change-postgres-dev-postgresql`
-
-## ✅ 매니페스트 업데이트 완료
-
-모든 매니페스트 파일이 실제 환경 정보로 업데이트 완료되었습니다:
-
-### 1. ✅ Ingress External IP 적용
-`deployment/k8s/common/ingress.yaml`:
-```yaml
-host: phonebill-api.20.214.196.128.nip.io
-```
-
-### 2. ✅ CORS Origins 적용
-`deployment/k8s/common/cm-common.yaml`:
-```yaml
-CORS_ALLOWED_ORIGINS: "http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill.20.214.196.128.nip.io"
-```
-
-### 3. ✅ ACR 인증 정보 적용
-`deployment/k8s/common/secret-imagepull.yaml`:
-```yaml
-stringData:
- .dockerconfigjson: |
- {
- "auths": {
- "acrdigitalgarage01.azurecr.io": {
- "username": "acrdigitalgarage01",
- "password": "+OY+rmOagorjWvQe/tTk6oqvnZI8SmNbY/Y2o5EDcY+ACRDCDbYk",
- "auth": "YWNyZGlnaXRhbGdhcmFnZTAxOitPWStybU9hZ29yald2UWUvdFRrNm9xdm5aSThTbU5iWS9ZMm81RURjWStBQ1JEQ0RiWWs="
- }
- }
- }
-```
-
-### 4. ✅ Redis Host 적용
-`deployment/k8s/common/secret-common.yaml`:
-```yaml
-REDIS_HOST: "redis-cache-dev-master"
-```
-
-### 5. ✅ Database Host 적용
-
-**user-service**: `deployment/k8s/user-service/secret-user-service.yaml`
-```yaml
-DB_HOST: "auth-postgres-dev-postgresql"
-```
-
-**bill-service**: `deployment/k8s/bill-service/secret-bill-service.yaml`
-```yaml
-DB_HOST: "bill-inquiry-postgres-dev-postgresql"
-```
-
-**product-service**: `deployment/k8s/product-service/secret-product-service.yaml`
-```yaml
-DB_HOST: "product-change-postgres-dev-postgresql"
-```
-
-## 🚀 배포 실행 가이드
-
-### 1. 공통 매니페스트 적용
-```bash
-kubectl apply -f deployment/k8s/common/
-```
-
-### 2. 서비스별 매니페스트 적용
-```bash
-# 각 서비스 순차 적용
-kubectl apply -f deployment/k8s/api-gateway/
-kubectl apply -f deployment/k8s/user-service/
-kubectl apply -f deployment/k8s/bill-service/
-kubectl apply -f deployment/k8s/product-service/
-kubectl apply -f deployment/k8s/kos-mock/
-```
-
-### 3. 배포 상태 확인
-
-#### 전체 객체 확인
-```bash
-kubectl get all -n phonebill-dev
-```
-
-#### Pod 상태 확인
-```bash
-kubectl get pods -n phonebill-dev
-```
-
-#### Service 확인
-```bash
-kubectl get svc -n phonebill-dev
-```
-
-#### Ingress 확인
-```bash
-kubectl get ingress -n phonebill-dev
-```
-
-#### ConfigMap/Secret 확인
-```bash
-kubectl get cm,secret -n phonebill-dev
-```
-
-### 4. 로그 확인
-```bash
-# 특정 서비스 로그 확인
-kubectl logs -f deployment/user-service -n phonebill-dev
-kubectl logs -f deployment/bill-service -n phonebill-dev
-kubectl logs -f deployment/product-service -n phonebill-dev
-kubectl logs -f deployment/api-gateway -n phonebill-dev
-kubectl logs -f deployment/kos-mock -n phonebill-dev
-```
-
-### 5. Health Check 확인
-```bash
-# 각 서비스 Health 상태 확인 (Pod 내부에서)
-kubectl exec -n phonebill-dev deployment/user-service -- curl http://localhost:8081/actuator/health
-kubectl exec -n phonebill-dev deployment/bill-service -- curl http://localhost:8082/actuator/health
-kubectl exec -n phonebill-dev deployment/product-service -- curl http://localhost:8083/actuator/health
-```
-
-## 🔍 문제 해결 가이드
-
-### Pod 시작 실패시
-```bash
-# Pod 상세 정보 확인
-kubectl describe pod -n phonebill-dev
-
-# 이벤트 확인
-kubectl get events -n phonebill-dev --sort-by='.lastTimestamp'
-```
-
-### ConfigMap/Secret 변경시
-```bash
-# 변경 후 Pod 재시작
-kubectl rollout restart deployment/ -n phonebill-dev
-```
-
-### 네트워크 연결 문제
-```bash
-# Service DNS 해결 테스트
-kubectl exec -n phonebill-dev deployment/api-gateway -- nslookup user-service
-```
-
-## 📊 환경변수 매핑 테이블
-
-| 서비스명 | 환경변수 | 지정 객체명 | 환경변수값 |
-|---------|---------|-----------|-----------|
-| api-gateway | SERVER_PORT | cm-api-gateway | 8080 |
-| api-gateway | BILL_SERVICE_URL | cm-api-gateway | http://bill-service |
-| api-gateway | PRODUCT_SERVICE_URL | cm-api-gateway | http://product-service |
-| api-gateway | USER_SERVICE_URL | cm-api-gateway | http://user-service |
-| api-gateway | KOS_MOCK_URL | cm-api-gateway | http://kos-mock |
-| 공통 | CORS_ALLOWED_ORIGINS | cm-common | http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8084,http://phonebill.{EXTERNAL_IP}.nip.io |
-| 공통 | JWT_ACCESS_TOKEN_VALIDITY | cm-common | 18000000 |
-| 공통 | JWT_REFRESH_TOKEN_VALIDITY | cm-common | 86400000 |
-| 공통 | JWT_SECRET | secret-common | (base64 encoded JWT secret) |
-| 공통 | REDIS_HOST | secret-common | (Redis 서비스명) |
-| 공통 | REDIS_PASSWORD | secret-common | Redis2025Dev! |
-| 공통 | REDIS_PORT | cm-common | 6379 |
-| 공통 | SPRING_PROFILES_ACTIVE | cm-common | dev |
-| user-service | SERVER_PORT | cm-user-service | 8081 |
-| user-service | DB_KIND | cm-user-service | postgresql |
-| user-service | DB_PORT | cm-user-service | 5432 |
-| user-service | DDL_AUTO | cm-user-service | update |
-| user-service | REDIS_DATABASE | cm-user-service | 0 |
-| user-service | SHOW_SQL | cm-user-service | true |
-| user-service | DB_HOST | secret-user-service | (Auth DB 서비스명) |
-| user-service | DB_NAME | secret-user-service | phonebill_auth |
-| user-service | DB_USERNAME | secret-user-service | auth_user |
-| user-service | DB_PASSWORD | secret-user-service | AuthUser2025! |
-| bill-service | SERVER_PORT | cm-bill-service | 8082 |
-| bill-service | DB_KIND | cm-bill-service | postgresql |
-| bill-service | DB_PORT | cm-bill-service | 5432 |
-| bill-service | DB_CONNECTION_TIMEOUT | cm-bill-service | 30000 |
-| bill-service | DB_IDLE_TIMEOUT | cm-bill-service | 600000 |
-| bill-service | DB_LEAK_DETECTION | cm-bill-service | 60000 |
-| bill-service | DB_MAX_LIFETIME | cm-bill-service | 1800000 |
-| bill-service | DB_MAX_POOL | cm-bill-service | 20 |
-| bill-service | DB_MIN_IDLE | cm-bill-service | 5 |
-| bill-service | KOS_BASE_URL | cm-bill-service | http://kos-mock |
-| bill-service | LOG_FILE_NAME | cm-bill-service | logs/bill-service.log |
-| bill-service | REDIS_DATABASE | cm-bill-service | 1 |
-| bill-service | REDIS_MAX_ACTIVE | cm-bill-service | 8 |
-| bill-service | REDIS_MAX_IDLE | cm-bill-service | 8 |
-| bill-service | REDIS_MAX_WAIT | cm-bill-service | -1 |
-| bill-service | REDIS_MIN_IDLE | cm-bill-service | 0 |
-| bill-service | REDIS_TIMEOUT | cm-bill-service | 2000 |
-| bill-service | DB_HOST | secret-bill-service | (Bill DB 서비스명) |
-| bill-service | DB_NAME | secret-bill-service | bill_inquiry_db |
-| bill-service | DB_USERNAME | secret-bill-service | bill_inquiry_user |
-| bill-service | DB_PASSWORD | secret-bill-service | BillUser2025! |
-| product-service | SERVER_PORT | cm-product-service | 8083 |
-| product-service | DB_KIND | cm-product-service | postgresql |
-| product-service | DB_PORT | cm-product-service | 5432 |
-| product-service | DDL_AUTO | cm-product-service | update |
-| product-service | KOS_BASE_URL | cm-product-service | http://kos-mock |
-| product-service | KOS_CLIENT_ID | cm-product-service | product-service-dev |
-| product-service | KOS_MOCK_ENABLED | cm-product-service | true |
-| product-service | REDIS_DATABASE | cm-product-service | 2 |
-| product-service | DB_HOST | secret-product-service | (Product DB 서비스명) |
-| product-service | DB_NAME | secret-product-service | product_change_db |
-| product-service | DB_USERNAME | secret-product-service | product_change_user |
-| product-service | DB_PASSWORD | secret-product-service | ProductUser2025! |
-| product-service | KOS_API_KEY | secret-product-service | dev-api-key |
-| kos-mock | SERVER_PORT | cm-kos-mock | 8084 |
-
-## 🎯 배포 완료 후 접근 URL
-
-- **API Gateway**: http://phonebill-api.20.214.196.128.nip.io
-- **Swagger UI**: http://phonebill-api.20.214.196.128.nip.io/swagger-ui/index.html
-- **사용자 인증**: http://phonebill-api.20.214.196.128.nip.io/api/v1/auth
-- **요금 조회**: http://phonebill-api.20.214.196.128.nip.io/api/v1/bills
-- **상품 변경**: http://phonebill-api.20.214.196.128.nip.io/api/v1/products
-
----
-
-**✅ 배포 준비 완료**: 모든 환경 정보가 확인되어 매니페스트 파일에 반영되었습니다. 이제 바로 배포를 진행할 수 있습니다.
\ No newline at end of file
diff --git a/deployment/k8s/deploy-minikube-guide.md b/deployment/k8s/deploy-minikube-guide.md
new file mode 100644
index 0000000..ea78388
--- /dev/null
+++ b/deployment/k8s/deploy-minikube-guide.md
@@ -0,0 +1,867 @@
+# Minikube 백엔드 서비스 배포 가이드
+
+## 개요
+본 문서는 phonebill 프로젝트의 백엔드 마이크로서비스들을 Minikube 환경에 배포하는 방법을 설명합니다.
+
+## 배포 대상 서비스
+
+| 서비스명 | 포트 | 설명 |
+|---------|------|------|
+| api-gateway | 8080 | API Gateway 서비스 |
+| user-service | 8081 | 사용자 인증/관리 서비스 |
+| bill-service | 8082 | 요금 조회 서비스 |
+| product-service | 8083 | 상품 변경 서비스 |
+| kos-mock | 8084 | KOS 목업 서비스 |
+
+## 배포 환경 정보
+
+| 항목 | 값 |
+|------|-----|
+| Image Registry | docker.io |
+| Image Organization | hiondal |
+| Kubernetes Context | minikube-remote |
+| Namespace | phonebill |
+| Replicas | 1 |
+| CPU Request/Limit | 256m/1024m |
+| Memory Request/Limit | 256Mi/1024Mi |
+
+---
+
+## 사전 준비
+
+### 1. Minikube 상태 확인
+```bash
+# context 전환
+kubectl config use-context minikube-remote
+
+# minikube 상태 확인
+minikube status
+
+# 노드 확인
+kubectl get nodes
+```
+
+### 2. Namespace 생성
+```bash
+kubectl create namespace phonebill
+kubectl config set-context --current --namespace=phonebill
+```
+
+### 3. Ingress Controller 활성화
+```bash
+minikube addons enable ingress
+```
+
+### 4. 백킹 서비스 확인
+배포 전 PostgreSQL과 Redis가 실행 중인지 확인합니다:
+```bash
+# PostgreSQL 파드 확인
+kubectl get pods -n phonebill | grep postgres
+
+# Redis 파드 확인
+kubectl get pods -n phonebill | grep redis
+```
+
+---
+
+## Step 1: 컨테이너 이미지 빌드 및 푸시
+
+### 1.1 Gradle 빌드
+```bash
+cd /Users/dreamondal/home/workspace/phonebill
+./gradlew clean build -x test
+```
+
+### 1.2 Docker 이미지 빌드
+```bash
+DOCKER_FILE=deployment/container/Dockerfile-backend
+REGISTRY=docker.io
+PROJECT=hiondal
+TAG=latest
+
+# 각 서비스 이미지 빌드
+for service in api-gateway user-service bill-service product-service kos-mock; do
+ docker build \
+ --platform linux/amd64 \
+ --build-arg BUILD_LIB_DIR="${service}/build/libs" \
+ --build-arg ARTIFACTORY_FILE="${service}.jar" \
+ -f ${DOCKER_FILE} \
+ -t ${REGISTRY}/${PROJECT}/${service}:${TAG} .
+done
+```
+
+### 1.3 Docker Hub 푸시
+```bash
+# Docker Hub 로그인
+docker login
+
+# 이미지 푸시
+for service in api-gateway user-service bill-service product-service kos-mock; do
+ docker push ${REGISTRY}/${PROJECT}/${service}:${TAG}
+done
+```
+
+---
+
+## Step 2: Secret 생성
+
+### 2.1 공통 Secret (JWT, Redis)
+```bash
+kubectl create secret generic phonebill-common-secret \
+ --namespace=phonebill \
+ --from-literal=JWT_SECRET='your-jwt-secret-key-must-be-at-least-256-bits-long-for-hs256' \
+ --from-literal=REDIS_PASSWORD=''
+```
+
+### 2.2 서비스별 DB Secret
+
+```bash
+# user-service DB Secret
+kubectl create secret generic user-service-db-secret \
+ --namespace=phonebill \
+ --from-literal=DB_USERNAME='postgres' \
+ --from-literal=DB_PASSWORD='your-auth-db-password'
+
+# bill-service DB Secret
+kubectl create secret generic bill-service-db-secret \
+ --namespace=phonebill \
+ --from-literal=DB_USERNAME='postgres' \
+ --from-literal=DB_PASSWORD='your-bill-db-password'
+
+# product-service DB Secret
+kubectl create secret generic product-service-db-secret \
+ --namespace=phonebill \
+ --from-literal=DB_USERNAME='postgres' \
+ --from-literal=DB_PASSWORD='your-product-db-password'
+```
+
+---
+
+## Step 3: ConfigMap 생성
+
+### 3.1 공통 ConfigMap
+```bash
+kubectl apply -f - < **참고**: nip.io 도메인을 사용하므로 별도의 hosts 파일 설정이 필요하지 않습니다.
+
+---
+
+## Step 7: 배포 확인
+
+### 7.1 파드 상태 확인
+```bash
+kubectl get pods -n phonebill -w
+```
+
+### 7.2 로그 확인
+```bash
+# 각 서비스 로그 확인
+kubectl logs -f deployment/api-gateway -n phonebill
+kubectl logs -f deployment/user-service -n phonebill
+kubectl logs -f deployment/bill-service -n phonebill
+kubectl logs -f deployment/product-service -n phonebill
+kubectl logs -f deployment/kos-mock -n phonebill
+```
+
+### 7.3 서비스 엔드포인트 확인
+```bash
+kubectl get endpoints -n phonebill
+```
+
+### 7.4 Ingress 상태 확인
+```bash
+kubectl get ingress -n phonebill
+```
+
+---
+
+## Step 8: API 테스트
+
+### 8.1 Health Check
+```bash
+# API Gateway Health Check
+curl http://phonebill-api.72.155.72.236.nip.io/actuator/health
+```
+
+### 8.2 서비스 API 테스트
+```bash
+# 사용자 등록 API
+curl -X POST http://phonebill-api.72.155.72.236.nip.io/api/users/register \
+ -H "Content-Type: application/json" \
+ -d '{
+ "userId": "testuser",
+ "password": "Test1234!",
+ "name": "테스트사용자",
+ "email": "test@example.com",
+ "phoneNumber": "01012345678"
+ }'
+
+# 로그인 API
+curl -X POST http://phonebill-api.72.155.72.236.nip.io/api/users/login \
+ -H "Content-Type: application/json" \
+ -d '{
+ "userId": "testuser",
+ "password": "Test1234!"
+ }'
+```
+
+---
+
+## 트러블슈팅
+
+### 파드가 시작되지 않는 경우
+```bash
+# 파드 상세 정보 확인
+kubectl describe pod -n phonebill
+
+# 이벤트 확인
+kubectl get events -n phonebill --sort-by='.lastTimestamp'
+```
+
+### 이미지 풀 실패
+```bash
+# Docker Hub 인증 Secret 생성 (필요시)
+kubectl create secret docker-registry regcred \
+ --namespace=phonebill \
+ --docker-server=https://index.docker.io/v1/ \
+ --docker-username= \
+ --docker-password= \
+ --docker-email=
+
+# Deployment에 imagePullSecrets 추가
+kubectl patch deployment -n phonebill \
+ -p '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"regcred"}]}}}}'
+```
+
+### DB 연결 실패
+```bash
+# PostgreSQL 서비스 확인
+kubectl get svc -n phonebill | grep postgres
+
+# DNS 해석 테스트
+kubectl run -it --rm debug --image=busybox --restart=Never -n phonebill \
+ -- nslookup auth-postgres.phonebill.svc.cluster.local
+```
+
+### Redis 연결 실패
+```bash
+# Redis 서비스 확인
+kubectl get svc -n phonebill | grep redis
+
+# Redis 연결 테스트
+kubectl run -it --rm redis-cli --image=redis:alpine --restart=Never -n phonebill \
+ -- redis-cli -h redis-cache.phonebill.svc.cluster.local ping
+```
+
+---
+
+## 리소스 정리
+
+### 전체 삭제
+```bash
+kubectl delete namespace phonebill
+```
+
+### 개별 삭제
+```bash
+# Ingress 삭제
+kubectl delete ingress phonebill-ingress -n phonebill
+
+# 서비스 삭제
+kubectl delete svc api-gateway user-service bill-service product-service kos-mock -n phonebill
+
+# Deployment 삭제
+kubectl delete deployment api-gateway user-service bill-service product-service kos-mock -n phonebill
+
+# ConfigMap 삭제
+kubectl delete configmap phonebill-common-config api-gateway-config user-service-config \
+ bill-service-config product-service-config kos-mock-config -n phonebill
+
+# Secret 삭제
+kubectl delete secret phonebill-common-secret user-service-db-secret \
+ bill-service-db-secret product-service-db-secret -n phonebill
+```
+
+---
+
+## 원클릭 배포 스크립트
+
+전체 배포를 한 번에 수행하는 스크립트:
+
+```bash
+#!/bin/bash
+# deploy-all.sh
+
+NAMESPACE=phonebill
+REGISTRY=docker.io
+PROJECT=hiondal
+TAG=latest
+
+echo "=== Minikube Backend 배포 시작 ==="
+
+# 1. Namespace 생성
+kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f -
+
+# 2. Secrets 생성
+echo "Creating secrets..."
+kubectl create secret generic phonebill-common-secret \
+ --namespace=$NAMESPACE \
+ --from-literal=JWT_SECRET='your-jwt-secret-key-must-be-at-least-256-bits-long-for-hs256' \
+ --from-literal=REDIS_PASSWORD='' \
+ --dry-run=client -o yaml | kubectl apply -f -
+
+# 3. ConfigMaps 적용
+echo "Applying ConfigMaps..."
+kubectl apply -f deployment/k8s/configmaps/
+
+# 4. Deployments 적용
+echo "Applying Deployments..."
+kubectl apply -f deployment/k8s/deployments/
+
+# 5. Services 적용
+echo "Applying Services..."
+kubectl apply -f deployment/k8s/services/
+
+# 6. Ingress 적용
+echo "Applying Ingress..."
+kubectl apply -f deployment/k8s/ingress/
+
+# 7. 배포 상태 확인
+echo "Waiting for deployments..."
+kubectl rollout status deployment/api-gateway -n $NAMESPACE --timeout=120s
+kubectl rollout status deployment/user-service -n $NAMESPACE --timeout=120s
+kubectl rollout status deployment/bill-service -n $NAMESPACE --timeout=120s
+kubectl rollout status deployment/product-service -n $NAMESPACE --timeout=120s
+kubectl rollout status deployment/kos-mock -n $NAMESPACE --timeout=120s
+
+echo "=== 배포 완료 ==="
+kubectl get pods -n $NAMESPACE
+```
+
+---
+
+## 작성자
+- **작성자**: 최운영(데옵스)
+- **작성일**: 2025-11-29
+- **버전**: 1.0.0
diff --git a/deployment/k8s/api-gateway/deployment.yaml b/deployment/k8s/deployments/api-gateway.yaml
similarity index 54%
rename from deployment/k8s/api-gateway/deployment.yaml
rename to deployment/k8s/deployments/api-gateway.yaml
index ceb7e8c..469f151 100644
--- a/deployment/k8s/api-gateway/deployment.yaml
+++ b/deployment/k8s/deployments/api-gateway.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
+ namespace: phonebill
+ labels:
+ app: api-gateway
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,46 +16,40 @@ spec:
labels:
app: api-gateway
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: api-gateway
- image: acrdigitalgarage01.azurecr.io/phonebill/api-gateway:latest
+ image: docker.io/hiondal/api-gateway:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-api-gateway
+ name: api-gateway-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /health
- port: 8080
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /health
- port: 8080
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
- path: /health
+ path: /actuator/health/liveness
+ port: 8080
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/k8s/bill-service/deployment.yaml b/deployment/k8s/deployments/bill-service.yaml
similarity index 58%
rename from deployment/k8s/bill-service/deployment.yaml
rename to deployment/k8s/deployments/bill-service.yaml
index 78a42dd..a57eff2 100644
--- a/deployment/k8s/bill-service/deployment.yaml
+++ b/deployment/k8s/deployments/bill-service.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: bill-service
+ namespace: phonebill
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,48 +16,42 @@ spec:
labels:
app: bill-service
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: bill-service
- image: acrdigitalgarage01.azurecr.io/phonebill/bill-service:latest
+ image: docker.io/hiondal/bill-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8082
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-bill-service
+ name: bill-service-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
- secretRef:
- name: secret-bill-service
+ name: bill-service-db-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8082
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8082
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8082
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8082
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/k8s/kos-mock/deployment.yaml b/deployment/k8s/deployments/kos-mock.yaml
similarity index 59%
rename from deployment/k8s/kos-mock/deployment.yaml
rename to deployment/k8s/deployments/kos-mock.yaml
index bd588f4..6c9a7ee 100644
--- a/deployment/k8s/kos-mock/deployment.yaml
+++ b/deployment/k8s/deployments/kos-mock.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: kos-mock
+ namespace: phonebill
+ labels:
+ app: kos-mock
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,46 +16,40 @@ spec:
labels:
app: kos-mock
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: kos-mock
- image: acrdigitalgarage01.azurecr.io/phonebill/kos-mock:latest
+ image: docker.io/hiondal/kos-mock:latest
imagePullPolicy: Always
ports:
- containerPort: 8084
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-kos-mock
+ name: kos-mock-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8084
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8084
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8084
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8084
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/k8s/product-service/deployment.yaml b/deployment/k8s/deployments/product-service.yaml
similarity index 58%
rename from deployment/k8s/product-service/deployment.yaml
rename to deployment/k8s/deployments/product-service.yaml
index 0b463a3..e7ca7db 100644
--- a/deployment/k8s/product-service/deployment.yaml
+++ b/deployment/k8s/deployments/product-service.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
+ namespace: phonebill
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,48 +16,42 @@ spec:
labels:
app: product-service
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: product-service
- image: acrdigitalgarage01.azurecr.io/phonebill/product-service:latest
+ image: docker.io/hiondal/product-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8083
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-product-service
+ name: product-service-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
- secretRef:
- name: secret-product-service
+ name: product-service-db-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8083
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8083
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8083
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8083
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/k8s/user-service/deployment.yaml b/deployment/k8s/deployments/user-service.yaml
similarity index 58%
rename from deployment/k8s/user-service/deployment.yaml
rename to deployment/k8s/deployments/user-service.yaml
index 2dbd2d4..ddd9095 100644
--- a/deployment/k8s/user-service/deployment.yaml
+++ b/deployment/k8s/deployments/user-service.yaml
@@ -2,6 +2,10 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
+ namespace: phonebill
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
spec:
replicas: 1
selector:
@@ -12,48 +16,42 @@ spec:
labels:
app: user-service
spec:
- imagePullSecrets:
- - name: phonebill
containers:
- name: user-service
- image: acrdigitalgarage01.azurecr.io/phonebill/user-service:latest
+ image: docker.io/hiondal/user-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8081
+ name: http
envFrom:
- configMapRef:
- name: cm-common
+ name: phonebill-common-config
- configMapRef:
- name: cm-user-service
+ name: user-service-config
- secretRef:
- name: secret-common
+ name: phonebill-common-secret
- secretRef:
- name: secret-user-service
+ name: user-service-db-secret
resources:
requests:
- cpu: 256m
- memory: 256Mi
+ cpu: "256m"
+ memory: "256Mi"
limits:
- cpu: 1024m
- memory: 1024Mi
- startupProbe:
- httpGet:
- path: /actuator/health
- port: 8081
- initialDelaySeconds: 30
- periodSeconds: 10
- failureThreshold: 6
- readinessProbe:
- httpGet:
- path: /actuator/health/readiness
- port: 8081
- initialDelaySeconds: 10
- periodSeconds: 5
- failureThreshold: 3
+ cpu: "1024m"
+ memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8081
+ initialDelaySeconds: 60
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ readinessProbe:
+ httpGet:
+ path: /actuator/health/readiness
+ port: 8081
initialDelaySeconds: 30
periodSeconds: 10
- failureThreshold: 3
\ No newline at end of file
+ timeoutSeconds: 5
+ failureThreshold: 3
diff --git a/deployment/k8s/ingress/phonebill-ingress.yaml b/deployment/k8s/ingress/phonebill-ingress.yaml
new file mode 100644
index 0000000..c05d65b
--- /dev/null
+++ b/deployment/k8s/ingress/phonebill-ingress.yaml
@@ -0,0 +1,25 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: phonebill-ingress
+ namespace: phonebill
+ labels:
+ app.kubernetes.io/part-of: phonebill
+ annotations:
+ nginx.ingress.kubernetes.io/proxy-body-size: "50m"
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
+spec:
+ ingressClassName: nginx
+ rules:
+ - host: phonebill-api.72.155.72.236.nip.io
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: api-gateway
+ port:
+ number: 8080
diff --git a/deployment/k8s/kos-mock/cm-kos-mock.yaml b/deployment/k8s/kos-mock/cm-kos-mock.yaml
deleted file mode 100644
index 3e55476..0000000
--- a/deployment/k8s/kos-mock/cm-kos-mock.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: cm-kos-mock
-data:
- SERVER_PORT: "8084"
\ No newline at end of file
diff --git a/deployment/k8s/kos-mock/service.yaml b/deployment/k8s/kos-mock/service.yaml
deleted file mode 100644
index fdb5336..0000000
--- a/deployment/k8s/kos-mock/service.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: kos-mock
-spec:
- selector:
- app: kos-mock
- ports:
- - port: 80
- targetPort: 8084
- type: ClusterIP
\ No newline at end of file
diff --git a/deployment/k8s/product-service/cm-product-service.yaml b/deployment/k8s/product-service/cm-product-service.yaml
deleted file mode 100644
index 5a3893d..0000000
--- a/deployment/k8s/product-service/cm-product-service.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: cm-product-service
-data:
- SERVER_PORT: "8083"
- DB_KIND: "postgresql"
- DB_PORT: "5432"
- KOS_BASE_URL: "http://kos-mock"
- REDIS_DATABASE: "2"
\ No newline at end of file
diff --git a/deployment/k8s/product-service/secret-product-service.yaml b/deployment/k8s/product-service/secret-product-service.yaml
deleted file mode 100644
index e773ec9..0000000
--- a/deployment/k8s/product-service/secret-product-service.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: secret-product-service
-type: Opaque
-stringData:
- DB_HOST: "product-change-postgres-dev-postgresql"
- DB_NAME: "product_change_db"
- DB_USERNAME: "product_change_user"
- DB_PASSWORD: "ProductUser2025@"
\ No newline at end of file
diff --git a/deployment/k8s/product-service/service.yaml b/deployment/k8s/product-service/service.yaml
deleted file mode 100644
index b784a5d..0000000
--- a/deployment/k8s/product-service/service.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: product-service
-spec:
- selector:
- app: product-service
- ports:
- - port: 80
- targetPort: 8083
- type: ClusterIP
\ No newline at end of file
diff --git a/deployment/k8s/secrets/bill-service-db-secret.yaml b/deployment/k8s/secrets/bill-service-db-secret.yaml
new file mode 100644
index 0000000..64245b9
--- /dev/null
+++ b/deployment/k8s/secrets/bill-service-db-secret.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: bill-service-db-secret
+ namespace: phonebill
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
+type: Opaque
+stringData:
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/k8s/secrets/common-secret.yaml b/deployment/k8s/secrets/common-secret.yaml
new file mode 100644
index 0000000..6fc3772
--- /dev/null
+++ b/deployment/k8s/secrets/common-secret.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: phonebill-common-secret
+ namespace: phonebill
+ labels:
+ app.kubernetes.io/part-of: phonebill
+type: Opaque
+stringData:
+ # JWT Secret (최소 256비트 이상, HS256 알고리즘용)
+ JWT_SECRET: "EK1ZV7vROOXREXbYe/BCISdQq0Yklk9JtoA2v88ux1DBDc0bDGiRRxHeDSb7GHkDP9IUYHMVsBi4/1rS4OhfRg=="
+ # Redis 비밀번호 (비밀번호 없는 경우 빈 값)
+ REDIS_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/k8s/secrets/product-service-db-secret.yaml b/deployment/k8s/secrets/product-service-db-secret.yaml
new file mode 100644
index 0000000..aae620c
--- /dev/null
+++ b/deployment/k8s/secrets/product-service-db-secret.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: product-service-db-secret
+ namespace: phonebill
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
+type: Opaque
+stringData:
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/k8s/secrets/user-service-db-secret.yaml b/deployment/k8s/secrets/user-service-db-secret.yaml
new file mode 100644
index 0000000..2464171
--- /dev/null
+++ b/deployment/k8s/secrets/user-service-db-secret.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: user-service-db-secret
+ namespace: phonebill
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
+type: Opaque
+stringData:
+ DB_USERNAME: "unicorn"
+ DB_PASSWORD: "P@ssw0rd$"
diff --git a/deployment/k8s/api-gateway/service.yaml b/deployment/k8s/services/api-gateway.yaml
similarity index 50%
rename from deployment/k8s/api-gateway/service.yaml
rename to deployment/k8s/services/api-gateway.yaml
index e1f6460..21e6dba 100644
--- a/deployment/k8s/api-gateway/service.yaml
+++ b/deployment/k8s/services/api-gateway.yaml
@@ -2,10 +2,16 @@ apiVersion: v1
kind: Service
metadata:
name: api-gateway
+ namespace: phonebill
+ labels:
+ app: api-gateway
+ app.kubernetes.io/part-of: phonebill
spec:
+ type: ClusterIP
selector:
app: api-gateway
ports:
- - port: 80
+ - name: http
+ port: 8080
targetPort: 8080
- type: ClusterIP
+ protocol: TCP
diff --git a/deployment/k8s/services/bill-service.yaml b/deployment/k8s/services/bill-service.yaml
new file mode 100644
index 0000000..12dc0ef
--- /dev/null
+++ b/deployment/k8s/services/bill-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: bill-service
+ namespace: phonebill
+ labels:
+ app: bill-service
+ app.kubernetes.io/part-of: phonebill
+spec:
+ type: ClusterIP
+ selector:
+ app: bill-service
+ ports:
+ - name: http
+ port: 8082
+ targetPort: 8082
+ protocol: TCP
diff --git a/deployment/k8s/services/kos-mock.yaml b/deployment/k8s/services/kos-mock.yaml
new file mode 100644
index 0000000..b912ff2
--- /dev/null
+++ b/deployment/k8s/services/kos-mock.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: kos-mock
+ namespace: phonebill
+ labels:
+ app: kos-mock
+ app.kubernetes.io/part-of: phonebill
+spec:
+ type: ClusterIP
+ selector:
+ app: kos-mock
+ ports:
+ - name: http
+ port: 8084
+ targetPort: 8084
+ protocol: TCP
diff --git a/deployment/k8s/services/product-service.yaml b/deployment/k8s/services/product-service.yaml
new file mode 100644
index 0000000..10bc374
--- /dev/null
+++ b/deployment/k8s/services/product-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: product-service
+ namespace: phonebill
+ labels:
+ app: product-service
+ app.kubernetes.io/part-of: phonebill
+spec:
+ type: ClusterIP
+ selector:
+ app: product-service
+ ports:
+ - name: http
+ port: 8083
+ targetPort: 8083
+ protocol: TCP
diff --git a/deployment/k8s/services/user-service.yaml b/deployment/k8s/services/user-service.yaml
new file mode 100644
index 0000000..f782c5d
--- /dev/null
+++ b/deployment/k8s/services/user-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: user-service
+ namespace: phonebill
+ labels:
+ app: user-service
+ app.kubernetes.io/part-of: phonebill
+spec:
+ type: ClusterIP
+ selector:
+ app: user-service
+ ports:
+ - name: http
+ port: 8081
+ targetPort: 8081
+ protocol: TCP
diff --git a/deployment/k8s/user-service/cm-user-service.yaml b/deployment/k8s/user-service/cm-user-service.yaml
deleted file mode 100644
index 4031913..0000000
--- a/deployment/k8s/user-service/cm-user-service.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: cm-user-service
-data:
- SERVER_PORT: "8081"
- DB_KIND: "postgresql"
- DB_PORT: "5432"
- DDL_AUTO: "update"
- REDIS_DATABASE: "0"
- SHOW_SQL: "true"
\ No newline at end of file
diff --git a/deployment/k8s/user-service/secret-user-service.yaml b/deployment/k8s/user-service/secret-user-service.yaml
deleted file mode 100644
index 8424423..0000000
--- a/deployment/k8s/user-service/secret-user-service.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: secret-user-service
-type: Opaque
-stringData:
- DB_HOST: "auth-postgres-dev-postgresql"
- DB_NAME: "phonebill_auth"
- DB_USERNAME: "auth_user"
- DB_PASSWORD: "AuthUser2025@"
\ No newline at end of file
diff --git a/deployment/k8s/user-service/service.yaml b/deployment/k8s/user-service/service.yaml
deleted file mode 100644
index c9fb9cf..0000000
--- a/deployment/k8s/user-service/service.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: user-service
-spec:
- selector:
- app: user-service
- ports:
- - port: 80
- targetPort: 8081
- type: ClusterIP
\ No newline at end of file
diff --git a/develop/database/exec/auth-postgres-values.yaml b/develop/database/exec/auth-postgres-values.yaml
index 9acf0d9..b5daa25 100644
--- a/develop/database/exec/auth-postgres-values.yaml
+++ b/develop/database/exec/auth-postgres-values.yaml
@@ -7,7 +7,7 @@ global:
database: "phonebill_auth"
username: "auth_user"
password: "AuthUser2025@"
- storageClass: "managed"
+ storageClass: "standard"
# Primary 설정 (개발환경 단독 구성)
architecture: standalone
@@ -25,7 +25,7 @@ primary:
# 스토리지 설정
persistence:
enabled: true
- storageClass: "managed"
+ storageClass: "standard"
size: 20Gi
# PostgreSQL 성능 설정 (개발환경 최적화)
diff --git a/develop/database/exec/bill-inquiry-postgres-values.yaml b/develop/database/exec/bill-inquiry-postgres-values.yaml
index 5dc4e26..5dd3aed 100644
--- a/develop/database/exec/bill-inquiry-postgres-values.yaml
+++ b/develop/database/exec/bill-inquiry-postgres-values.yaml
@@ -7,7 +7,7 @@ global:
database: "bill_inquiry_db"
username: "bill_inquiry_user"
password: "BillUser2025@"
- storageClass: "managed"
+ storageClass: "standard"
# Primary 설정 (개발환경 단독 구성)
architecture: standalone
@@ -25,7 +25,7 @@ primary:
# 스토리지 설정
persistence:
enabled: true
- storageClass: "managed"
+ storageClass: "standard"
size: 20Gi
# PostgreSQL 성능 설정 (개발환경 최적화)
diff --git a/develop/database/exec/product-change-postgres-values.yaml b/develop/database/exec/product-change-postgres-values.yaml
index 21db70c..8fc7b34 100644
--- a/develop/database/exec/product-change-postgres-values.yaml
+++ b/develop/database/exec/product-change-postgres-values.yaml
@@ -7,7 +7,7 @@ global:
database: "product_change_db"
username: "product_change_user"
password: "ProductUser2025@"
- storageClass: "managed"
+ storageClass: "standard"
# Primary 설정 (개발환경 단독 구성)
architecture: standalone
@@ -25,7 +25,7 @@ primary:
# 스토리지 설정
persistence:
enabled: true
- storageClass: "managed"
+ storageClass: "standard"
size: 20Gi
# PostgreSQL 성능 설정 (개발환경 최적화)
diff --git a/develop/database/exec/redis-cache-values.yaml b/develop/database/exec/redis-cache-values.yaml
index 6170e19..059d24c 100644
--- a/develop/database/exec/redis-cache-values.yaml
+++ b/develop/database/exec/redis-cache-values.yaml
@@ -1,7 +1,7 @@
# values.yaml - Redis Cache 개발환경 설정
# Redis 기본 설정
global:
- storageClass: "managed"
+ storageClass: "standard"
# 아키텍처 (개발환경 단일 구성)
architecture: standalone
diff --git a/kos-mock/data/kos_mock.mv.db b/kos-mock/data/kos_mock.mv.db
index 1912b3a..974dd1a 100644
Binary files a/kos-mock/data/kos_mock.mv.db and b/kos-mock/data/kos_mock.mv.db differ
diff --git a/kos-mock/data/kos_mock.trace.db b/kos-mock/data/kos_mock.trace.db
deleted file mode 100644
index bd3eb23..0000000
--- a/kos-mock/data/kos_mock.trace.db
+++ /dev/null
@@ -1,1312 +0,0 @@
-2025-09-09 16:44:37.343275+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:61)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
- at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
- at org.hibernate.boot.model.relational.Database.(Database.java:45)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189)
- at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 149 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 143 more
-2025-09-09 16:44:38.915218+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:39)
- at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63)
- at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43)
- at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.(DatabaseInformationImpl.java:60)
- at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185)
- at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:98)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:280)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144)
- at java.base/java.util.HashMap.forEach(HashMap.java:1429)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:141)
- at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37)
- at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35)
- at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:322)
- at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:457)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 153 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 147 more
-2025-09-09 16:44:40.401986+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:61)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
- at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
- at org.hibernate.boot.model.relational.Database.(Database.java:45)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189)
- at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 149 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 143 more
-2025-09-09 16:44:41.479340+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:39)
- at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63)
- at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43)
- at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.(DatabaseInformationImpl.java:60)
- at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185)
- at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:98)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:280)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144)
- at java.base/java.util.HashMap.forEach(HashMap.java:1429)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:141)
- at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37)
- at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35)
- at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:322)
- at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:457)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 153 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 147 more
-2025-09-09 16:45:23.324975+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:61)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
- at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
- at org.hibernate.boot.model.relational.Database.(Database.java:45)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189)
- at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 149 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 143 more
-2025-09-09 16:45:24.882303+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:39)
- at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63)
- at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43)
- at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.(DatabaseInformationImpl.java:60)
- at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185)
- at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:98)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:280)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144)
- at java.base/java.util.HashMap.forEach(HashMap.java:1429)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:141)
- at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37)
- at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35)
- at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:322)
- at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:457)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 153 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 147 more
-2025-09-09 16:45:26.315245+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:61)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
- at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
- at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
- at org.hibernate.boot.model.relational.Database.(Database.java:45)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221)
- at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:189)
- at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 149 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 143 more
-2025-09-09 16:45:27.401788+09:00 database: flush
-org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.get(DbException.java:212)
- at org.h2.message.DbException.convert(DbException.java:407)
- at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
- at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
- at org.h2.mvstore.MVStore.panic(MVStore.java:371)
- at org.h2.mvstore.MVStore.(MVStore.java:291)
- at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
- at org.h2.mvstore.db.Store.(Store.java:133)
- at org.h2.engine.Database.(Database.java:326)
- at org.h2.engine.Engine.openSession(Engine.java:92)
- at org.h2.engine.Engine.openSession(Engine.java:222)
- at org.h2.engine.Engine.createSession(Engine.java:201)
- at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
- at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:125)
- at org.h2.Driver.connect(Driver.java:59)
- at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
- at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
- at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
- at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
- at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
- at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:98)
- at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
- at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
- at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46)
- at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:39)
- at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63)
- at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43)
- at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66)
- at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.(DatabaseInformationImpl.java:60)
- at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185)
- at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:98)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:280)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144)
- at java.base/java.util.HashMap.forEach(HashMap.java:1429)
- at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:141)
- at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37)
- at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35)
- at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:322)
- at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:457)
- at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506)
- at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
- at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
- at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
- at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
- at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
- at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
- at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
- at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
- at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
- at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463)
- at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
- at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)
- at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)
- at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
- at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378)
- at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
- at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
- at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
- at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
- at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
- at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
- at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
- at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279)
- at java.base/java.util.Optional.orElseGet(Optional.java:364)
- at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278)
- at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105)
- at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
- at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
- at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
- at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
- at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
- at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
- at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
- at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
- at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:124)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:99)
- at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:94)
- at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
- at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
- at java.base/java.lang.reflect.Method.invoke(Method.java:580)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
- at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
- at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
- at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
- at jdk.proxy1/jdk.proxy1.$Proxy4.stop(Unknown Source)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:200)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
- at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
- at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
- at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
- at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
-Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]" [50000-224]
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
- at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
- ... 153 more
-Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/dreamondal/home/workspace/phonebill/kos-mock/data/kos_mock.mv.db [2.2.224/7]
- at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
- at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
- at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
- at org.h2.mvstore.MVStore.(MVStore.java:286)
- ... 147 more
diff --git a/product-service/.run/product-service.run.xml b/product-service/.run/product-service.run.xml
index 86da7b1..48e3823 100644
--- a/product-service/.run/product-service.run.xml
+++ b/product-service/.run/product-service.run.xml
@@ -6,10 +6,10 @@
-
-
+
+
-
+
@@ -20,8 +20,8 @@
-
-
+
+
diff --git a/user-service/.run/user-service.run.xml b/user-service/.run/user-service.run.xml
index a074ffa..254be8b 100644
--- a/user-service/.run/user-service.run.xml
+++ b/user-service/.run/user-service.run.xml
@@ -6,18 +6,18 @@
-
-
+
+
-
+
-
-
+
+