ctyun-cli 0.1.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. ctyun_cli-0.1.0a1/PKG-INFO +31 -0
  2. ctyun_cli-0.1.0a1/README.md +62 -0
  3. ctyun_cli-0.1.0a1/ctyun_cli.egg-info/PKG-INFO +31 -0
  4. ctyun_cli-0.1.0a1/ctyun_cli.egg-info/SOURCES.txt +30 -0
  5. ctyun_cli-0.1.0a1/ctyun_cli.egg-info/dependency_links.txt +1 -0
  6. ctyun_cli-0.1.0a1/ctyun_cli.egg-info/entry_points.txt +2 -0
  7. ctyun_cli-0.1.0a1/ctyun_cli.egg-info/requires.txt +10 -0
  8. ctyun_cli-0.1.0a1/ctyun_cli.egg-info/top_level.txt +1 -0
  9. ctyun_cli-0.1.0a1/setup.cfg +4 -0
  10. ctyun_cli-0.1.0a1/setup.py +41 -0
  11. ctyun_cli-0.1.0a1/src/__init__.py +22 -0
  12. ctyun_cli-0.1.0a1/src/auth/__init__.py +5 -0
  13. ctyun_cli-0.1.0a1/src/auth/eop_signature.py +235 -0
  14. ctyun_cli-0.1.0a1/src/auth/signature.py +225 -0
  15. ctyun_cli-0.1.0a1/src/billing/__init__.py +8 -0
  16. ctyun_cli-0.1.0a1/src/billing/client.py +1204 -0
  17. ctyun_cli-0.1.0a1/src/billing/commands.py +701 -0
  18. ctyun_cli-0.1.0a1/src/cli/__init__.py +5 -0
  19. ctyun_cli-0.1.0a1/src/cli/main.py +1483 -0
  20. ctyun_cli-0.1.0a1/src/client.py +391 -0
  21. ctyun_cli-0.1.0a1/src/config/__init__.py +5 -0
  22. ctyun_cli-0.1.0a1/src/config/settings.py +159 -0
  23. ctyun_cli-0.1.0a1/src/ecs/__init__.py +6 -0
  24. ctyun_cli-0.1.0a1/src/ecs/client.py +475 -0
  25. ctyun_cli-0.1.0a1/src/ecs/commands.py +587 -0
  26. ctyun_cli-0.1.0a1/src/security/__init__.py +6 -0
  27. ctyun_cli-0.1.0a1/src/security/client.py +1188 -0
  28. ctyun_cli-0.1.0a1/src/security/commands.py +245 -0
  29. ctyun_cli-0.1.0a1/src/utils/__init__.py +11 -0
  30. ctyun_cli-0.1.0a1/src/utils/cache.py +176 -0
  31. ctyun_cli-0.1.0a1/src/utils/helpers.py +322 -0
  32. ctyun_cli-0.1.0a1/tests/test_basic.py +313 -0
@@ -0,0 +1,31 @@
1
+ Metadata-Version: 2.4
2
+ Name: ctyun-cli
3
+ Version: 0.1.0a1
4
+ Summary: 天翼云CLI工具 - 基于终端的云资源管理平台
5
+ Author: Your Name
6
+ Author-email: your.email@example.com
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.8
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Requires-Python: >=3.8
16
+ Requires-Dist: requests>=2.31.0
17
+ Requires-Dist: click>=8.1.0
18
+ Requires-Dist: cryptography>=41.0.0
19
+ Requires-Dist: colorama>=0.4.6
20
+ Requires-Dist: tabulate>=0.9.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
25
+ Dynamic: author
26
+ Dynamic: author-email
27
+ Dynamic: classifier
28
+ Dynamic: provides-extra
29
+ Dynamic: requires-dist
30
+ Dynamic: requires-python
31
+ Dynamic: summary
@@ -0,0 +1,62 @@
1
+ # 天翼云CLI工具
2
+
3
+ 基于终端的天翼云API操作平台,提供完整的云资源管理功能。
4
+
5
+ ## 功能特性
6
+
7
+ - 🔐 **安全认证**: 基于AK/SK的签名认证机制
8
+ - 🖥️ **ECS管理**: 云服务器生命周期管理
9
+ - 💾 **存储管理**: 对象存储、云硬盘管理
10
+ - 🌐 **网络管理**: VPC、弹性IP、安全组配置
11
+ - 📊 **监控查询**: 资源监控和日志查询
12
+ - ⚡ **批量操作**: 支持批量资源管理
13
+ - 📝 **配置管理**: 灵活的配置文件支持
14
+
15
+ ## 项目结构
16
+
17
+ ```
18
+ ctyun-cli/
19
+ ├── src/
20
+ │ ├── auth/ # 认证模块
21
+ │ ├── ecs/ # 云服务器管理
22
+ │ ├── storage/ # 存储管理
23
+ │ ├── network/ # 网络管理
24
+ │ ├── monitor/ # 监控查询
25
+ │ ├── cli/ # 命令行界面
26
+ │ ├── config/ # 配置管理
27
+ │ └── utils/ # 工具函数
28
+ ├── tests/ # 测试文件
29
+ ├── docs/ # 文档
30
+ ├── examples/ # 示例代码
31
+ ├── requirements.txt # Python依赖
32
+ ├── setup.py # 安装脚本
33
+ └── README.md # 项目说明
34
+ ```
35
+
36
+ ## 快速开始
37
+
38
+ ```bash
39
+ # 安装依赖
40
+ pip install -r requirements.txt
41
+
42
+ # 配置认证信息
43
+ python setup_config.py
44
+
45
+ # 查看帮助
46
+ python -m ctyun-cli --help
47
+
48
+ # 列出所有云服务器
49
+ python -m ctyun-cli ecs list
50
+
51
+ # 创建云服务器
52
+ python -m ctyun-cli ecs create --instance-type "s6.small" --image "img-ubuntu20"
53
+ ```
54
+
55
+ ## 技术栈
56
+
57
+ - **语言**: Python 3.8+
58
+ - **HTTP客户端**: requests
59
+ - **CLI框架**: click
60
+ - **配置管理**: configparser
61
+ - **日志**: logging
62
+ - **测试**: pytest
@@ -0,0 +1,31 @@
1
+ Metadata-Version: 2.4
2
+ Name: ctyun-cli
3
+ Version: 0.1.0a1
4
+ Summary: 天翼云CLI工具 - 基于终端的云资源管理平台
5
+ Author: Your Name
6
+ Author-email: your.email@example.com
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.8
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Requires-Python: >=3.8
16
+ Requires-Dist: requests>=2.31.0
17
+ Requires-Dist: click>=8.1.0
18
+ Requires-Dist: cryptography>=41.0.0
19
+ Requires-Dist: colorama>=0.4.6
20
+ Requires-Dist: tabulate>=0.9.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
25
+ Dynamic: author
26
+ Dynamic: author-email
27
+ Dynamic: classifier
28
+ Dynamic: provides-extra
29
+ Dynamic: requires-dist
30
+ Dynamic: requires-python
31
+ Dynamic: summary
@@ -0,0 +1,30 @@
1
+ README.md
2
+ setup.py
3
+ ctyun_cli.egg-info/PKG-INFO
4
+ ctyun_cli.egg-info/SOURCES.txt
5
+ ctyun_cli.egg-info/dependency_links.txt
6
+ ctyun_cli.egg-info/entry_points.txt
7
+ ctyun_cli.egg-info/requires.txt
8
+ ctyun_cli.egg-info/top_level.txt
9
+ src/__init__.py
10
+ src/client.py
11
+ src/auth/__init__.py
12
+ src/auth/eop_signature.py
13
+ src/auth/signature.py
14
+ src/billing/__init__.py
15
+ src/billing/client.py
16
+ src/billing/commands.py
17
+ src/cli/__init__.py
18
+ src/cli/main.py
19
+ src/config/__init__.py
20
+ src/config/settings.py
21
+ src/ecs/__init__.py
22
+ src/ecs/client.py
23
+ src/ecs/commands.py
24
+ src/security/__init__.py
25
+ src/security/client.py
26
+ src/security/commands.py
27
+ src/utils/__init__.py
28
+ src/utils/cache.py
29
+ src/utils/helpers.py
30
+ tests/test_basic.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ctyun-cli = ctyun_cli:main
@@ -0,0 +1,10 @@
1
+ requests>=2.31.0
2
+ click>=8.1.0
3
+ cryptography>=41.0.0
4
+ colorama>=0.4.6
5
+ tabulate>=0.9.0
6
+ pyyaml>=6.0
7
+
8
+ [dev]
9
+ pytest>=7.4.0
10
+ pytest-cov>=4.1.0
@@ -0,0 +1 @@
1
+ ctyun_cli
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,41 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="ctyun-cli",
5
+ version="0.1.0a1",
6
+ description="天翼云CLI工具 - 基于终端的云资源管理平台",
7
+ author="Your Name",
8
+ author_email="your.email@example.com",
9
+ packages=["ctyun_cli"] + ["ctyun_cli." + p for p in find_packages(where="src")],
10
+ package_dir={"ctyun_cli": "src"},
11
+ install_requires=[
12
+ "requests>=2.31.0",
13
+ "click>=8.1.0",
14
+ "cryptography>=41.0.0",
15
+ "colorama>=0.4.6",
16
+ "tabulate>=0.9.0",
17
+ "pyyaml>=6.0",
18
+ ],
19
+ extras_require={
20
+ "dev": [
21
+ "pytest>=7.4.0",
22
+ "pytest-cov>=4.1.0",
23
+ ]
24
+ },
25
+ entry_points={
26
+ "console_scripts": [
27
+ "ctyun-cli=ctyun_cli:main",
28
+ ],
29
+ },
30
+ python_requires=">=3.8",
31
+ classifiers=[
32
+ "Development Status :: 4 - Beta",
33
+ "Intended Audience :: Developers",
34
+ "License :: OSI Approved :: MIT License",
35
+ "Programming Language :: Python :: 3",
36
+ "Programming Language :: Python :: 3.8",
37
+ "Programming Language :: Python :: 3.9",
38
+ "Programming Language :: Python :: 3.10",
39
+ "Programming Language :: Python :: 3.11",
40
+ ],
41
+ )
@@ -0,0 +1,22 @@
1
+ """
2
+ 天翼云CLI工具
3
+ """
4
+
5
+ __version__ = "1.0.0"
6
+ __author__ = "Your Name"
7
+ __email__ = "your.email@example.com"
8
+
9
+ from .client import CTYUNClient, CTYUNAPIError
10
+ from .config.settings import ConfigManager, config
11
+
12
+ __all__ = [
13
+ 'CTYUNClient',
14
+ 'CTYUNAPIError',
15
+ 'ConfigManager',
16
+ 'config'
17
+ ]
18
+
19
+ def main():
20
+ """CLI主入口函数"""
21
+ from .cli.main import cli
22
+ cli()
@@ -0,0 +1,5 @@
1
+ """认证模块"""
2
+
3
+ from .signature import CTYUNAuth
4
+
5
+ __all__ = ['CTYUNAuth']
@@ -0,0 +1,235 @@
1
+ """
2
+ 天翼云EOP签名认证模块
3
+ 实现基于EOP规范的AK/SK签名认证机制
4
+ """
5
+
6
+ import hashlib
7
+ import hmac
8
+ import base64
9
+ import uuid
10
+ from datetime import datetime
11
+ from urllib.parse import quote
12
+ from typing import Dict, Any, Optional
13
+
14
+
15
+ class CTYUNEOPAuth:
16
+ """天翼云EOP签名认证类"""
17
+
18
+ def __init__(self, access_key: str, secret_key: str):
19
+ """
20
+ 初始化认证器
21
+
22
+ Args:
23
+ access_key: 访问密钥(AK)
24
+ secret_key: 密钥(SK)
25
+ """
26
+ self.access_key = access_key
27
+ self.secret_key = secret_key
28
+
29
+ def sign_request(self, method: str, url: str, query_params: Optional[Dict[str, Any]] = None,
30
+ body: Optional[str] = None, extra_headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
31
+ """
32
+ 对请求进行签名,返回完整的请求头
33
+
34
+ Args:
35
+ method: HTTP方法
36
+ url: 请求URL
37
+ query_params: 查询参数
38
+ body: 请求体
39
+ extra_headers: 额外的请求头
40
+
41
+ Returns:
42
+ 包含签名的请求头字典
43
+ """
44
+ # 生成必需的请求头
45
+ request_id = str(uuid.uuid4())
46
+ eop_date = self._get_eop_date()
47
+
48
+ # 构建基础请求头
49
+ headers = {
50
+ 'Content-Type': 'application/json',
51
+ 'ctyun-eop-request-id': request_id,
52
+ 'Eop-date': eop_date
53
+ }
54
+
55
+ # 添加额外的请求头
56
+ if extra_headers:
57
+ headers.update(extra_headers)
58
+
59
+ # 步骤一:构造待签名字符串 signature
60
+ signature_string = self._build_signature_string(
61
+ headers, query_params, body
62
+ )
63
+
64
+ # 步骤二:构造动态密钥 kdate
65
+ kdate = self._build_kdate(eop_date)
66
+
67
+ # 步骤三:构造 signature
68
+ signature = self._build_signature(signature_string, kdate)
69
+
70
+ # 步骤四:构造 Eop-Authorization
71
+ eop_authorization = self._build_eop_authorization(signature, headers)
72
+
73
+ # 添加认证头
74
+ headers['Eop-Authorization'] = eop_authorization
75
+
76
+ return headers
77
+
78
+ def _get_eop_date(self) -> str:
79
+ """
80
+ 获取EOP格式的日期时间
81
+ 格式:yyyyMMdd'T'HHmmss'Z'
82
+ 注意:实际传时间为北京东八区UTC+8时间,TZ仅为格式,非UTC时间
83
+
84
+ Returns:
85
+ EOP格式的日期时间字符串
86
+ """
87
+ # 获取当前北京时间(UTC+8)
88
+ now = datetime.now()
89
+ return now.strftime('%Y%m%dT%H%M%SZ')
90
+
91
+ def _build_signature_string(self, headers: Dict[str, str],
92
+ query_params: Optional[Dict[str, Any]] = None,
93
+ body: Optional[str] = None) -> str:
94
+ """
95
+ 构造待签名字符串
96
+ sigture = 需要进行签名的Header排序后的组合列表 + "\n" + encode的query + "\n" + toHex(sha256(原封的body))
97
+
98
+ Args:
99
+ headers: 请求头字典
100
+ query_params: 查询参数
101
+ body: 请求体
102
+
103
+ Returns:
104
+ 待签名字符串
105
+ """
106
+ # 1. 构造需要签名的Header排序后的组合列表
107
+ # EOP强制要求 ctyun-eop-request-id、eop-date 必须进行签名
108
+ signed_header_names = ['ctyun-eop-request-id', 'eop-date']
109
+
110
+ # 按字母顺序排序
111
+ signed_header_names.sort()
112
+
113
+ # 构造 header_name:header_value\n 格式
114
+ header_list = []
115
+ for header_name in signed_header_names:
116
+ # 注意:查找header时不区分大小写,但构造签名字符串时必须用小写
117
+ header_value = None
118
+ for k, v in headers.items():
119
+ if k.lower() == header_name.lower():
120
+ header_value = v
121
+ break
122
+
123
+ if header_value:
124
+ header_list.append(f"{header_name.lower()}:{header_value}\n")
125
+
126
+ header_string = ''.join(header_list)
127
+
128
+ # 2. 构造编码后的query字符串
129
+ query_string = ''
130
+ if query_params:
131
+ # 对参数按key排序
132
+ sorted_params = sorted(query_params.items())
133
+ encoded_params = []
134
+ for key, value in sorted_params:
135
+ # 值需要进行URL编码
136
+ encoded_value = quote(str(value), safe='')
137
+ encoded_params.append(f"{key}={encoded_value}")
138
+ query_string = '&'.join(encoded_params)
139
+
140
+ # 3. 对body进行SHA256摘要并转十六进制
141
+ if body is None or body == '':
142
+ body = ''
143
+ body_hash = hashlib.sha256(body.encode('utf-8')).hexdigest()
144
+
145
+ # 拼接最终的待签名字符串
146
+ # 格式:header_string + "\n" + query_string + "\n" + body_hash
147
+ signature_string = f"{header_string}\n{query_string}\n{body_hash}"
148
+
149
+ return signature_string
150
+
151
+ def _build_kdate(self, eop_date: str) -> bytes:
152
+ """
153
+ 构造动态密钥 kdate
154
+
155
+ 步骤:
156
+ 1. ktime = hmacSHA256(eop_date, sk)
157
+ 2. kAk = hmacSHA256(ak, ktime)
158
+ 3. kdate = hmacSHA256(eop_date的年月日值, kAk)
159
+
160
+ Args:
161
+ eop_date: EOP格式的日期时间
162
+
163
+ Returns:
164
+ 动态密钥 kdate
165
+ """
166
+ # 1. 使用eop_date作为数据,sk作为密钥,算出ktime
167
+ ktime = hmac.new(
168
+ self.secret_key.encode('utf-8'),
169
+ eop_date.encode('utf-8'),
170
+ hashlib.sha256
171
+ ).digest()
172
+
173
+ # 2. 使用ak作为数据,ktime作为密钥,算出kAk
174
+ kAk = hmac.new(
175
+ ktime,
176
+ self.access_key.encode('utf-8'),
177
+ hashlib.sha256
178
+ ).digest()
179
+
180
+ # 3. 使用eop_date的年月日值作为数据,kAk作为密钥,算出kdate
181
+ # eop_date格式:20221107T093029Z,提取年月日:20221107
182
+ date_part = eop_date.split('T')[0]
183
+ kdate = hmac.new(
184
+ kAk,
185
+ date_part.encode('utf-8'),
186
+ hashlib.sha256
187
+ ).digest()
188
+
189
+ return kdate
190
+
191
+ def _build_signature(self, signature_string: str, kdate: bytes) -> str:
192
+ """
193
+ 构造 signature
194
+ 使用kdate作为密钥、signature_string作为数据,进行HMAC-SHA256,然后Base64编码
195
+
196
+ Args:
197
+ signature_string: 待签名字符串
198
+ kdate: 动态密钥
199
+
200
+ Returns:
201
+ Base64编码的签名
202
+ """
203
+ signature_bytes = hmac.new(
204
+ kdate,
205
+ signature_string.encode('utf-8'),
206
+ hashlib.sha256
207
+ ).digest()
208
+
209
+ # Base64编码
210
+ signature = base64.b64encode(signature_bytes).decode('utf-8')
211
+
212
+ return signature
213
+
214
+ def _build_eop_authorization(self, signature: str, headers: Dict[str, str]) -> str:
215
+ """
216
+ 构造 Eop-Authorization 请求头
217
+ 格式:ak Headers=header1;header2 Signature=xxx
218
+
219
+ Args:
220
+ signature: 签名
221
+ headers: 请求头字典
222
+
223
+ Returns:
224
+ Eop-Authorization 字符串
225
+ """
226
+ # 构造 Headers 部分(需要签名的header,按字母排序,用分号分隔)
227
+ signed_header_names = ['ctyun-eop-request-id', 'eop-date']
228
+ signed_header_names.sort()
229
+ headers_part = ';'.join(signed_header_names)
230
+
231
+ # 构造完整的 Eop-Authorization
232
+ # 格式:ak Headers=xxx Signature=xxx
233
+ eop_authorization = f"{self.access_key} Headers={headers_part} Signature={signature}"
234
+
235
+ return eop_authorization