mirror of
https://github.com/yshtcn/alicloud-ip-updater.git
synced 2026-01-28 08:31:53 +08:00
# 功能实现
- 增加打包工具 - 优化docker打包结构 - 增加首次强制刷新
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
74
AliCloudIPUpdater_DockerBuilder.ps1
Normal file
74
AliCloudIPUpdater_DockerBuilder.ps1
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
|
||||||
|
# <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Թ<EFBFBD><D4B9><EFBFBD>ԱȨ<D4B1><C8A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||||
|
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԱȨ<D4B1><C8A8>
|
||||||
|
Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# <20>л<EFBFBD><D0BB><EFBFBD><EFBFBD>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD>Ŀ¼
|
||||||
|
Set-Location $PSScriptRoot
|
||||||
|
|
||||||
|
Write-Host "<EFBFBD><EFBFBD>ǰĿ¼<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>Ϊ<EFBFBD>ű<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼: $PSScriptRoot"
|
||||||
|
|
||||||
|
# <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD>ں<EFBFBD>ʱ<EFBFBD><CAB1>
|
||||||
|
$dateTime = Get-Date -Format "yyyyMMdd"
|
||||||
|
Write-Host "<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $dateTime"
|
||||||
|
|
||||||
|
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ȡ<EFBFBD>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һλ
|
||||||
|
$revision = Read-Host -Prompt "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ汾<EFBFBD><EFBFBD> ($dateTime,<2C><><EFBFBD><EFBFBD>û<EFBFBD>дΣ<D0B4><CEA3><EFBFBD>ֱ<EFBFBD>ӻس<D3BB>)"
|
||||||
|
Write-Host "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ汾<EFBFBD><EFBFBD>: $revision"
|
||||||
|
|
||||||
|
# <20><><EFBFBD><EFBFBD><EFBFBD>汾<EFBFBD><E6B1BE>
|
||||||
|
if ([string]::IsNullOrWhiteSpace($revision)) {
|
||||||
|
$version = "$dateTime"
|
||||||
|
} else {
|
||||||
|
$version = "$dateTime" + "_$revision"
|
||||||
|
}
|
||||||
|
Write-Host "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ汾<EFBFBD><EFBFBD>: $version"
|
||||||
|
|
||||||
|
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϰ汾<CFB0>ű<EFBFBD>ǩ<EFBFBD><C7A9> Docker <20><><EFBFBD><EFBFBD>
|
||||||
|
Write-Host "<EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD><EFBFBD> Docker <20><><EFBFBD><EFBFBD>..."
|
||||||
|
$tempFileBuild = [System.IO.Path]::GetTempFileName()
|
||||||
|
docker build -t yshtcn/alicloud_ip_updater:$version . 2> $tempFileBuild
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "Docker <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>" -ForegroundColor Red
|
||||||
|
Write-Host (Get-Content $tempFileBuild) -ForegroundColor Red
|
||||||
|
Remove-Item $tempFileBuild
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
Write-Host "Docker <20><><EFBFBD><EFBFBD><F1B9B9BD>ɹ<EFBFBD>"
|
||||||
|
Remove-Item $tempFileBuild
|
||||||
|
|
||||||
|
# <20><><EFBFBD>ʹ<EFBFBD><CDB4>а汾<D0B0>ű<EFBFBD>ǩ<EFBFBD><C7A9> Docker <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Docker Hub
|
||||||
|
Write-Host "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Docker <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Docker Hub..."
|
||||||
|
$tempFilePush = [System.IO.Path]::GetTempFileName()
|
||||||
|
docker push yshtcn/alicloud_ip_updater:$version 2> $tempFilePush
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "Docker <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>" -ForegroundColor Red
|
||||||
|
Write-Host (Get-Content $tempFilePush) -ForegroundColor Red
|
||||||
|
Remove-Item $tempFilePush
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
Write-Host "Docker <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳɹ<CDB3>"
|
||||||
|
Remove-Item $tempFilePush
|
||||||
|
|
||||||
|
# Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'latest' <20><>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
Write-Host "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'latest' <20><>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..."
|
||||||
|
$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 <20><><EFBFBD><EFBFBD> 'latest' <20><>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>" -ForegroundColor Red
|
||||||
|
Write-Host (Get-Content $tempFilePushLatest) -ForegroundColor Red
|
||||||
|
Remove-Item $tempFilePushLatest
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
Write-Host "Docker <20><><EFBFBD><EFBFBD> 'latest' <20><>ǩ<EFBFBD><C7A9><EFBFBD>ͳɹ<CDB3>"
|
||||||
|
Remove-Item $tempFilePushLatest
|
||||||
|
|
||||||
|
Write-Host "Docker <20><><EFBFBD><EFBFBD><F1B9B9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
@@ -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
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
requests
|
||||||
|
aliyun-python-sdk-core
|
||||||
|
aliyun-python-sdk-ecs
|
||||||
Reference in New Issue
Block a user