Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions app/extensions/db/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ def get_by_user_challenge_name(self, userChallengeName: str) -> Optional[UserCha
Returns:
UserChallenges: 사용자 챌린지
"""
return UserChallenges.query.filter_by(userChallengeName=userChallengeName).first()
user_challenge = UserChallenges.query.filter_by(userChallengeName=userChallengeName).first()
if not user_challenge:
raise InternalServerError(error_msg=f"User challenge {userChallengeName} not found")
return user_challenge


def update_status(self, challenge: UserChallenges, new_status: str) -> bool:
"""
Expand All @@ -73,7 +77,7 @@ def update_status(self, challenge: UserChallenges, new_status: str) -> bool:
except SQLAlchemyError as e:
# logger.error(f"Error updating challenge status: {e}")
self.session.rollback()
return False
raise InternalServerError(error_msg=f"Error updating challenge status: {e}") from e

def update_port(self, challenge: UserChallenges, port: int) -> bool:
"""
Expand Down
131 changes: 66 additions & 65 deletions app/extensions/k8s/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,86 +48,87 @@ def create_challenge_resource(self, challenge_id, username, namespace="default")
ChallengeCreationError: Challenge Custom Resource 생성에 실패했을 때

"""
try:
user_challenge_repo = UserChallengesRepository()

user_challenge_repo = UserChallengesRepository()

# Challenge definition 조회
challenge_definition = ChallengeRepository.get_challenge_name(challenge_id)
if not challenge_definition:
raise ChallengeNotFound(error_msg=f"Challenge definition not found for ID: {challenge_id}")
# Challenge definition 조회
challenge_definition = ChallengeRepository.get_challenge_name(challenge_id)
if not challenge_definition:
raise ChallengeNotFound(error_msg=f"Challenge definition not found for ID: {challenge_id}")

# Challenge name 생성 및 검증
challenge_name = f"challenge-{challenge_id}-{username}"
if not self._is_valid_k8s_name(challenge_name):
raise UserChallengeCreationError(error_msg=f"Invalid challenge name: {challenge_name}")
# Challenge name 생성 및 검증
challenge_name = f"challenge-{challenge_id}-{username}"
if not self._is_valid_k8s_name(challenge_name):
raise UserChallengeCreationError(error_msg=f"Invalid challenge name: {challenge_name}")

# Namespace 존재 여부 확인
try:
self.core_api.read_namespace(namespace)
except Exception as e:
raise UserChallengeCreationError(error_msg=str(e))
# Namespace 존재 여부 확인
try:
self.core_api.read_namespace(namespace)
except Exception as e:
raise UserChallengeCreationError(error_msg=str(e))

# Database에 UserChallenge 생성
user_challenge = user_challenge_repo.get_by_user_challenge_name(challenge_name)
if not user_challenge:
user_challenge = user_challenge_repo.create(username, challenge_id, challenge_name, 0)
else:
# 이미 실행 중인 Challenge가 있으면 데이터베이스에 저장된 포트 번호 반환
if user_challenge.status == 'Running':
return user_challenge.port
# Database에 UserChallenge 생성
user_challenge = user_challenge_repo.get_by_user_challenge_name(challenge_name)
if not user_challenge:
user_challenge = user_challenge_repo.create(username, challenge_id, challenge_name, 0)
else:
# 이미 실행 중인 Challenge가 있으면 데이터베이스에 저장된 포트 번호 반환
if user_challenge.status == 'Running':
return user_challenge.port

# Challenge manifest 생성
challenge_manifest = {
"apiVersion": "apps.hexactf.io/v1alpha1",
"kind": "Challenge",
"metadata": {
"name": challenge_name,
"labels": {
"apps.hexactf.io/challengeId": str(challenge_id),
"apps.hexactf.io/user": username
}
},
"spec": {
"namespace": namespace,
"definition": challenge_definition
# Challenge manifest 생성
challenge_manifest = {
"apiVersion": "apps.hexactf.io/v1alpha1",
"kind": "Challenge",
"metadata": {
"name": challenge_name,
"labels": {
"apps.hexactf.io/challengeId": str(challenge_id),
"apps.hexactf.io/user": username
}
},
"spec": {
"namespace": namespace,
"definition": challenge_definition
}
}

challenge = self.custom_api.create_namespaced_custom_object(
challenge = self.custom_api.create_namespaced_custom_object(
group="apps.hexactf.io",
version="v1alpha1",
namespace=namespace,
plural="challenges",
body=challenge_manifest
)

# status 값 가져오기
status = challenge.get('status', {})
endpoint = status.get('endpoint')

# status가 아직 설정되지 않았을 수 있으므로, 필요한 경우 다시 조회
if not status:
time.sleep(3)
challenge = self.custom_api.get_namespaced_custom_object(
group="apps.hexactf.io",
version="v1alpha1",
namespace=namespace,
plural="challenges",
body=challenge_manifest
name=challenge['metadata']['name']
)

# status 값 가져오기
status = challenge.get('status', {})
endpoint = status.get('endpoint')

# status가 아직 설정되지 않았을 수 있으므로, 필요한 경우 다시 조회
if not status:
time.sleep(3)
challenge = self.custom_api.get_namespaced_custom_object(
group="apps.hexactf.io",
version="v1alpha1",
namespace=namespace,
plural="challenges",
name=challenge['metadata']['name']
)
status = challenge.get('status', {})
endpoint = status.get('endpoint')

# NodePort 업데이트
if endpoint:
success = user_challenge_repo.update_port(user_challenge, int(endpoint))
if not success:
raise UserChallengeCreationError(error_msg=f"Failed to update UserChallenge with NodePort: {endpoint}")


return endpoint
except Exception as e:
raise UserChallengeCreationError(error_msg=str(e)) from e

# NodePort 업데이트
if not endpoint:
raise UserChallengeCreationError(error_msg=f"Failed to get NodePort for Challenge: {challenge_name}")

success = user_challenge_repo.update_port(user_challenge, int(endpoint))
if not success:
raise UserChallengeCreationError(error_msg=f"Failed to update UserChallenge with NodePort: {endpoint}")

return endpoint




def _is_valid_k8s_name(self, name: str) -> bool:
Expand Down