From 556a4f43a9cc4d8e7a3ba6c04231e2082a1d9c3b Mon Sep 17 00:00:00 2001 From: jung-geun Date: Thu, 5 Jun 2025 19:15:32 +0900 Subject: [PATCH 1/2] =?UTF-8?q?README.md=20=EB=B0=8F=20cloud-init=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=EC=9D=98=20=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=EB=A1=9C=EB=93=9C=20URL=EC=9D=84=20GitHub=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=98=EC=97=AC=20=EC=B5=9C=EC=8B=A0=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84=EC=9C=BC=EB=A1=9C=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- pbr-script-cloud-init.yaml | 2 +- policy_routing.py | 82 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 468c7a2..8305879 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ NIC 의 ip 설정이 미리 되어 있어야 합니다. 스크립트는 아래 명령어로 다운로드 받을 수 있습니다 ```bash -wget -O policy_routing.py https://git.dmslab.xyz/dmslab/policy-routing/-/raw/v0.3/policy_routing.py +wget -O policy_routing.py https://raw.githubusercontent.com/jung-geun/policy-routing/main/policy_routing.py # or -curl -o policy_routing.py https://git.dmslab.xyz/dmslab/policy-routing/-/raw/v0.3/policy_routing.py +curl -o policy_routing.py https://raw.githubusercontent.com/jung-geun/policy-routing/main/policy_routing.py ``` 다운로드한 스크립트를 setup 옵션으로 시스템 데몬으로 설치할 수 있습니다 diff --git a/pbr-script-cloud-init.yaml b/pbr-script-cloud-init.yaml index b713c47..4f5caa6 100644 --- a/pbr-script-cloud-init.yaml +++ b/pbr-script-cloud-init.yaml @@ -10,7 +10,7 @@ write_files: # GitLab 스크립트 URL (공개 저장소 또는 접근 가능한 URL) # 예시: GitLab Pages, Raw 파일 URL 등 # private repository인 경우 인증 관련 부분을 추가해야 합니다. (아래 설명) - SCRIPT_URL="https://git.dmslab.xyz/dmslab/policy-routing/-/raw/v0.3/policy_routing.py" + SCRIPT_URL="https://raw.githubusercontent.com/jung-geun/policy-routing/v0.3/policy_routing.py" DEST_PATH="/opt/PBR/routing.py" # 스크립트 저장될 디렉토리 생성 (필요하다면) diff --git a/policy_routing.py b/policy_routing.py index bb0547f..99ca2be 100755 --- a/policy_routing.py +++ b/policy_routing.py @@ -4,6 +4,8 @@ Ubuntu 22.04 Multi-NIC Policy Based Routing Setup Script Python Implementation """ +__version__ = "0.3" # 현재 스크립트 버전 + import subprocess import logging import os @@ -13,6 +15,7 @@ import re import ipaddress from datetime import datetime from pathlib import Path +import requests # requests 라이브러리 추가 class PolicyBasedRoutingManager: @@ -31,6 +34,7 @@ class PolicyBasedRoutingManager: # 네트워크 인터페이스 설정 (초기에는 비워둠) self.config = {"nics": {}} + self.github_repo_url = "https://raw.githubusercontent.com/jung-geun/policy-routing/main/policy_routing.py" def run_command(self, cmd, ignore_error=False): """시스템 명령어 실행""" @@ -44,6 +48,78 @@ class PolicyBasedRoutingManager: self.logger.error(f"명령어 실행 실패: {cmd} - {e}") return None + def get_latest_version(self): + """GitHub에서 최신 버전 정보 가져오기""" + try: + response = requests.get(self.github_repo_url) + response.raise_for_status() # HTTP 오류 발생 시 예외 발생 + + # 파일 내용에서 __version__ 라인 찾기 + for line in response.text.splitlines(): + if "__version__" in line: + match = re.search(r'__version__\s*=\s*["\'](\d+\.\d+\.\d+)["\']', line) + if match: + return match.group(1) + return None + except requests.exceptions.RequestException as e: + self.logger.error(f"최신 버전 정보를 가져오는 데 실패했습니다: {e}") + return None + + def check_for_updates(self): + """업데이트 확인 및 사용자에게 알림""" + self.logger.info("최신 버전 확인 중...") + latest_version = self.get_latest_version() + current_version = __version__ + + if latest_version: + self.logger.info(f"현재 버전: {current_version}, 최신 버전: {latest_version}") + + # 버전 비교 (간단한 문자열 비교, 실제로는 semantic versioning 라이브러리 사용 권장) + if latest_version > current_version: + self.logger.info("새로운 버전이 사용 가능합니다!") + response = input("업데이트를 진행하시겠습니까? (y/N): ") + if response.lower() == "y": + return True + else: + self.logger.info("업데이트가 취소되었습니다.") + return False + else: + self.logger.info("현재 최신 버전을 사용 중입니다.") + return False + else: + self.logger.warning("최신 버전 정보를 가져올 수 없어 업데이트 확인을 건너뜁니다.") + return False + + def perform_update(self): + """스크립트를 최신 버전으로 업데이트""" + self.logger.info("스크립트 업데이트를 시작합니다...") + try: + response = requests.get(self.github_repo_url) + response.raise_for_status() # HTTP 오류 발생 시 예외 발생 + + script_content = response.text + current_script_path = Path(sys.argv[0]) # 현재 실행 중인 스크립트의 경로 + + # 현재 스크립트 파일을 백업 + backup_path = current_script_path.with_suffix(f".py.bak_{datetime.now().strftime('%Y%m%d%H%M%S')}") + current_script_path.rename(backup_path) + self.logger.info(f"현재 스크립트 백업 완료: {backup_path}") + + # 최신 내용으로 스크립트 파일 덮어쓰기 + with open(current_script_path, "w") as f: + f.write(script_content) + + # 실행 권한 유지 + current_script_path.chmod(0o755) + + self.logger.info("스크립트 업데이트가 성공적으로 완료되었습니다. 스크립트를 다시 실행해주세요.") + sys.exit(0) # 업데이트 후 스크립트 재시작을 위해 종료 + except requests.exceptions.RequestException as e: + self.logger.error(f"스크립트 다운로드 실패: {e}") + except Exception as e: + self.logger.error(f"스크립트 업데이트 중 오류 발생: {e}") + return False + def get_network_interfaces(self): """활성화된 네트워크 인터페이스 목록 가져오기""" interfaces = {} @@ -65,6 +141,7 @@ class PolicyBasedRoutingManager: and not interface.startswith("docker") and not interface.startswith("veth") and not interface.startswith("br-") + and not interface.startswith("ovs-") and "state UP" in line ): interfaces[interface] = {} @@ -858,6 +935,11 @@ def main(): manager = PolicyBasedRoutingManager() + # 스크립트 시작 시 업데이트 확인 + if manager.check_for_updates(): + manager.perform_update() + # perform_update는 성공 시 sys.exit(0)을 호출하므로, 이 아래 코드는 실행되지 않음 + if args.action == "setup": manager.setup(force=args.force) elif args.action == "remove": From 2fabaf865a5ffc3747706d39c6305dbf8d99f109 Mon Sep 17 00:00:00 2001 From: jung-geun Date: Fri, 6 Jun 2025 20:44:36 +0900 Subject: [PATCH 2/2] =?UTF-8?q?GitLab=20CI=20=EA=B5=AC=EC=84=B1=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8:=20=EB=B9=8C=EB=93=9C=20?= =?UTF-8?q?=EB=8B=A8=EA=B3=84=EC=97=90=20SonarQube=20=EB=B6=84=EC=84=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EA=B4=80=EB=A0=A8=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitlab-ci.yml | 32 +++++++++++++------------ .gitlab/ci/sonarqube.gitlab-ci.yml | 26 ++++++++++++++++++++ policy_routing.py | 38 +++++++++++++++++++----------- sonar-project.properties | 2 ++ 4 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 .gitlab/ci/sonarqube.gitlab-ci.yml create mode 100644 sonar-project.properties diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8bc7cf7..f0e67e6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,24 +6,26 @@ # Note that environment variables can be set in several places # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence stages: -- build -- test -- deploy -- review -- dast -- staging -- canary -- production -- incremental rollout 10% -- incremental rollout 25% -- incremental rollout 50% -- incremental rollout 100% -- performance -- cleanup + - build + - build-sonar + - test + - deploy + - review + - dast + - staging + - canary + - production + - incremental rollout 10% + - incremental rollout 25% + - incremental rollout 50% + - incremental rollout 100% + - performance + - cleanup sast: stage: test include: -- template: Auto-DevOps.gitlab-ci.yml + - template: Auto-DevOps.gitlab-ci.yml + - local: .gitlab/ci/*.gitlab-ci.yml python_tests: stage: test diff --git a/.gitlab/ci/sonarqube.gitlab-ci.yml b/.gitlab/ci/sonarqube.gitlab-ci.yml new file mode 100644 index 0000000..9398648 --- /dev/null +++ b/.gitlab/ci/sonarqube.gitlab-ci.yml @@ -0,0 +1,26 @@ +image: + name: sonarsource/sonar-scanner-cli:11 + entrypoint: [""] + +variables: + SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache + GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task + +build-sonar: + stage: build-sonar + + cache: + policy: pull-push + key: "sonar-cache-$CI_COMMIT_REF_SLUG" + paths: + - "${SONAR_USER_HOME}/cache" + - sonar-scanner/ + + script: + - sonar-scanner -Dsonar.host.url="${SONAR_HOST_URL}" + allow_failure: true + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + - if: $CI_COMMIT_BRANCH == 'master' + - if: $CI_COMMIT_BRANCH == 'main' + - if: $CI_COMMIT_BRANCH == 'develop' diff --git a/policy_routing.py b/policy_routing.py index 99ca2be..1f4f237 100755 --- a/policy_routing.py +++ b/policy_routing.py @@ -4,7 +4,7 @@ Ubuntu 22.04 Multi-NIC Policy Based Routing Setup Script Python Implementation """ -__version__ = "0.3" # 현재 스크립트 버전 +__version__ = "0.3" # 현재 스크립트 버전 import subprocess import logging @@ -15,7 +15,7 @@ import re import ipaddress from datetime import datetime from pathlib import Path -import requests # requests 라이브러리 추가 +import requests # requests 라이브러리 추가 class PolicyBasedRoutingManager: @@ -52,12 +52,14 @@ class PolicyBasedRoutingManager: """GitHub에서 최신 버전 정보 가져오기""" try: response = requests.get(self.github_repo_url) - response.raise_for_status() # HTTP 오류 발생 시 예외 발생 - + response.raise_for_status() # HTTP 오류 발생 시 예외 발생 + # 파일 내용에서 __version__ 라인 찾기 for line in response.text.splitlines(): if "__version__" in line: - match = re.search(r'__version__\s*=\s*["\'](\d+\.\d+\.\d+)["\']', line) + match = re.search( + r'__version__\s*=\s*["\'](\d+\.\d+\.\d+)["\']', line + ) if match: return match.group(1) return None @@ -72,8 +74,10 @@ class PolicyBasedRoutingManager: current_version = __version__ if latest_version: - self.logger.info(f"현재 버전: {current_version}, 최신 버전: {latest_version}") - + self.logger.info( + f"현재 버전: {current_version}, 최신 버전: {latest_version}" + ) + # 버전 비교 (간단한 문자열 비교, 실제로는 semantic versioning 라이브러리 사용 권장) if latest_version > current_version: self.logger.info("새로운 버전이 사용 가능합니다!") @@ -87,7 +91,9 @@ class PolicyBasedRoutingManager: self.logger.info("현재 최신 버전을 사용 중입니다.") return False else: - self.logger.warning("최신 버전 정보를 가져올 수 없어 업데이트 확인을 건너뜁니다.") + self.logger.warning( + "최신 버전 정보를 가져올 수 없어 업데이트 확인을 건너뜁니다." + ) return False def perform_update(self): @@ -95,25 +101,29 @@ class PolicyBasedRoutingManager: self.logger.info("스크립트 업데이트를 시작합니다...") try: response = requests.get(self.github_repo_url) - response.raise_for_status() # HTTP 오류 발생 시 예외 발생 + response.raise_for_status() # HTTP 오류 발생 시 예외 발생 script_content = response.text - current_script_path = Path(sys.argv[0]) # 현재 실행 중인 스크립트의 경로 + current_script_path = Path(sys.argv[0]) # 현재 실행 중인 스크립트의 경로 # 현재 스크립트 파일을 백업 - backup_path = current_script_path.with_suffix(f".py.bak_{datetime.now().strftime('%Y%m%d%H%M%S')}") + backup_path = current_script_path.with_suffix( + f".py.bak_{datetime.now().strftime('%Y%m%d%H%M%S')}" + ) current_script_path.rename(backup_path) self.logger.info(f"현재 스크립트 백업 완료: {backup_path}") # 최신 내용으로 스크립트 파일 덮어쓰기 with open(current_script_path, "w") as f: f.write(script_content) - + # 실행 권한 유지 current_script_path.chmod(0o755) - self.logger.info("스크립트 업데이트가 성공적으로 완료되었습니다. 스크립트를 다시 실행해주세요.") - sys.exit(0) # 업데이트 후 스크립트 재시작을 위해 종료 + self.logger.info( + "스크립트 업데이트가 성공적으로 완료되었습니다. 스크립트를 다시 실행해주세요." + ) + sys.exit(0) # 업데이트 후 스크립트 재시작을 위해 종료 except requests.exceptions.RequestException as e: self.logger.error(f"스크립트 다운로드 실패: {e}") except Exception as e: diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..a9a0c59 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,2 @@ +sonar.projectKey=dmslab_policy-routing_56aaf3b2-bfac-465c-8417-8c99edccf1c2 +sonar.qualitygate.wait=true \ No newline at end of file