Skip to content

[AIP-3127] feat: 프로젝트 삭제 시 해당 프로젝트의 템플릿 정리 - #120

Merged
juu-n-oo merged 4 commits into
developfrom
feature/AIP-3127
Sep 10, 2026
Merged

juu-n-oo merged 4 commits into
developfrom
feature/AIP-3127

Conversation

@joonseolee

Copy link
Copy Markdown
Member

Summary

  • project CR 이 삭제될 때 그 프로젝트에 속한 템플릿을 aipub-backend 에 요청해 함께 정리한다
  • template 의 SoT 는 DB, project 의 SoT 는 k8s 라 두 저장소의 생명주기가 어긋나 있던 문제를 맞춘다
  • 템플릿 삭제 요청이 실패해도 프로젝트 삭제와 나머지 reconcile 은 계속 진행한다(best-effort)
  • 앞으로 늘어날 v1alpha2 API 를 위해 전용 ApiClient 를 분리한다

변경 내용

domain/aipubbackend — 백엔드 호출

TemplateService / TemplateServiceImpl 추가.

DELETE /api/v1alpha2/templates?projectName={name}  ->  204

기존 ImageHubService, RepositoryService 와 동일하게 ApiClient.buildCall + CallHelper 패턴을 따른다.

configuration — v1alpha2 클라이언트 분리

AipubConfiguration 이 만들던 ApiClient 는 basePath 가 /api/v1alpha1 로 고정이었다. 신규 엔드포인트가 v1alpha2 라 전용 클라이언트를 하나 더 둔다.

  • 인증(basic auth)·SSL 설정은 기존과 동일하고 basePath 만 다르다
  • 생성 로직은 buildClient(properties, basePath) 로 묶어 중복을 없앴다
  • 앞으로 추가될 v1alpha2 API 도 이 클라이언트를 재사용한다
  • app.aipub.enabled=false 면 기존 서비스들과 같이 no-op 으로 동작한다 — 신규 설정값은 없다

controller/cr — 삭제 훅

ProjectReconciler.reconcileTerminatingProject() 에서 네임스페이스가 정리된 뒤 finalizer 를 떼기 직전에 템플릿 삭제를 요청한다.

호출은 try/catch 로 감싼다. 근거:

  • 백엔드 장애가 project 를 Terminating 에 묶어두면 안 된다
  • 같은 reconcile 루프의 finalizer 제거·상태 갱신까지 함께 중단되면 안 된다
  • 여기서 놓친 템플릿은 aipub-backend 의 고아 템플릿 정리 배치가 주기적으로 회수한다

관련 변경

AIP-3127 은 두 저장소에 걸쳐 있다.

  • 이 PR: project CR 삭제 시 삭제 API 호출 (TO-BE 1)
  • ten1010-io/aipub-backend feature/AIP-3127: 삭제 API 신설 + 고아 템플릿 정리 배치 (TO-BE 2)

배포 순서: aipub-backend 가 먼저 떠 있어야 이 호출이 404 를 받지 않는다. 순서가 뒤집혀도 best-effort 라 장애로 번지지는 않고 배치가 회수한다.

Test plan

  • ./gradlew clean build 통과 (전 모듈)
  • 프로젝트가 삭제되면 그 프로젝트의 템플릿도 함께 정리한다
  • 템플릿 정리에 실패해도 프로젝트 삭제는 멈추지 않는다
  • 삭제 중이 아닌 프로젝트는 템플릿을 건드리지 않는다
  • 백엔드 엔드포인트 실호출 검증 (로컬 격리 환경, 운영 무접촉)
    • ?projectName=alive-project → 204, 대상만 삭제
    • ?projectName=no-such → 204 (대상 없어도 성공)
    • 파라미터 누락 → 400
  • 실제 클러스터에서 project CR 삭제 후 템플릿 정리 확인 (미수행)
  • 백엔드 다운 상태에서 project 삭제가 정상 완료되는지 확인 (미수행 — 단위 테스트로만 검증)

template 의 SoT 는 DB, project 의 SoT 는 k8s 라 project CR 이 삭제돼도 그 프로젝트의
template 이 DB 에 그대로 남아 있었다. 프로젝트가 사라지는 시점에 aipub-backend 에
템플릿 삭제를 요청해 두 저장소의 생명주기를 맞춘다.

- TemplateService / TemplateServiceImpl 추가
  DELETE /api/v1alpha2/templates?projectName={name}
- AipubConfiguration: v1alpha2 전용 ApiClient 를 별도로 둔다. 인증·SSL 은 기존과 같고
  basePath 만 다르며, 앞으로 늘어날 v1alpha2 API 도 이 클라이언트를 재사용한다.
  aipub 연동이 꺼져 있으면 기존 서비스들과 같이 no-op 으로 동작한다.
- ProjectReconciler: 네임스페이스가 정리된 뒤 finalizer 를 떼기 직전에 템플릿 삭제를
  요청한다. 요청이 실패해도 예외를 전파하지 않아 프로젝트가 Terminating 에 묶이거나
  나머지 reconcile 이 중단되지 않는다. 놓친 템플릿은 aipub-backend 의 고아 템플릿
  정리 배치가 회수한다.
AIP-2317 이 aipub-backend 호출을 Basic 인증에서 mTLS 로 바꾸면서 이 브랜치가
쓰던 buildClient(Basic 인증) 방식이 사라졌다. 충돌을 mTLS 팩토리 쪽으로 해소한다.

- AipubBackendClientFactory.create 에 basePath 파라미터 추가.
  v1alpha1/v1alpha2 두 클라이언트가 같은 mTLS 설정을 공유하고 basePath 만 달라진다
- AipubConfiguration.buildClient 는 팩토리 위임으로 축소. Basic 인증 코드 제거
- Dockerfile 정리(AIP-3158)와 형태 통일 — 인터페이스 설명·훅 주석·로그 문구·
  테스트 네이밍(<상황>_<기대>)을 같은 모양으로 맞췄다
코드리뷰 지적 반영.

- AipubBackendClientFactory: callTimeout 5초. OkHttp 기본값이 무제한이라
  응답 없는 백엔드가 reconcile 워커(1개)를 무한정 잡을 수 있었다
- AipubBackendResponseException: content-type 헤더가 없는 non-2xx 응답에서
  Map.get 의 null 을 빈 리스트로 오인해 NPE 가 났다. 정작 필요한 statusCode 가
  로그에서 사라지던 문제 (기존 버그, 신규 테스트가 잡음)
- TemplateServiceImplTest 신설: 경로·메서드·쿼리 파라미터명 계약을 고정한다.
  호출부가 best-effort 라 계약이 어긋나도 조용히 삼켜지므로 코드로 막는다
- ProjectControllerFactory: 쓰이지 않는 @AllArgsConstructor 제거.
  필드를 추가할 때마다 생성자 시그니처가 조용히 바뀌던 것을 막는다
AIP-3158(Dockerfile 정리) 머지로 같은 4개 파일이 겹쳐 재충돌. 양쪽을 모두 살린다.

- ProjectReconciler / ProjectControllerFactory / ControllerConfiguration:
  dockerfileService · templateService 두 의존성을 나란히 받는다
- reconcileTerminatingProject: project 이름을 지역변수로 뽑아 두 정리 훅에 넘긴다
- 두 정리 테스트: 관심 밖 서비스는 목으로 채워 생성자 변경에 맞춘다
@juu-n-oo
juu-n-oo merged commit bb52bfa into develop Sep 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants