# 功能实现

- 增加打包工具
- 优化docker打包结构
- 增加首次强制刷新
This commit is contained in:
yshtcn 2024-06-03 22:55:03 +08:00
parent dd4eb1ec44
commit aba948bc2b
4 changed files with 123 additions and 23 deletions

View File

@ -3,28 +3,33 @@ import json
import requests import requests
import time import time
import shutil import shutil
import logging
from requests.exceptions import RequestException from requests.exceptions import RequestException
from aliyunsdkcore.client import AcsClient from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException, ServerException from aliyunsdkcore.acs_exception.exceptions import ClientException, ServerException
from aliyunsdkecs.request.v20140526 import DescribeSecurityGroupAttributeRequest, AuthorizeSecurityGroupRequest, RevokeSecurityGroupRequest from aliyunsdkecs.request.v20140526 import DescribeSecurityGroupAttributeRequest, AuthorizeSecurityGroupRequest, RevokeSecurityGroupRequest
# 设置日志记录
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
logger = logging.getLogger()
# 从配置文件加载配置信息 # 从配置文件加载配置信息
def load_config(config_file, sample_config_file): def load_config(config_file, sample_config_file):
if not os.path.exists(config_file): if not os.path.exists(config_file):
print(f"配置文件 {config_file} 不存在。") logger.error(f"配置文件 {config_file} 不存在。")
print(f"将从样例配置文件 {sample_config_file} 复制一份。") logger.info(f"将从样例配置文件 {sample_config_file} 复制一份。")
shutil.copy(sample_config_file, config_file) shutil.copy(sample_config_file, config_file)
print(f"请在 {config_file} 中配置您的设置。") logger.info(f"请在 {config_file} 中配置您的设置。")
raise FileNotFoundError(f"配置文件 {config_file} 不存在。") raise FileNotFoundError(f"配置文件 {config_file} 不存在。")
try: try:
with open(config_file, 'r') as file: with open(config_file, 'r') as file:
config = json.load(file) config = json.load(file)
return config return config
except FileNotFoundError: except FileNotFoundError:
print(f"配置文件 {config_file} 未找到。") logger.error(f"配置文件 {config_file} 未找到。")
raise raise
except json.JSONDecodeError: except json.JSONDecodeError:
print(f"配置文件 {config_file} 解析错误。") logger.error(f"配置文件 {config_file} 解析错误。")
raise raise
# 获取IP地址 # 获取IP地址
@ -35,7 +40,7 @@ def get_ip_from_service(url):
ip = response.text.strip() ip = response.text.strip()
return ip return ip
except RequestException as e: except RequestException as e:
print(f"无法从 {url} 获取IP地址: {e}") logger.error(f"无法从 {url} 获取IP地址: {e}")
raise raise
# 获取当前安全组的规则 # 获取当前安全组的规则
@ -49,7 +54,7 @@ def get_security_group_rules(client, security_group_id):
rules = json.loads(response) rules = json.loads(response)
return rules.get('Permissions', {}).get('Permission', []) return rules.get('Permissions', {}).get('Permission', [])
except (ClientException, ServerException) as e: except (ClientException, ServerException) as e:
print(f"无法获取安全组规则: {e}") logger.error(f"无法获取安全组规则: {e}")
raise raise
# 删除带有标记的旧规则 # 删除带有标记的旧规则
@ -67,7 +72,7 @@ def delete_old_rules(client, security_group_id, tag):
request.set_NicType(rule['NicType']) request.set_NicType(rule['NicType'])
client.do_action_with_exception(request) client.do_action_with_exception(request)
except (ClientException, ServerException) as e: except (ClientException, ServerException) as e:
print(f"无法删除旧的安全组规则: {e}") logger.error(f"无法删除旧的安全组规则: {e}")
raise raise
# 更新安全组白名单 # 更新安全组白名单
@ -91,9 +96,9 @@ def update_security_group_white_list(client, security_group_id, ip, ports, tag,
request.set_Priority(priority) request.set_Priority(priority)
response = client.do_action_with_exception(request) response = client.do_action_with_exception(request)
print(str(response, encoding='utf-8')) logger.info(str(response, encoding='utf-8'))
except (ClientException, ServerException) as e: except (ClientException, ServerException) as e:
print(f"无法更新安全组白名单: {e}") logger.error(f"无法更新安全组白名单: {e}")
raise raise
# 记录IP地址到本地文件 # 记录IP地址到本地文件
@ -102,7 +107,7 @@ def record_ip(ip_record_file, ip_records):
with open(ip_record_file, 'w') as file: with open(ip_record_file, 'w') as file:
json.dump(ip_records, file) json.dump(ip_records, file)
except IOError as e: except IOError as e:
print(f"无法写入IP记录文件 {ip_record_file}: {e}") logger.error(f"无法写入IP记录文件 {ip_record_file}: {e}")
raise raise
# 读取本地记录的IP地址 # 读取本地记录的IP地址
@ -115,17 +120,17 @@ def load_ip_records(ip_record_file):
else: else:
return {} return {}
except IOError as e: except IOError as e:
print(f"无法读取IP记录文件 {ip_record_file}: {e}") logger.error(f"无法读取IP记录文件 {ip_record_file}: {e}")
raise raise
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
print(f"IP记录文件 {ip_record_file} 解析错误: {e}") logger.error(f"IP记录文件 {ip_record_file} 解析错误: {e}")
raise raise
def main(): def main():
try: try:
# 加载配置文件 # 加载配置文件
config_path = os.environ.get('CONFIG_PATH', 'config.json') config_path = os.environ.get('CONFIG_PATH', '/config/config.json')
sample_config_path = os.environ.get('SAMPLE_CONFIG_PATH', 'config.sample.json') sample_config_path = os.environ.get('SAMPLE_CONFIG_PATH', '/config/config.sample.json')
config = load_config(config_path, sample_config_path) config = load_config(config_path, sample_config_path)
ACCESS_KEY_ID = config['ACCESS_KEY_ID'] ACCESS_KEY_ID = config['ACCESS_KEY_ID']
@ -136,30 +141,45 @@ def main():
GETIP_URLS = config['GETIP_URLS'] GETIP_URLS = config['GETIP_URLS']
PORTS = config['PORTS'] PORTS = config['PORTS']
PRIORITY = config.get('PRIORITY', 1) PRIORITY = config.get('PRIORITY', 1)
IP_RECORD_FILE = config.get('IP_RECORD_FILE', 'ip_records.json') IP_RECORD_FILE = config.get('IP_RECORD_FILE', '/logs/ip_records.json')
INTERVAL_SECONDS = config.get('INTERVAL_SECONDS', 3600) INTERVAL_SECONDS = config.get('INTERVAL_SECONDS', 3600)
client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION_ID) client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION_ID)
# 忽略现有的 IP 记录文件,强制更新一次规则
new_ip_records = {}
# 获取并删除旧规则
delete_old_rules(client, SECURITY_GROUP_ID, TAG)
# 获取新的IP地址并更新安全组白名单
for url in GETIP_URLS:
ip = get_ip_from_service(url)
logger.info(f"IP from {url}: {ip}")
new_ip_records[url] = ip
# 更新安全组白名单
update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY)
# 记录新的IP地址到本地文件
record_ip(IP_RECORD_FILE, new_ip_records)
while True: while True:
# 读取本地记录的IP地址 # 读取本地记录的IP地址
ip_records = load_ip_records(IP_RECORD_FILE) ip_records = load_ip_records(IP_RECORD_FILE)
new_ip_records = {} new_ip_records = {}
# 获取并删除旧规则
delete_old_rules(client, SECURITY_GROUP_ID, TAG)
# 获取新的IP地址并更新安全组白名单 # 获取新的IP地址并更新安全组白名单
for url in GETIP_URLS: for url in GETIP_URLS:
ip = get_ip_from_service(url) ip = get_ip_from_service(url)
print(f"IP from {url}: {ip}") logger.info(f"IP from {url}: {ip}")
new_ip_records[url] = ip new_ip_records[url] = ip
if ip_records.get(url) != ip: if ip_records.get(url) != ip:
# 更新安全组白名单 # 更新安全组白名单
update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY) update_security_group_white_list(client, SECURITY_GROUP_ID, ip, PORTS, TAG, PRIORITY)
else: else:
print(f"IP from {url} has not changed, no update required.") logger.info(f"IP from {url} has not changed, no update required.")
# 记录新的IP地址到本地文件 # 记录新的IP地址到本地文件
record_ip(IP_RECORD_FILE, new_ip_records) record_ip(IP_RECORD_FILE, new_ip_records)
@ -168,7 +188,7 @@ def main():
time.sleep(INTERVAL_SECONDS) time.sleep(INTERVAL_SECONDS)
except Exception as e: except Exception as e:
print(f"程序运行过程中出现错误: {e}") logger.error(f"程序运行过程中出现错误: {e}")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -0,0 +1,74 @@
# Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
# 检查是否以管理员权限运行
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
# 请求管理员权限
Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
exit
}
# 切换到脚本所在目录
Set-Location $PSScriptRoot
Write-Host "当前目录已切换为脚本所在目录: $PSScriptRoot"
# 获取当前日期和时间
$dateTime = Get-Date -Format "yyyyMMdd"
Write-Host "当前日期: $dateTime"
# 输入提示并获取版本的最后一位
$revision = Read-Host -Prompt "请输入今天的版本次 ($dateTime,如果没有次,请直接回车)"
Write-Host "输入的版本次: $revision"
# 构建版本号
if ([string]::IsNullOrWhiteSpace($revision)) {
$version = "$dateTime"
} else {
$version = "$dateTime" + "_$revision"
}
Write-Host "构建的版本号: $version"
# 构建并打上版本号标签的 Docker 镜像
Write-Host "正在构建 Docker 镜像..."
$tempFileBuild = [System.IO.Path]::GetTempFileName()
docker build -t yshtcn/alicloud_ip_updater:$version . 2> $tempFileBuild
if ($LASTEXITCODE -ne 0) {
Write-Host "Docker 镜像构建失败" -ForegroundColor Red
Write-Host (Get-Content $tempFileBuild) -ForegroundColor Red
Remove-Item $tempFileBuild
exit
}
Write-Host "Docker 镜像构建成功"
Remove-Item $tempFileBuild
# 推送带有版本号标签的 Docker 镜像到 Docker Hub
Write-Host "正在推送 Docker 镜像到 Docker Hub..."
$tempFilePush = [System.IO.Path]::GetTempFileName()
docker push yshtcn/alicloud_ip_updater:$version 2> $tempFilePush
if ($LASTEXITCODE -ne 0) {
Write-Host "Docker 镜像推送失败" -ForegroundColor Red
Write-Host (Get-Content $tempFilePush) -ForegroundColor Red
Remove-Item $tempFilePush
exit
}
Write-Host "Docker 镜像推送成功"
Remove-Item $tempFilePush
# 为镜像打上 'latest' 标签并推送
Write-Host "正在为镜像打上 'latest' 标签并推送..."
$tempFilePushLatest = [System.IO.Path]::GetTempFileName()
docker tag yshtcn/alicloud_ip_updater:$version yshtcn/alicloud_ip_updater:latest
docker push yshtcn/alicloud_ip_updater:latest 2> $tempFilePushLatest
if ($LASTEXITCODE -ne 0) {
Write-Host "Docker 镜像 'latest' 标签推送失败" -ForegroundColor Red
Write-Host (Get-Content $tempFilePushLatest) -ForegroundColor Red
Remove-Item $tempFilePushLatest
exit
}
Write-Host "Docker 镜像 'latest' 标签推送成功"
Remove-Item $tempFilePushLatest
Write-Host "Docker 镜像构建和推送流程全部完成"

View File

@ -10,8 +10,11 @@ COPY . /app
# Install any needed packages specified in requirements.txt # Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
# Create directories for config and logs
RUN mkdir /config /logs
# Copy the sample config file into the image # Copy the sample config file into the image
COPY config.sample.json /app/config.sample.json COPY config.sample.json /config/config.sample.json
# Run update_aliyun.py when the container launches # Run update_aliyun.py when the container launches
CMD ["python", "AliCloudIPUpdater.py"] CMD ["python", "AliCloudIPUpdater.py"]

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
requests
aliyun-python-sdk-core
aliyun-python-sdk-ecs