fufu-cloud-cli 0.9.0__tar.gz → 0.9.2__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 (48) hide show
  1. {fufu_cloud_cli-0.9.0/src/fufu_cloud_cli.egg-info → fufu_cloud_cli-0.9.2}/PKG-INFO +9 -2
  2. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/README.md +8 -1
  3. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/pyproject.toml +1 -1
  4. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/__init__.py +1 -1
  5. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/api_backend.py +12 -3
  6. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/secrets.py +6 -5
  7. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2/src/fufu_cloud_cli.egg-info}/PKG-INFO +9 -2
  8. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/LICENSE +0 -0
  9. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/MANIFEST.in +0 -0
  10. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/setup.cfg +0 -0
  11. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/__main__.py +0 -0
  12. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/capabilities.json +0 -0
  13. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/capacity.py +0 -0
  14. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/cli.py +0 -0
  15. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/cloud_data.py +0 -0
  16. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/cloudflare.py +0 -0
  17. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/control.py +0 -0
  18. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/docker_backend.py +0 -0
  19. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/errors.py +0 -0
  20. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/http_runtime.py +0 -0
  21. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/iac_state.py +0 -0
  22. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/lambda_adapter.py +0 -0
  23. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/limits.py +0 -0
  24. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/manifest.py +0 -0
  25. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/object_transfer.py +0 -0
  26. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/public_access.py +0 -0
  27. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/pubsub.py +0 -0
  28. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/pulumi-endpoints.json +0 -0
  29. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/pulumi_bridge.py +0 -0
  30. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/remote_compute.py +0 -0
  31. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/runtime/functions/Dockerfile +0 -0
  32. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/runtime/ingress/Dockerfile +0 -0
  33. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/runtime/ingress/proxy.py +0 -0
  34. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/runtime_sdk.py +0 -0
  35. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/serverless.py +0 -0
  36. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/__init__.py +0 -0
  37. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/aws.py +0 -0
  38. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/aws_data.py +0 -0
  39. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/common.py +0 -0
  40. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/google.py +0 -0
  41. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/google_pubsub.py +0 -0
  42. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/remote_state.py +0 -0
  43. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli/terraform_bridge/runner.py +0 -0
  44. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli.egg-info/SOURCES.txt +0 -0
  45. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli.egg-info/dependency_links.txt +0 -0
  46. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli.egg-info/entry_points.txt +0 -0
  47. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli.egg-info/requires.txt +0 -0
  48. {fufu_cloud_cli-0.9.0 → fufu_cloud_cli-0.9.2}/src/fufu_cloud_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fufu-cloud-cli
3
- Version: 0.9.0
3
+ Version: 0.9.2
4
4
  Summary: FUFU Cloud CLI for tenant-scoped mock cloud development and deployment
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  Requires-Python: >=3.10
@@ -22,12 +22,19 @@ Dynamic: license-file
22
22
  `gcloud-fufu`、`az-fufu`、`wrangler-fufu`。這是 AWS、Google Cloud、Azure 與 Cloudflare 的**明確子集**,
23
23
  只供 FUFU mock 環境使用;不會把部署轉送到正式雲端。
24
24
 
25
+ 0.9.2 新增 `gcloud-fufu secrets versions describe`,以 metadata 權限查看版本狀態而不讀取秘密;GCP 秘密內容不可為空。配套後端依真實 GCP 驗證修正 Editor/Viewer 等角色的明列權限子集、Gen 1 HTTP invoker 與 Pub/Sub 的 0 秒預設 ack deadline。這些新能力需要同步更新 FUFU 服務端;沒有完整 Google IAM、SDK/ADC 或自動擴縮相容保證。
26
+
27
+ 0.9.1 統一所有 CLI API 請求的 `User-Agent: fufu-cloud-cli`,涵蓋物件傳輸、
28
+ Cloudflare 靜態檔案部署、IaC 遠端 state 與 Cloud Shell session,避免沿用
29
+ Python 預設識別而遇到 Cloudflare HTTP 403/1010。識別標頭不取代 credential
30
+ 或 IAM;HTTPS 驗證、禁止重新導向與不使用環境代理的行為保留。
31
+
25
32
  0.8.0 包含資源配額、分段傳輸、Terraform 核心子集與 Cloudflare 靜態部署/R2。需要同步更新服務端;CLI 安裝成功不表示任意 FUFU 服務端都已有這些能力。
26
33
 
27
34
  ## Cloudflare 前端部署與 R2
28
35
 
29
36
  ```bash
30
- pip install 'fufu-cloud-cli==0.8.0'
37
+ pip install 'fufu-cloud-cli==0.9.2'
31
38
  export FUFU_CLOUDFLARE_CREDENTIAL_FILE=/run/secrets/fufu-cloudflare.json
32
39
  wrangler-fufu capabilities
33
40
  wrangler-fufu pages project create frontend --production-branch main
@@ -4,12 +4,19 @@
4
4
  `gcloud-fufu`、`az-fufu`、`wrangler-fufu`。這是 AWS、Google Cloud、Azure 與 Cloudflare 的**明確子集**,
5
5
  只供 FUFU mock 環境使用;不會把部署轉送到正式雲端。
6
6
 
7
+ 0.9.2 新增 `gcloud-fufu secrets versions describe`,以 metadata 權限查看版本狀態而不讀取秘密;GCP 秘密內容不可為空。配套後端依真實 GCP 驗證修正 Editor/Viewer 等角色的明列權限子集、Gen 1 HTTP invoker 與 Pub/Sub 的 0 秒預設 ack deadline。這些新能力需要同步更新 FUFU 服務端;沒有完整 Google IAM、SDK/ADC 或自動擴縮相容保證。
8
+
9
+ 0.9.1 統一所有 CLI API 請求的 `User-Agent: fufu-cloud-cli`,涵蓋物件傳輸、
10
+ Cloudflare 靜態檔案部署、IaC 遠端 state 與 Cloud Shell session,避免沿用
11
+ Python 預設識別而遇到 Cloudflare HTTP 403/1010。識別標頭不取代 credential
12
+ 或 IAM;HTTPS 驗證、禁止重新導向與不使用環境代理的行為保留。
13
+
7
14
  0.8.0 包含資源配額、分段傳輸、Terraform 核心子集與 Cloudflare 靜態部署/R2。需要同步更新服務端;CLI 安裝成功不表示任意 FUFU 服務端都已有這些能力。
8
15
 
9
16
  ## Cloudflare 前端部署與 R2
10
17
 
11
18
  ```bash
12
- pip install 'fufu-cloud-cli==0.8.0'
19
+ pip install 'fufu-cloud-cli==0.9.2'
13
20
  export FUFU_CLOUDFLARE_CREDENTIAL_FILE=/run/secrets/fufu-cloudflare.json
14
21
  wrangler-fufu capabilities
15
22
  wrangler-fufu pages project create frontend --production-branch main
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fufu-cloud-cli"
7
- version = "0.9.0"
7
+ version = "0.9.2"
8
8
  description = "FUFU Cloud CLI for tenant-scoped mock cloud development and deployment"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """FUFU CLI 與本機部署工具;相容範圍見 capabilities.json。"""
2
2
 
3
- __version__ = "0.9.0"
3
+ __version__ = "0.9.2"
@@ -19,6 +19,7 @@ PROVIDERS = {"aws", "gcp", "azure", "cloudflare"}
19
19
  from .limits import JSON_BODY_BYTES, JSON_RESPONSE_BYTES
20
20
 
21
21
  MAX_RESPONSE = 8 * 1024 * 1024
22
+ HTTP_USER_AGENT = "fufu-cloud-cli"
22
23
 
23
24
 
24
25
  @contextmanager
@@ -49,6 +50,15 @@ class NoRedirect(HTTPRedirectHandler):
49
50
  return None
50
51
 
51
52
 
53
+ def api_opener():
54
+ """Keep the CLI identity on every request, including binary and IaC traffic."""
55
+ opener = build_opener(ProxyHandler({}), NoRedirect(), HTTPSHandler(context=ssl.create_default_context()))
56
+ # Python-urllib's default identity can trigger Cloudflare error 1010. Set
57
+ # this at the transport boundary so new request paths inherit it as well.
58
+ opener.addheaders = [("User-Agent", HTTP_USER_AGENT)]
59
+ return opener
60
+
61
+
52
62
  def endpoint_url(value):
53
63
  require(isinstance(value, str) and value == value.strip(), "INVALID_ENDPOINT", "請提供有效的 FUFU API endpoint。")
54
64
  parsed = urlsplit(value)
@@ -113,7 +123,7 @@ def load_credential(provider=None, filename=None):
113
123
  class ApiClient:
114
124
  def __init__(self, provider=None, filename=None, read_only=False):
115
125
  self.owns_token = True
116
- self.opener = build_opener(ProxyHandler({}), NoRedirect(), HTTPSHandler(context=ssl.create_default_context()))
126
+ self.opener = api_opener()
117
127
  if os.environ.get('FUFU_SESSION_FILE') and not filename:
118
128
  p = Path(os.environ['FUFU_SESSION_FILE'])
119
129
  require(p.is_file() and p.stat().st_size <= 16384, 'INVALID_SESSION', 'Session 檔案無效。')
@@ -133,7 +143,6 @@ class ApiClient:
133
143
  credential, self.endpoint = load_credential(provider, filename)
134
144
  self.provider = credential["provider"]
135
145
  self.token = None
136
- self.opener = build_opener(ProxyHandler({}), NoRedirect(), HTTPSHandler(context=ssl.create_default_context()))
137
146
  scopes = [f"{self.provider}:read"] + ([] if read_only else [f"{self.provider}:write"])
138
147
  issued = self._request("POST", "/api/auth/token", {**credential, "scopes": scopes,
139
148
  **({'assume_role': os.environ['FUFU_ASSUME_ROLE']} if os.environ.get('FUFU_ASSUME_ROLE') else {})})
@@ -157,7 +166,7 @@ class ApiClient:
157
166
  def _request(self, method, path, body=None, *, large=False):
158
167
  require(path.startswith("/api/") and "\r" not in path and "\n" not in path,
159
168
  "INVALID_REQUEST", "API 路徑無效。")
160
- headers = {"Accept": "application/json", "User-Agent": "fufu-cloud-cli"}
169
+ headers = {"Accept": "application/json"}
161
170
  if self.token:
162
171
  headers["Authorization"] = f"Bearer {self.token}"
163
172
  data = None if body is None else json.dumps(body).encode("utf-8")
@@ -7,7 +7,7 @@ from .api_backend import ApiClient, api_selected
7
7
  from .errors import require
8
8
 
9
9
 
10
- def input_data(filename=None, variable=None):
10
+ def input_data(filename=None, variable=None, minimum=0):
11
11
  if variable:
12
12
  require(variable in os.environ, 'MISSING_ENV', '秘密環境變數未注入。')
13
13
  raw = os.environ[variable].encode()
@@ -17,6 +17,7 @@ def input_data(filename=None, variable=None):
17
17
  require(file.is_file() and not file.is_symlink() and file.stat().st_size <= 65536, 'INVALID_SECRET', '秘密來源必須是不超過 64 KiB 的一般檔案。')
18
18
  raw = file.read_bytes()
19
19
  require(len(raw) <= 65536, 'SECRET_LIMIT', '秘密上限為 64 KiB。')
20
+ require(len(raw) >= minimum, 'INVALID_SECRET', 'GCP 秘密內容不可為空。')
20
21
  return base64.b64encode(raw).decode()
21
22
 
22
23
 
@@ -46,8 +47,8 @@ def command(provider, argv, Parser):
46
47
  q.add_argument('--replication-policy', choices=['automatic'], default='automatic')
47
48
  src = q.add_mutually_exclusive_group(); src.add_argument('--data-file'); src.add_argument('--secret-env')
48
49
  versions = s.add_parser('versions').add_subparsers(dest='version_action', required=True)
49
- for action in ['add', 'list', 'access', 'enable', 'disable', 'destroy']:
50
- q = versions.add_parser(action); q.set_defaults(operation='versions' if action == 'list' else action)
50
+ for action in ['add', 'list', 'describe', 'access', 'enable', 'disable', 'destroy']:
51
+ q = versions.add_parser(action); q.set_defaults(operation={'list': 'versions', 'describe': 'describe-version'}.get(action, action))
51
52
  if action in {'add', 'list'}: q.add_argument('name')
52
53
  else: q.add_argument('version'); q.add_argument('--secret', dest='name', required=True)
53
54
  if action == 'add':
@@ -60,14 +61,14 @@ def command(provider, argv, Parser):
60
61
  if getattr(args, 'secret_string', None):
61
62
  require(args.secret_string.startswith('file://'), 'SECRET_FILE_REQUIRED', '--secret-string 只接受 file:// 路徑;亦可使用 --secret-env。')
62
63
  source = args.secret_string[7:]
63
- if source is not None or variable: body['data'] = input_data(source, variable)
64
+ if source is not None or variable: body['data'] = input_data(source, variable, minimum=1 if provider == 'gcp' else 0)
64
65
  version = getattr(args, 'version', None) or getattr(args, 'version_id', None) or getattr(args, 'client_request_token', None)
65
66
  if version is not None: body['version'] = version
66
67
  destination = getattr(args, 'out_file', None)
67
68
  if destination:
68
69
  file = Path(destination)
69
70
  require(not file.exists() and not file.is_symlink() and file.parent.is_dir(), 'OUTPUT_EXISTS', '秘密輸出必須是新檔案。')
70
- with ApiClient(provider, read_only=op in {'list', 'describe', 'versions', 'access'}) as api:
71
+ with ApiClient(provider, read_only=op in {'list', 'describe', 'describe-version', 'versions', 'access'}) as api:
71
72
  result = api.request('POST', '/secrets/' + op, body)
72
73
  if destination:
73
74
  raw = base64.b64decode(result['data'], validate=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fufu-cloud-cli
3
- Version: 0.9.0
3
+ Version: 0.9.2
4
4
  Summary: FUFU Cloud CLI for tenant-scoped mock cloud development and deployment
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  Requires-Python: >=3.10
@@ -22,12 +22,19 @@ Dynamic: license-file
22
22
  `gcloud-fufu`、`az-fufu`、`wrangler-fufu`。這是 AWS、Google Cloud、Azure 與 Cloudflare 的**明確子集**,
23
23
  只供 FUFU mock 環境使用;不會把部署轉送到正式雲端。
24
24
 
25
+ 0.9.2 新增 `gcloud-fufu secrets versions describe`,以 metadata 權限查看版本狀態而不讀取秘密;GCP 秘密內容不可為空。配套後端依真實 GCP 驗證修正 Editor/Viewer 等角色的明列權限子集、Gen 1 HTTP invoker 與 Pub/Sub 的 0 秒預設 ack deadline。這些新能力需要同步更新 FUFU 服務端;沒有完整 Google IAM、SDK/ADC 或自動擴縮相容保證。
26
+
27
+ 0.9.1 統一所有 CLI API 請求的 `User-Agent: fufu-cloud-cli`,涵蓋物件傳輸、
28
+ Cloudflare 靜態檔案部署、IaC 遠端 state 與 Cloud Shell session,避免沿用
29
+ Python 預設識別而遇到 Cloudflare HTTP 403/1010。識別標頭不取代 credential
30
+ 或 IAM;HTTPS 驗證、禁止重新導向與不使用環境代理的行為保留。
31
+
25
32
  0.8.0 包含資源配額、分段傳輸、Terraform 核心子集與 Cloudflare 靜態部署/R2。需要同步更新服務端;CLI 安裝成功不表示任意 FUFU 服務端都已有這些能力。
26
33
 
27
34
  ## Cloudflare 前端部署與 R2
28
35
 
29
36
  ```bash
30
- pip install 'fufu-cloud-cli==0.8.0'
37
+ pip install 'fufu-cloud-cli==0.9.2'
31
38
  export FUFU_CLOUDFLARE_CREDENTIAL_FILE=/run/secrets/fufu-cloudflare.json
32
39
  wrangler-fufu capabilities
33
40
  wrangler-fufu pages project create frontend --production-branch main
File without changes
File without changes