Spaces:
Sleeping
Sleeping
File size: 4,748 Bytes
2e60707 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
#!/usr/bin/env python3
"""
List all variables and secrets for a Hugging Face Space.
Usage:
export HF_TOKEN=hf_xxx
python backend/scripts/list_hf_space_config.py --space davidtran999/hue-portal-backend
"""
from __future__ import annotations
import argparse
import os
import sys
from typing import Dict, List, Optional
import requests
def get_space_variables(space_id: str, token: str) -> Dict[str, str]:
"""Fetch all environment variables for a Space."""
url = f"https://huggingface.co/api/spaces/{space_id}/variables"
headers = {"Authorization": f"Bearer {token}"}
try:
response = requests.get(url, headers=headers, timeout=30)
if response.status_code == 200:
data = response.json()
# Handle both list and dict responses
if isinstance(data, list):
return {item["key"]: item.get("value", "") for item in data}
elif isinstance(data, dict):
return {k: v.get("value", "") if isinstance(v, dict) else v for k, v in data.items()}
else:
return {}
elif response.status_code == 404:
return {}
else:
print(f"⚠️ Failed to fetch variables: {response.status_code} - {response.text}", file=sys.stderr)
return {}
except Exception as e:
print(f"⚠️ Error fetching variables: {e}", file=sys.stderr)
return {}
def get_space_secrets(space_id: str, token: str) -> List[str]:
"""Fetch all secret keys (values are hidden) for a Space."""
url = f"https://huggingface.co/api/spaces/{space_id}/secrets"
headers = {"Authorization": f"Bearer {token}"}
try:
response = requests.get(url, headers=headers, timeout=30)
if response.status_code == 200:
data = response.json()
# Handle both list and dict responses
if isinstance(data, list):
return [item["key"] for item in data]
elif isinstance(data, dict):
return list(data.keys())
else:
return []
elif response.status_code == 404:
return []
else:
print(f"⚠️ Failed to fetch secrets: {response.status_code} - {response.text}", file=sys.stderr)
return []
except Exception as e:
print(f"⚠️ Error fetching secrets: {e}", file=sys.stderr)
return []
def build_parser() -> argparse.ArgumentParser:
"""Configure CLI options."""
parser = argparse.ArgumentParser(description="List variables and secrets for a Hugging Face Space.")
parser.add_argument(
"--space",
required=True,
help="Space identifier in the form owner/space (e.g. davidtran999/hue-portal-backend).",
)
parser.add_argument(
"--token-env",
default="HF_TOKEN",
help="Environment variable that stores the Hugging Face access token (default: %(default)s).",
)
return parser
def main() -> None:
"""CLI entry point."""
parser = build_parser()
args = parser.parse_args()
token = os.environ.get(args.token_env)
if not token:
parser.error(f"Environment variable {args.token_env} is not set.")
print(f"📋 Listing configuration for: {args.space}\n")
# Fetch variables
variables = get_space_variables(args.space, token)
print("🔧 Environment Variables:")
if variables:
for key, value in sorted(variables.items()):
# Mask sensitive values
if "password" in key.lower() or "secret" in key.lower() or "token" in key.lower() or "key" in key.lower():
masked = value[:4] + "***" if len(value) > 4 else "***"
print(f" {key} = {masked}")
else:
print(f" {key} = {value}")
else:
print(" (none)")
print()
# Fetch secrets
secrets = get_space_secrets(args.space, token)
print("🔐 Secrets:")
if secrets:
for key in sorted(secrets):
print(f" {key} = <hidden>")
else:
print(" (none)")
print()
# Check for collisions
var_keys = set(variables.keys())
secret_keys = set(secrets)
collisions = var_keys & secret_keys
if collisions:
print("❌ COLLISIONS DETECTED (same name in both Variables and Secrets):")
for key in sorted(collisions):
print(f" ⚠️ {key}")
print("\n💡 Fix: Remove from Variables (keep only in Secrets)")
sys.exit(1)
else:
print("✅ No collisions detected")
if __name__ == "__main__":
try:
main()
except Exception as exc: # pylint: disable=broad-except
print(f"❌ {exc}", file=sys.stderr)
sys.exit(1)
|