
Alibabacloud Solution Deploy
- 175 installs
- 208 repo stars
- Updated August 4, 2026
- aliyun/alibabacloud-aiops-skills
Deploy Alibaba Cloud solution templates or reference architectures when shipping demos, POCs, or production stacks through agent-guided provisioning and configuration.
About
alibabacloud-solution-deploy guides agents through launching Alibaba Cloud solution templates end to end, wiring parameters, dependencies, and provisioning steps so teams can ship reference architectures and demos without manual console assembly.
- Deploys curated Alibaba solution templates
- Handles parameterization and dependency ordering
- Accelerates POC-to-staging provisioning
- Integrates with agent-driven release workflows
- Reduces manual console setup for standard patterns
Alibabacloud Solution Deploy by the numbers
- 175 all-time installs (skills.sh)
- Ranked #433 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aliyun/alibabacloud-aiops-skills --skill alibabacloud-solution-deployAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 175 |
|---|---|
| repo stars | ★ 208 |
| Last updated | August 4, 2026 |
| Repository | aliyun/alibabacloud-aiops-skills ↗ |
What it does
Deploy Alibaba Cloud solution templates or reference architectures when shipping demos, POCs, or production stacks through agent-guided provisioning and configuration.
Files
Alibaba Cloud Solution Deploy
Match the user's scenario to the best execution path (Terraform or CLI), then complete the task end-to-end.
Core Principles
Maximum Automation
If 10 steps are needed and 9 can be automated, automate all 9. Only pause for the 1 that genuinely requires human action. Every cloud operation that has a CLI path should use it — the user came to you precisely so they don't have to click through consoles.
CLI-First, Console-Last
Express every cloud action as a runnable aliyun CLI command. Only fall back to console when no CLI exists — and when you do, give a direct deep-linked URL (not a product homepage). The difference between https://vision.aliyun.com/facebody and https://console.aliyun.com/ is the difference between being helpful and being useless.
Never Guess — Verify First
- CLI syntax: Run
aliyun <product> <command> --helpbefore constructing commands. Parameter naming is inconsistent across products —--RegionIdvs--region-idvs--regionall exist. - Errors: Run
diagnose_cli_command.pyimmediately on failure. Error messages from the Alibaba Cloud API are often cryptic — the diagnosis script calls a specialized endpoint that maps error codes to fixes.
---
Workflow
Step 0: Verify Environment
Run this first in any new session:
Pre-check: Aliyun CLI >= 3.3.1 required
>
Run aliyun version to verify >= 3.3.1. If not installed or version too low, see installation guide for instructions.>
Then run the following command to enable automatic plugin installation and set the agent user-agent:
```bash
aliyun configure set --auto-plugin-install true --user-agent AlibabaCloud-Agent-Skills
```
This ensures product-specific CLI plugins are downloaded on first use (no manual install needed), and identifies requests as coming from this skill.
Then run the full environment check:
bash {{SKILL_PATH}}/scripts/verify_env.shThis checks: CLI version, valid credentials, auto-plugin-install, Python3 + SDK. If any check fails, tell the user what to fix and stop — a broken environment means every subsequent command will fail.
RAM Permission Pre-check
Before executing any commands, verify the current user has the required permissions:
1. Compare the user's permissions against references/ram-policies.md 2. If any permission is missing, abort and prompt the user to attach the required policy
Minimum required permissions are listed in references/ram-policies.md.
Step 1: Understand the Scenario
Extract from the user's request:
- What they want to build or configure
- Which Alibaba Cloud products are involved (or can be inferred)
- Key requirements: region, instance specs, budget, HA needs, environment (dev/staging/prod)
Distill into search keywords (Chinese + English) for Step 2. For example, "我要搭个RAG知识库" → keywords: RAG, 知识库, AnalyticDB, 百炼.
Step 2: Route to the Right Path
Check references/alicloud-tech-solutions-all.md — the master catalog of 187 Alibaba Cloud tech solutions. Search by keyword match against the solution names and descriptions.
Each row has a Terraform Module 名称 column:
- Column has a value (e.g.,
analyticdb-rag,deepseek-personal-website) → Path A: Terraform - Column is empty or no matching solution found → Path B: CLI-First
Also use intent-mapping.md for fuzzy keyword → solution matching (e.g., "小程序" → develop-your-wechat-mini-program-in-10-minutes).
Tell the user which path you're taking and why before proceeding.
---
Path A: Terraform Solution
When a Terraform module matches, deploy through the IaCService remote runtime — no local terraform binary needed.
A.1: Locate the Module
Look up the Module 名称 and Module 地址 in references/tf-plan/tf-solutions.md. Match by: 1. Exact module name from the master catalog 2. Keyword match against the 描述 column 3. Intent mapping
A.2: Fetch Example Parameters
Every module has a GitHub repo with tested examples. Derive the URLs:
Module 地址: https://registry.terraform.io/modules/alibabacloud-automation/<name>/alicloud/latest
GitHub repo: https://github.com/alibabacloud-automation/terraform-alicloud-<name>
Example: https://raw.githubusercontent.com/alibabacloud-automation/terraform-alicloud-<name>/main/examples/complete/main.tfFetch the example main.tf via WebFetch. These values come from real tested deployments — they're far more reliable than generic defaults.
Parameter priority: 1. User explicitly specified → always use 2. Example main.tf from examples/complete/ → use as default 3. Fallback defaults (only if fetch fails): see terraform-defaults.md
A.3: Confirm with User
Show the parameters and ask for confirmation. Never silently apply them — cloud resources cost real money.
以下是基于官方示例的部署参数,请确认或修改:
• Region: cn-hangzhou
• Instance type: ecs.c7.large
• VPC CIDR: 172.16.0.0/12
• Password: (请提供)Sensitive values like passwords and API keys: never generate them yourself. The user provides these.
A.4: Write main.tf and Deploy
# Based on: https://github.com/alibabacloud-automation/terraform-alicloud-<name>/blob/main/examples/complete/main.tf
module "<module_name>" {
source = "alibabacloud-automation/<module_name>/alicloud"
version = "~> 1.0"
# Parameters adjusted per user confirmation
}Deploy using the remote runtime — see terraform-online-runtime.md for full usage:
SKILL_DIR="{{SKILL_PATH}}"
TF="${SKILL_DIR}/scripts/terraform_runtime_online.sh"
STATE_ID=$($TF apply main.tf | grep '^STATE_ID=' | cut -d= -f2)
echo "STATE_ID=$STATE_ID" >> terraform_state_ids.envThe STATE_ID is required for any future update or destroy. Losing it means you lose control over the resources.
A.5: Verify and Report
Confirm resources exist. Provide the destroy command for cleanup.
---
Path B: CLI-First Execution
This path handles everything without a Terraform template. The approach: understand the architecture → decompose into steps → find the CLI command for each step → execute.
B.1: Understand the Architecture
Before writing any commands, understand what you're building:
- If the master catalog had a matching solution (just without TF Module), it still has tutorial links (部署教程 column). Fetch that page to understand the target architecture, required products, and deployment sequence. This gives you the blueprint — you'll then translate each step into CLI commands.
- If no solution matched at all, reason from the user's description: what products are needed, what depends on what, what's the end state.
B.2: Decompose into Steps
Break the goal into atomic steps ordered by dependency. Think through:
- Resource creation order: VPC → VSwitch → Security Group → ECS is almost always the foundation
- ID chaining: which step outputs IDs that later steps need (VpcId → CreateVSwitch, VSwitchId → RunInstances)
- Async operations: some create calls return immediately but the resource takes time — you'll need to poll
- What might not have a CLI: some product activations, some console-only features
B.3: Research CLI Commands
For each step, use the scripts to find the correct API name and parameters. This is critical — don't rely on memory. Alibaba Cloud has thousands of APIs, and parameter names are inconsistent across products.
python3 {{SKILL_PATH}}/scripts/lsit_products.py '<keyword>' # Find product code + API version
python3 {{SKILL_PATH}}/scripts/search_apis.py '<what you want to do>' # Natural language → API
python3 {{SKILL_PATH}}/scripts/search_documents.py '<topic>' # Parameter details, valid values, constraints
python3 {{SKILL_PATH}}/scripts/lsit_api_overview.py <Product> <version> # Full API list for a productRun scripts in parallel when researching multiple products — don't serialize what can be parallelized.
Common CLI shortcuts that avoid console entirely:
| Scenario | CLI Command | Notes |
|---|---|---|
| Get Bailian (百炼) API Key | aliyun modelstudio list-workspaces → aliyun modelstudio create-api-key --WorkspaceId <id> | Avoids console entirely. Almost every AI solution needs this. |
| Run commands on ECS | aliyun ecs RunCommand --Type RunShellScript --CommandContent '<script>' --InstanceId.1 <id> | Use Cloud Assistant instead of asking the user to SSH in. |
| OSS operations | aliyun ossutil cp/ls/mb ... | Use ossutil subcommand, not oss. |
The Bailian API Key pattern is especially important — nearly every AI-related solution needs a DashScope/Bailian SK, and users often don't know it can be obtained programmatically. Whenever a plan involves 百炼/Bailian/DashScope, proactively use the modelstudio commands to get the key.
B.4: Present Plan and Confirm
Before running any write operations, show the complete execution plan. The plan MUST include a RAM permissions section listing all permissions the current account needs — this lets the user verify access before execution starts, avoiding mid-deploy Forbidden.RAM errors.
Derive the required permissions from the planned CLI commands: each aliyun <product> <API> call maps to a RAM action in the form <product>:<API> (e.g., aliyun vpc CreateVpc → vpc:CreateVpc).
所需 RAM 权限:
| 云产品 | 所需权限 (Action) | 对应步骤 | 快捷策略 |
|--------|-------------------|----------|----------|
| VPC | vpc:CreateVpc, vpc:CreateVSwitch, vpc:DescribeVpcs | 步骤 1-2 | AliyunVPCFullAccess |
| ECS | ecs:RunInstances, ecs:DescribeInstances, ecs:RunCommand | 步骤 4-6 | AliyunECSFullAccess |
| EIP | vpc:AllocateEipAddress, vpc:AssociateEipAddress | 步骤 3 | AliyunEIPFullAccess |
提示: 可使用快捷策略快速授权,或按 Action 列配置最小权限自定义策略。
---
执行计划 (共 N 步, M 步 CLI 自动化, K 步需控制台):
步骤 1 — 创建 VPC
aliyun vpc CreateVpc --RegionId cn-hangzhou --CidrBlock 172.16.0.0/12 --VpcName demo-vpc
步骤 2 — 创建交换机 (依赖: 步骤1 VpcId)
aliyun vpc CreateVSwitch --RegionId cn-hangzhou --VpcId <步骤1> --ZoneId cn-hangzhou-h --CidrBlock 172.16.0.0/24
步骤 3 — [控制台] 开通视觉智能 API (无 CLI)
打开: https://vision.aliyun.com/facebody → 点击 "立即开通"Wait for user approval. Cloud resources cost money, and some operations (like deleting RDS instances) are irreversible.
B.5: Execute
For each step: 1. Verify syntax first: aliyun <product> <api> --help — catch parameter errors before they hit the API 2. Run the command 3. Verify result: poll async operations; describe the resource to confirm it exists 4. Capture output: save IDs, endpoints, connection strings for subsequent steps and final report
B.6: Handle Errors
When a command fails:
python3 {{SKILL_PATH}}/scripts/diagnose_cli_command.py '<the full command>' '<the error message>'The diagnosis script calls a specialized API that maps error codes to actionable fixes. Apply the fix and retry. If the same error persists after the fix, report to the user with the diagnosis — don't keep retrying blindly.
Resume from the failed step. Never re-run steps that already succeeded — those resources already exist and re-running would either fail (duplicate) or create unwanted duplicates.
B.7: Report
Summarize:
- Resources created (with IDs)
- Access endpoints / connection strings
- How to use what was built
- Cleanup commands (delete in reverse dependency order: ECS → Security Group → VSwitch → VPC)
---
Script Reference
| Script | Purpose | Example |
|---|---|---|
verify_env.sh | Environment check | bash {{SKILL_PATH}}/scripts/verify_env.sh |
lsit_products.py | Find product code + version | python3 {{SKILL_PATH}}/scripts/lsit_products.py 'ECS' |
search_apis.py | Natural language → API | python3 {{SKILL_PATH}}/scripts/search_apis.py '创建ECS实例' |
search_documents.py | Doc search for details | python3 {{SKILL_PATH}}/scripts/search_documents.py 'ECS实例规格' |
lsit_api_overview.py | Full API list for a product | python3 {{SKILL_PATH}}/scripts/lsit_api_overview.py Ecs 2014-05-26 |
diagnose_cli_command.py | Diagnose CLI errors | python3 {{SKILL_PATH}}/scripts/diagnose_cli_command.py '<cmd>' '<err>' |
terraform_runtime_online.sh | Remote TF execution | See terraform-online-runtime.md |
References
- Intent Mapping — keyword → solution mapping
- Terraform Defaults — default parameter values
- Terraform Online Runtime — IaCService script usage
- All Tech Solutions Catalog — 187 solutions with TF Module availability
- TF Solutions Detail — 48 Terraform modules with Registry addresses
Aliyun CLI Installation & Configuration Guide
Complete guide for installing and configuring Aliyun CLI.
Aliyun CLI 3.3.0+: Supports installing and using all published Alibaba Cloud product plugins. Make sure to upgrade to 3.3.0 or later for full plugin ecosystem coverage.
Installation
macOS
Using Homebrew (Recommended)
brew install aliyun-cli
# Upgrade to latest
brew upgrade aliyun-cli
# Verify version (>= 3.3.0)
aliyun versionUsing Binary
# Download
wget https://aliyuncli.alicdn.com/aliyun-cli-macosx-latest-amd64.tgz
# Extract
tar -xzf aliyun-cli-macosx-latest-amd64.tgz
# Move to PATH
sudo mv aliyun /usr/local/bin/
# Verify
aliyun versionLinux
Debian/Ubuntu
# Download
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
# Extract and install
tar -xzf aliyun-cli-linux-latest-amd64.tgz
sudo mv aliyun /usr/local/bin/
# Verify
aliyun versionCentOS/RHEL
# Download
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
# Extract and install
tar -xzf aliyun-cli-linux-latest-amd64.tgz
sudo mv aliyun /usr/local/bin/
# Verify
aliyun versionARM64 Architecture
# Download ARM64 version
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-arm64.tgz
# Extract and install
tar -xzf aliyun-cli-linux-latest-arm64.tgz
sudo mv aliyun /usr/local/bin/Windows
Using Binary 1. Download from: https://aliyuncli.alicdn.com/aliyun-cli-windows-latest-amd64.zip 2. Extract the ZIP file 3. Add the directory to your PATH environment variable 4. Open new Command Prompt or PowerShell 5. Verify: aliyun version
Using PowerShell
# Download
Invoke-WebRequest -Uri "https://aliyuncli.alicdn.com/aliyun-cli-windows-latest-amd64.zip" -OutFile "aliyun-cli.zip"
# Extract
Expand-Archive -Path aliyun-cli.zip -DestinationPath C:\aliyun-cli
# Add to PATH (requires admin privileges)
$env:Path += ";C:\aliyun-cli"
[Environment]::SetEnvironmentVariable("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)
# Verify
aliyun versionConfiguration
Quick Start
aliyun configure set \
--mode AK \
--access-key-id <your-access-key-id> \
--access-key-secret <your-access-key-secret> \
--region cn-hangzhouAll aliyun configure commands support non-interactive flags, which is the recommended approach — it works in scripts, CI/CD pipelines, and agent-driven automation without hanging on stdin prompts.
Where to Get Access Keys
1. Log in to Aliyun Console: https://ram.console.aliyun.com/ 2. Navigate to: AccessKey Management 3. Create a new AccessKey pair 4. Save the secret immediately — it's only shown once
Configuration Modes
Aliyun CLI supports 6 authentication modes. All examples below use non-interactive flags.
1. AK Mode (Access Key)
Most common mode for personal accounts and scripts.
aliyun configure set \
--mode AK \
--access-key-id LTAI5tXXXXXXXX \
--access-key-secret 8dXXXXXXXXXXXXXXXXXXXXXXXX \
--region cn-hangzhouConfiguration is stored in ~/.aliyun/config.json:
{
"current": "default",
"profiles": [
{
"name": "default",
"mode": "AK",
"access_key_id": "LTAI5tXXXXXXXX",
"access_key_secret": "8dXXXXXXXXXXXXXXXXXXXXXXXX",
"region_id": "cn-hangzhou",
"output_format": "json",
"language": "en"
}
]
}2. StsToken Mode (Temporary Credentials)
For short-lived access (tokens expire in 1-12 hours).
aliyun configure set \
--mode StsToken \
--access-key-id LTAI5tXXXXXXXX \
--access-key-secret 8dXXXXXXXXXXXXXXXXXXXXXXXX \
--sts-token v1.0:XXXXXXXXXXXXXXXX \
--region cn-hangzhouUse cases: CI/CD pipelines, temporary access for external contractors, cross-account access.
3. RamRoleArn Mode (Assume RAM Role)
Assume a RAM role for elevated or cross-account access.
aliyun configure set \
--mode RamRoleArn \
--access-key-id LTAI5tXXXXXXXX \
--access-key-secret 8dXXXXXXXXXXXXXXXXXXXXXXXX \
--ram-role-arn acs:ram::123456789012:role/AdminRole \
--role-session-name my-session \
--region cn-hangzhouUse cases: cross-account resource access, temporary elevated privileges, role-based access control.
4. EcsRamRole Mode (ECS Instance RAM Role)
Use the RAM role attached to an ECS instance — no credentials needed.
aliyun configure set \
--mode EcsRamRole \
--ram-role-name MyEcsRole \
--region cn-hangzhouRequirements: must be running on an ECS instance with a RAM role attached.
Use cases: scripts and automation running on ECS instances.
5. RsaKeyPair Mode (RSA Key Pair)
Use RSA key pair for authentication (generate key pair in Aliyun Console first).
aliyun configure set \
--mode RsaKeyPair \
--private-key /path/to/private-key.pem \
--key-pair-name my-key-pair \
--region cn-hangzhou6. RamRoleArnWithEcs Mode (ECS + RAM Role)
Combine ECS instance role with RAM role assumption for cross-account access from ECS.
aliyun configure set \
--mode RamRoleArnWithEcs \
--ram-role-name MyEcsRole \
--ram-role-arn acs:ram::123456789012:role/TargetRole \
--role-session-name my-session \
--region cn-hangzhouEnvironment Variables
Highest priority - overrides config file
Access Key Mode
export ALIBABA_CLOUD_ACCESS_KEY_ID=your_access_key_id
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=your_access_key_secret
export ALIBABA_CLOUD_REGION_ID=cn-hangzhouSTS Token Mode
export ALIBABA_CLOUD_ACCESS_KEY_ID=your_access_key_id
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=your_access_key_secret
export ALIBABA_CLOUD_SECURITY_TOKEN=your_sts_token
export ALIBABA_CLOUD_REGION_ID=cn-hangzhouECS RAM Role Mode
export ALIBABA_CLOUD_ECS_METADATA=role_nameUse Case:
- CI/CD pipelines
- Docker containers
- Temporary credential override
Managing Multiple Profiles
Create Named Profiles
aliyun configure set --profile projectA \
--mode AK \
--access-key-id LTAI5tAAAAAAAA \
--access-key-secret 8dAAAAAAAAAAAAAAAAAAAAAAAA \
--region cn-hangzhou
aliyun configure set --profile projectB \
--mode AK \
--access-key-id LTAI5tBBBBBBBB \
--access-key-secret 8dBBBBBBBBBBBBBBBBBBBBBBBB \
--region cn-shanghaiUse Specific Profile
aliyun ecs describe-instances --profile projectA
export ALIBABA_CLOUD_PROFILE=projectA
aliyun ecs describe-instances # Uses projectAList and Switch Profiles
aliyun configure list # List all profiles
aliyun configure set --current projectA # Switch default profileCredential Priority
Credentials are loaded in this order (first found wins):
1. Command-line flag: --profile <name> 2. Environment variable: ALIBABA_CLOUD_PROFILE 3. Environment credentials: ALIBABA_CLOUD_ACCESS_KEY_ID, etc. 4. Configuration file: ~/.aliyun/config.json (current profile) 5. ECS Instance RAM Role: If running on ECS with attached role
Verification
Test Authentication
# Basic test - list regions
aliyun ecs describe-regions
# Expected output: JSON array of regionsIf successful, you'll see:
{
"Regions": {
"Region": [
{
"RegionId": "cn-hangzhou",
"RegionEndpoint": "ecs.cn-hangzhou.aliyuncs.com",
"LocalName": "华东 1(杭州)"
},
...
]
},
"RequestId": "..."
}If failed, you'll see error messages:
InvalidAccessKeyId.NotFound- Wrong Access Key IDSignatureDoesNotMatch- Wrong Access Key SecretInvalidSecurityToken.Expired- STS token expired (for StsToken mode)Forbidden.RAM- Insufficient permissions
Debug Configuration
# Show current configuration
aliyun configure get
# Test with debug logging
aliyun ecs describe-regions --log-level=debug
# Check credential provider
aliyun configure get modeSecurity Best Practices
1. Use RAM Users (Not Root Account)
❌ Don't: Use Aliyun root account credentials ✅ Do: Create RAM users with specific permissions
# Create RAM user in console
# Attach only necessary policies
# Use RAM user's access keys2. Principle of Least Privilege
Grant only the minimum permissions needed:
# Example: Read-only ECS access
# Attach policy: AliyunECSReadOnlyAccess3. Rotate Access Keys Regularly
# Create new access key in RAM Console, then update configuration
aliyun configure set --access-key-id NEW_KEY --access-key-secret NEW_SECRET
# Delete old access key from console4. Use STS Tokens for Temporary Access
aliyun configure set --mode StsToken \
--access-key-id XXXX --access-key-secret XXXX \
--sts-token XXXX --region cn-hangzhou5. Use ECS RAM Roles When Possible
aliyun configure set --mode EcsRamRole --ram-role-name MyRole --region cn-hangzhou6. Never Commit Credentials
# Add to .gitignore
echo "~/.aliyun/config.json" >> .gitignore
# Use environment variables in CI/CD instead7. Secure Config File
# Restrict permissions
chmod 600 ~/.aliyun/config.jsonTroubleshooting
Issue: Command Not Found
# Check installation
which aliyun
# Check PATH
echo $PATH
# Reinstall or add to PATHIssue: Authentication Failed
# Verify configuration
aliyun configure get
# Test with debug
aliyun ecs describe-regions --log-level=debug
# Check credentials in console
# Verify access key is activeIssue: Permission Denied
# Error: Forbidden.RAM
# Check RAM user permissions
# Attach necessary policies in RAM console
# Example: AliyunECSFullAccess for ECS operationsIssue: STS Token Expired
# Error: InvalidSecurityToken.Expired
# Reconfigure with new token
aliyun configure set --mode StsToken \
--access-key-id XXXX --access-key-secret XXXX \
--sts-token NEW_TOKEN --region cn-hangzhouIssue: Wrong Region
# Some resources may not exist in the specified region
# Check available regions
aliyun ecs describe-regions
# Update default region
aliyun configure set region cn-shanghaiAdvanced Configuration
Custom Endpoint
# Use custom or private endpoint
export ALIBABA_CLOUD_ECS_ENDPOINT=ecs-vpc.cn-hangzhou.aliyuncs.comProxy Settings
# HTTP proxy
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
# No proxy for specific domains
export NO_PROXY=localhost,127.0.0.1,.aliyuncs.comTimeout Settings
# Connection timeout (default: 10s)
export ALIBABA_CLOUD_CONNECT_TIMEOUT=30
# Read timeout (default: 10s)
export ALIBABA_CLOUD_READ_TIMEOUT=30Next Steps
After installation and configuration:
1. Install plugins for services you need (v3.3.0+ supports all published product plugins):
aliyun plugin install --names ecs vpc rds
# List all available plugins
aliyun plugin list-remote2. Explore commands:
aliyun ecs --help
aliyun fc --help3. Read documentation:
- Command Syntax Guide
- Global Flags Reference
- Common Scenarios
References
- Official Documentation: https://help.aliyun.com/zh/cli/
- RAM Console: https://ram.console.aliyun.com/
- Access Key Management: https://ram.console.aliyun.com/manage/ak
- Plugin Repository: https://github.com/aliyun/aliyun-cli
Intent Mapping — 场景关键词映射解决方案
用户通常不会直接说解决方案名称,需要从模糊描述推断意图。以下是常见场景的关键词映射:
| 用户描述关键词 | 匹配的解决方案 |
|---|---|
| "搭个网站" / "建站" / "企业门户" | build-a-website |
| "AI 问答" / "智能客服" / "RAG" / "知识库" | analyticdb-rag, elasticsearch-ai-assistant, tongyi-langchain |
| "日志分析" / "日志平台" / "实时日志" | real-time-log-analysis-selectdb, log-management-platform |
| "监控告警" / "Prometheus" / "可观测" | prometheus-cloud-monitoring, end-to-end-tracing-diagnostics |
| "高可用" / "容灾" / "多活" | serverless-ha, tltcamanidl |
| "小程序" / "微信" | develop-your-wechat-mini-program-in-10-minutes |
| "AI 绘画" / "Stable Diffusion" / "图像生成" | pai-eas |
| "数据库迁移" / "MongoDB 迁移" | migrate-self-managed-mongodb-to-cloud |
| "读写分离" | rds-read-write-splitting 或 redis-read-write-splitting-tair-proxy |
| "DeepSeek" / "个人网站 + AI" | ecs-and-deepseek-build-personal-website |
| "消息队列" / "RocketMQ" / "RabbitMQ" | rocketmq-*, rabbitmq-serverless |
| "微服务" / "流量治理" / "限流熔断" | mse-traffic-protection |
| "容器" / "ACK" / "K8s" | ack-services, nginx-ingress |
| "无服务器" / "Serverless" | serverless-ha |
| "数据可视化" / "大屏" / "DataV" | datav-for-atlas, datav-for-digitalization |
| "大模型安全" / "LLM 安全" | large-language-model-security-system |
| "AI 应用" / "百炼" / "Model Studio" | ai-applications-model-studio |
| "WordPress" / "博客" / "MySQL 建站" | mysql-rds |
| "ClickHouse" / "HTAP" | rds-clickhouse-htap |
| "Hologres" / "OLAP" | hologres-olap |
| "PolarDB + AI" / "PolarDB 向量搜索" | polardb-ai-search, polardb-mysql-mcp |
| "物联网" / "时序数据" | lindorm-data-process |
| "CentOS 迁移" / "系统迁移" | centos-alinux-migration |
| "分布式任务调度" / "定时任务" | mse-schedulerx |
| "OLAP 数仓" | hologres-olap, rds-clickhouse-htap |
匹配规则
1. Exact match first — 用户说了解决方案名称,直接匹配 2. Keyword match — 用户描述包含上述关键词,映射到对应方案 3. Partial match OK — 描述与某个方案的领域有部分重叠,作为候选 4. Ambiguous → list candidates — 2-3个方案都匹配时,列出让用户选择:
找到以下几个匹配的方案,请选择:
1. analyticdb-rag — 基于 AnalyticDB + 通义千问的 RAG 智能问答
2. elasticsearch-ai-assistant — Elasticsearch + Kibana 智能运维助手
3. tongyi-langchain — 通义千问 + LangChain 对话服务RAM Policies for Alibaba Cloud Solution Deploy
This document lists all RAM permissions required by the Skill's built-in scripts.
Note: This Skill is a meta-tool — it helps users deploy various Alibaba Cloud solutions. The permissions below cover only the Skill's own helper scripts. Each specific solution deployment will require additional product-level permissions (ECS, VPC, RDS, etc.), which are presented to the user for confirmation in the execution plan (Step B.4) before any resources are created.
Required RAM Permissions
Overview
The Skill's scripts call two Alibaba Cloud services:
| Service | Endpoint | Scripts |
|---|---|---|
| OpenAPI Explorer | openapi-mcp.cn-hangzhou.aliyuncs.com | search_apis.py, search_documents.py, diagnose_cli_command.py, lsit_products.py, lsit_api_overview.py |
| IaCService (Terraform Runtime) | iac.cn-zhangjiakou.aliyuncs.com | terraform_runtime_online.sh |
| STS | (default) | verify_env.sh |
Detailed API-Level Permissions
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:GetCallerIdentity"
],
"Resource": "*",
"Condition": {}
},
{
"Effect": "Allow",
"Action": [
"openapiexplorer:SearchApis",
"openapiexplorer:SearchDocuments",
"openapiexplorer:DiagnoseCLI",
"openapiexplorer:ListProducts",
"openapiexplorer:ListApiOverviews"
],
"Resource": "*",
"Condition": {}
},
{
"Effect": "Allow",
"Action": [
"iacservice:ValidateModule",
"iacservice:ExecuteTerraformPlan",
"iacservice:ExecuteTerraformApply",
"iacservice:ExecuteTerraformDestroy",
"iacservice:GetExecuteState"
],
"Resource": "*",
"Condition": {}
}
]
}Permission Details by Script
| Script | API Action | Permission |
|---|---|---|
verify_env.sh | GetCallerIdentity | sts:GetCallerIdentity |
search_apis.py | SearchApis | openapiexplorer:SearchApis |
search_documents.py | SearchDocuments | openapiexplorer:SearchDocuments |
diagnose_cli_command.py | DiagnoseCLI | openapiexplorer:DiagnoseCLI |
lsit_products.py | ListProducts | openapiexplorer:ListProducts |
lsit_api_overview.py | ListApiOverviews | openapiexplorer:ListApiOverviews |
terraform_runtime_online.sh | ValidateModule | iacservice:ValidateModule |
terraform_runtime_online.sh | ExecuteTerraformPlan | iacservice:ExecuteTerraformPlan |
terraform_runtime_online.sh | ExecuteTerraformApply | iacservice:ExecuteTerraformApply |
terraform_runtime_online.sh | ExecuteTerraformDestroy | iacservice:ExecuteTerraformDestroy |
terraform_runtime_online.sh | GetExecuteState | iacservice:GetExecuteState |
How to Attach Policies
Option 1: Creating Custom Policy (Recommended — Least Privilege)
1. Log in to RAM Console 2. Navigate to Permissions > Policies 3. Click Create Policy 4. Select Script mode 5. Copy and paste the JSON policy from "Detailed API-Level Permissions" above 6. Name the policy: AlibabaCloudSolutionDeploySkillPolicy 7. Click OK to create 8. Navigate to Identities > Users 9. Find your RAM user and click Add Permissions 10. Select Custom Policy and choose AlibabaCloudSolutionDeploySkillPolicy 11. Click OK to attach
Permission Verification
# Verify STS access
aliyun sts GetCallerIdentity --user-agent AlibabaCloud-Agent-Skills
# Verify OpenAPI Explorer access (search for any API)
python3 scripts/search_apis.py 'DescribeInstances'
# Verify IaCService access (validate empty module)
bash scripts/terraform_runtime_online.sh validate 'resource "null_resource" "test" {}'Common Permission Errors
| Error Code | Description | Solution |
|---|---|---|
Forbidden.RAM | RAM user lacks permission for the action | Attach the custom policy above |
InvalidAccessKeyId.NotFound | Access Key ID invalid | Verify credentials via aliyun configure list |
NoPermission | No permission for the resource | Check policy is correctly attached |
Terraform 默认参数
Path A 使用 Terraform 模块部署时,以下参数作为默认值。必须向用户展示并确认,不可静默使用。
通用默认参数
| Parameter | Default | Notes |
|---|---|---|
region | cn-hangzhou | 杭州;可改为 cn-beijing / cn-shanghai / cn-shenzhen |
availability_zone | cn-hangzhou-h | 跟随 region 对应的可用区 |
vpc_cidr | 172.16.0.0/12 | |
vswitch_cidr | 172.16.0.0/24 | |
instance_type | ecs.c7.large | 2C4G;GPU 场景改为 ecs.gn6i-c8g1.2xlarge |
instance_name | <solution-name>-server | 以方案名为前缀 |
disk_size | 40 (GB) | 系统盘 |
rds_instance_type | mysql.n2.medium.1 | 2C4G RDS |
password | (must ask user) | Passwords are sensitive credentials — never generate or assume one. The user must provide it. |
确认格式示例
将使用以下参数部署,请确认或告知需要修改:
• Region: cn-hangzhou
• Instance type: ecs.c7.large
• VPC CIDR: 172.16.0.0/12
• Password: (请提供)模块特定参数
不同模块有额外参数,运行时检查模块 README:
- Terraform Registry:
https://registry.terraform.io/modules/alibabacloud-automation/<module_name>/alicloud/latest
Terraform Online Runtime — Usage Guide
Execute Terraform configurations remotely through Alibaba Cloud's IaCService using a single pre-built script. No local terraform CLI required.
Prerequisites
- aliyun CLI (v3.2+) installed and configured with valid AK/SK credentials (
aliyun configure) - The credentials must have permission to call IaCService APIs and to manage whatever cloud resources the Terraform code declares
SKILL_DIR Setup
Before running the script, set SKILL_DIR to the directory containing the skill's SKILL.md:
# Option A: dynamic (for use inside shell scripts)
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Option B: explicit absolute path
SKILL_DIR="/path/to/your-skill-dir"
TF="${SKILL_DIR}/scripts/terraform_runtime_online.sh"Commands
terraform_runtime_online.sh validate <hcl_file_or_code>
terraform_runtime_online.sh plan <hcl_file_or_code> [existing_state_id]
terraform_runtime_online.sh apply <hcl_file_or_code> [--state-id <id>]
terraform_runtime_online.sh apply --state-id <id>
terraform_runtime_online.sh destroy <state_id>
terraform_runtime_online.sh poll <state_id> [max_attempts] [interval_seconds]Command Usage
validate — Validate HCL syntax
$TF validate main.tf
$TF validate 'resource "alicloud_vpc" "vpc" { vpc_name = "test" cidr_block = "172.16.0.0/12" }'Exit codes: 0 = Valid, 1 = Invalid / error.
plan — Preview changes
plan_output=$($TF plan main.tf)
STATE_ID=$(echo "$plan_output" | grep '^STATE_ID=' | cut -d= -f2)
PLAN_FILE=$(echo "$plan_output" | grep '^PLAN_OUTPUT_FILE=' | cut -d= -f2)
# Compact plan summary is printed to stderr automatically.
# To view full details: cat "$PLAN_FILE"Exit codes: 0 = Planned, 1 = Errored.
apply — Create or update infrastructure
# Fresh apply (no prior state)
STATE_ID=$($TF apply main.tf | grep '^STATE_ID=' | cut -d= -f2)
echo "STATE_ID=$STATE_ID" >> terraform_state_ids.env
# Incremental update against existing state
STATE_ID=$($TF apply updated.tf --state-id "$EXISTING_STATE_ID" | grep '^STATE_ID=' | cut -d= -f2)
echo "STATE_ID=$STATE_ID" >> terraform_state_ids.envExit codes: 0 = Applied, 1 = Errored.
destroy — Destroy resources
$TF destroy "$STATE_ID" --forceWithout --force, the script lists resources and exits without destroying (safety pre-check). Always pass --force after confirming with the user.
Exit codes: 0 = Destroyed, 1 = Failed or not confirmed.
poll — Poll status (standalone use)
$TF poll <state_id> [max_attempts] [interval_seconds]Workflow Patterns
Pattern 1: Full lifecycle (plan → confirm → apply → destroy)
# 1. Write HCL
cat > main.tf << 'EOF'
resource "alicloud_vpc" "vpc" {
vpc_name = "my-vpc"
cidr_block = "172.16.0.0/12"
}
EOF
# 2. Plan
plan_output=$($TF plan main.tf)
PLAN_FILE=$(echo "$plan_output" | grep '^PLAN_OUTPUT_FILE=' | cut -d= -f2)
# ⚠️ STOP — present plan summary to user and wait for explicit confirmation before continuing
# 3. Apply (fresh apply with code; do NOT reuse the plan STATE_ID)
STATE_ID=$($TF apply main.tf | grep '^STATE_ID=' | cut -d= -f2)
echo "STATE_ID=$STATE_ID" >> terraform_state_ids.env
# 4. Destroy when done
$TF destroy "$STATE_ID" --forcePattern 2: Quick apply (skip plan)
STATE_ID=$($TF apply main.tf | grep '^STATE_ID=' | cut -d= -f2)
echo "STATE_ID=$STATE_ID" >> terraform_state_ids.envPattern 3: Incremental update
STATE_ID=$($TF apply updated.tf --state-id "$EXISTING_STATE_ID" | grep '^STATE_ID=' | cut -d= -f2)Pattern 4: Validate before deploy
$TF validate main.tf && echo "Validation passed"Critical Rules
- ALWAYS use `$TF <command>` — never write inline
aliyun iacservicecommands; inline commands silently fail due to argument/endpoint quirks - ALWAYS save every `STATE_ID` returned by apply to a file (e.g.,
terraform_state_ids.env) for later cleanup - After `plan`, ALWAYS wait for user confirmation before calling
apply - After plan, use fresh apply (
$TF apply <code>), NOT--state-idfrom the plan run — IaCService locks plan stateIds
Error Reference
| Error | Likely Cause |
|---|---|
InvalidOperation.TaskStatus | Plan stateId is locked — use fresh apply with code instead |
Your account does not have enough balance | Insufficient balance for postpaid resources |
InvalidAccessKeyId | AK/SK credentials are invalid or expired |
InvalidImageId.NotFound | Image ID doesn't exist in the target region |
| Provider/resource errors | Unsupported resource types or invalid arguments |
技术解决方案
| 解决方案模版名称 | 描述 | 进度 | Module 名称 | Module 地址 | 备注 |
|---|---|---|---|---|---|
| ack-services | 创建高可用、可自动伸缩的 Kubernetes 集群基础设施,使用阿里云 ACK 容器服务,支持集群自动伸缩(CAS)和水平 Pod 自动伸缩(HPA),适用于需要容器化应用编排和管理的企业 | 已完成 | ack-services | https://registry.terraform.io/modules/alibabacloud-automation/ack-services/alicloud/latest | |
| alb-acrlb | 通过阿里云 ALB 应用负载均衡和 CEN 云企业网实现跨地域流量调度与负载均衡,支持多地域 ECS 实例部署,适用于需要跨地域高可用与容灾的企业应用 | 已完成 | alb-cross-region-load-balancing | https://registry.terraform.io/modules/alibabacloud-automation/alb-cross-region-load-balancing/alicloud/latest | 多 region 抽象子Module |
| analyticdb-rag | 基于 AnalyticDB for PostgreSQL 和通义千问构建智能客服 RAG 系统,实现检索增强生成架构,适用于需要 AI 智能问答和企业知识库应用的场景 | 已完成 | analyticdb-rag | https://registry.terraform.io/modules/alibabacloud-automation/analyticdb-rag/alicloud/latest | |
| build-a-website | 创建企业门户网站基础架构,包含 VPC、RDS MySQL 数据库和 Mobi 低代码开发平台集成,适用于快速构建现代企业网站和低代码应用开发 | 已完成 | build-enterprise-portal-website | https://registry.terraform.io/modules/alibabacloud-automation/build-enterprise-portal-website/alicloud/latest | |
| build-ai-applications-based-on-alibaba-cloud-model-studio | 基于阿里云百炼 Model Studio 构建 AI 应用和智能体(Agent)工作流,自动部署 ECS 实例和 AI 应用环境,适用于企业快速构建和部署 AI 驱动的应用 | 已完成 | ai-applications-model-studio | https://registry.terraform.io/modules/alibabacloud-automation/ai-applications-model-studio/alicloud/latest | |
| build-an-observability-system-for-ai-applications-at-low-costs | 使用 ARMS 应用实时监控服务构建 AI 应用低成本可观测系统,集成 VPC、ECS 和监控告警功能,适用于需要实时监控 AI 应用性能和运行状态的企业 | 已完成 | ai-observability-system | https://registry.terraform.io/modules/alibabacloud-automation/ai-observability-system/alicloud/latest | |
| build-large-model-application-security-system | 为大语言模型应用构建全面安全防护体系,包含 VPC 网络隔离、ECS 计算资源、RAM 身份管理和自动化安全工具部署,适用于保护 AI 应用免受内容安全和访问控制等安全威胁 | 已完成 | large-language-model-security-system | https://registry.terraform.io/modules/alibabacloud-automation/large-language-model-security-system/alicloud/latest | |
| build-large-scale-low-cost-real-time-log-management-platform | 构建大规模低成本实时日志管理平台,使用 SLS 日志服务、ECS 和 Kibana 可视化,适用于需要实时日志收集、处理和分析的企业级应用 | 已完成 | log-management-platform | https://registry.terraform.io/modules/alibabacloud-automation/log-management-platform/alicloud/latest | |
| centos-alinux | 将 CentOS 系统迁移至阿里云 Linux 操作系统的自动化解决方案,在 CentOS 7 系统上自动部署迁移环境,适用于需要将自建 CentOS 服务器平滑迁移到阿里云 Linux 的企业 | 已完成 | centos-alinux-migration | https://registry.terraform.io/modules/alibabacloud-automation/centos-alinux-migration/alicloud/latest | |
| comprehensive-real-time-monitoring-of-cloud-services-through-managed-service-for-prometheus | 通过 Prometheus 托管服务对云上资源进行全面实时监控,集成 VPC、ECS、RDS、Redis、RocketMQ 和 MSE 等多种服务,适用于云原生应用的统一可观测性监控与告警 | 已完成 | prometheus-cloud-monitoring | https://registry.terraform.io/modules/alibabacloud-automation/prometheus-cloud-monitoring/alicloud/latest | |
| datav-for-atlas | 构建 DataV Atlas 时空决策平台,使用 RDS PostgreSQL 存储空间数据并进行可视化分析,适用于需要时空数据分析和可视化大屏决策的企业 | 已完成 | datav-atlas-solution | https://registry.terraform.io/modules/alibabacloud-automation/datav-atlas-solution/alicloud/latest | |
| datav-for-digitalization | 快速构建企业数字化管理大屏,部署 VPC、VSwitch、安全组和 RDS MySQL 数据库,为 DataV 数字孪生大屏提供数据存储和网络安全基础设施,适用于需要搭建企业经营数据可视化看板的场景 | 已完成 | datav-for-digitalization | https://registry.terraform.io/modules/alibabacloud-automation/datav-for-digitalization/alicloud/latest | |
| develop-apps | 基于阿里云 EMAS 移动研发平台和云效研发协作平台,构建云上移动应用开发完整基础设施(VPC、ECS、RDS),提供移动应用从开发、测试到运维的全生命周期管理能力 | 已完成 | develop-apps | https://registry.terraform.io/modules/alibabacloud-automation/develop-apps/alicloud/latest | |
| develop-your-wechat-mini-program-in-10-minutes | 快速搭建微信/支付宝小程序后端基础设施,自动部署 VPC、ECS、RDS MySQL 数据库并完成 WordPress 配置,适用于小程序后端开发和内容管理网站的快速搭建 | 已完成 | wechat-mini-program-infrastructure | https://registry.terraform.io/modules/alibabacloud-automation/wechat-mini-program-infrastructure/alicloud/latest | |
| ecs-and-deepseek-build-personal-website | 在 ECS 上一键部署 DeepSeek AI 个人网站,自动创建 VPC、ECS 实例、安全组和 RAM 用户并完成 DeepSeek 应用配置,适用于开发者快速搭建个人 AI 助手网站 | 已完成 | deepseek-personal-website | https://registry.terraform.io/modules/alibabacloud-automation/deepseek-personal-website/alicloud/latest | |
| ecs-deploy-deepsite-application | 在 ECS 上自动化部署 DeepSite 应用,DeepSite 是阿里云 AI 前端代码生成工具,可将自然语言描述转换为 Web 应用,支持 Qwen 和 DeepSeek 等大模型,适用于 Web 工具开发和产品快速原型场景 | 已完成 | ecs-deploy-deepsite-application | https://registry.terraform.io/modules/alibabacloud-automation/ecs-deploy-deepsite-application/alicloud/latest | |
| elasticsearch-ai-assistant | 构建 Elasticsearch 智能运维助手,部署 VPC、Elasticsearch 实例和 Kibana,提供分布式系统下的日志分析和智能运维可视化能力,适用于需要智能运维监控和日志检索的场景 | 已完成 | elasticsearch-ai-assistant | https://registry.terraform.io/modules/alibabacloud-automation/elasticsearch-ai-assistant/alicloud/latest | |
| end-to-end-tracing-and-diagnostics | 构建分布式应用全链路追踪与诊断系统,部署 VPC、ECS、RDS、Redis、RocketMQ 和 MSE 等资源,提供微服务架构下的性能监控与故障定位能力,适用于分布式微服务架构的可观测性建设 | 已完成 | end-to-end-tracing-diagnostics | https://registry.terraform.io/modules/alibabacloud-automation/end-to-end-tracing-diagnostics/alicloud/latest | |
| ha-web | 构建高可用 Web 共享存储服务,部署多 ECS 实例、NAS 共享文件存储和 CLB 负载均衡,提供可横向扩展的 Web 架构,适用于需要高可用性和多节点共享存储的 Web 应用场景 | 已完成 | high-availability-web-shared-storage | https://registry.terraform.io/modules/alibabacloud-automation/high-availability-web-shared-storage/alicloud/latest | |
| hologres-olap | 基于阿里云 Hologres 实时数仓构建高性能轻量级 OLAP 分析平台,创建 VPC、VSwitch 和 Hologres 实例,适用于需要对大规模数据进行实时 OLAP 多维分析的场景 | 已完成 | hologres-olap | https://registry.terraform.io/modules/alibabacloud-automation/hologres-olap/alicloud/latest | |
| improve-app-availability | 通过 ALB 应用负载均衡和 ESS 弹性伸缩提升应用可用性,支持基于负载的自动扩缩容,适用于需要高可用性和弹性伸缩能力的 Web 应用场景 | 已完成 | improve-app-availability | https://registry.terraform.io/modules/alibabacloud-automation/improve-app-availability/alicloud/latest | |
| lindorm-data-process | 构建统一时序数据分析处理平台,部署 VPC、ECS 和 Lindorm 时序数据库,适用于物联网、工业互联网等场景下海量时序数据的高效处理与分析 | 已完成 | lindorm-data-process | https://registry.terraform.io/modules/alibabacloud-automation/lindorm-data-process/alicloud/latest | |
| log-monitoring-alarming | 创建基于 SLS 日志服务的全面日志监控告警解决方案,部署 VPC、ECS、SLS 项目及日志采集配置,实现应用日志实时采集与告警通知,适用于需要实时监控应用日志并快速响应异常的企业 | 已完成 | log-monitoring-alarming | https://registry.terraform.io/modules/alibabacloud-automation/log-monitoring-alarming/alicloud/latest | |
| migrate-self-managed-mongodb-to-cloud | 将自建 MongoDB 迁移至阿里云云数据库 MongoDB 的完整解决方案,自动创建 VPC、ECS、ApsaraDB for MongoDB 并执行迁移脚本,适用于需要将自建 MongoDB 平滑迁移上云的企业 | 已完成 | mongodb-migration | https://registry.terraform.io/modules/alibabacloud-automation/mongodb-migration/alicloud/latest | |
| mse-schedulerx | 基于 MSE SchedulerX 构建分布式任务调度完整解决方案,部署 VPC、ECS、RDS MySQL 并自动部署 SchedulerX 示例应用,适用于需要可靠分布式定时任务和批量任务调度的企业应用 | 已完成 | mse-schedulerx | https://registry.terraform.io/modules/alibabacloud-automation/mse-schedulerx/alicloud/latest | |
| nginx-ingress | 在阿里云 ACK Kubernetes 集群上部署 Nginx 并通过 Ingress 对外暴露服务,集成 Nginx Ingress Controller、SLS 日志和 ARMS Prometheus 监控,适用于需要在 Kubernetes 上统一管理 HTTP/HTTPS 流量入口的场景 | 已完成 | nginx-ingress-deployment | https://registry.terraform.io/modules/alibabacloud-automation/nginx-ingress-deployment/alicloud/latest | |
| oss-nginx | 将 Nginx 访问日志通过 SLS 日志服务自动采集并归档到 OSS 对象存储,部署 VPC、ECS、SLS 和 OSS 资源,适用于需要低成本长期归档应用访问日志的场景 | 已完成 | oss-nginx-log-archiving | https://registry.terraform.io/modules/alibabacloud-automation/oss-nginx-log-archiving/alicloud/latest | |
| pai-eas | 在阿里云 PAI-EAS 上部署 Stable Diffusion WebUI AI 绘图服务,集成 NAS 文件存储、NAT Gateway 和 GPU 计算资源,适用于需要在云上提供文生图/图生图 AI 绘画服务的场景 | 已完成 | pai-eas-stable-diffusion | https://registry.terraform.io/modules/alibabacloud-automation/pai-eas-stable-diffusion/alicloud/latest | |
| polardb-ai-search | 基于 PolarDB for PostgreSQL 的原生 SQL 实现多模态 AI 智能搜索能力,部署 VPC、PolarDB 集群和 OSS 存储资源,适用于需要对图片、文本等多模态内容进行向量检索和 AI 搜索的场景 | 已完成 | polardb-ai-search | https://registry.terraform.io/modules/alibabacloud-automation/polardb-ai-search/alicloud/latest | |
| polardb-mysql-mcp | 通过 MCP(Model Context Protocol)协议赋能 PolarDB MySQL,构建支持可视化 OLAP 智能体应用的数据库环境,部署 VPC、PolarDB 集群并开启公网访问端点,适用于 AI 大模型直接操作数据库进行数据分析的场景 | 已完成 | polardb-mysql-mcp | https://registry.terraform.io/modules/alibabacloud-automation/polardb-mysql-mcp/alicloud/latest | |
| rabbitmq-serverless | 创建 RabbitMQ Serverless 消息队列实例及完整路由配置(虚拟主机、Exchange、队列和绑定),含 RAM 用户权限管理,适用于需要快速接入 Serverless 消息队列实现系统解耦和异步通信的场景 | 已完成 | rabbitmq-serverless | https://registry.terraform.io/modules/alibabacloud-automation/rabbitmq-serverless/alicloud/latest | |
| rdsclickhouse-htap | 使用 RDS MySQL 和 ClickHouse 构建 HTAP(混合事务分析处理)一体化解决方案,部署 VPC、RDS(事务处理)、ClickHouse(分析处理)和 ECS,适用于同时需要高并发写入和实时数据分析的业务场景 | 已完成 | rds-clickhouse-htap | https://registry.terraform.io/modules/alibabacloud-automation/rds-clickhouse-htap/alicloud/latest | |
| read-write-splitting-through-rds-proxy | 通过 RDS 数据库代理实现 MySQL 读写分离,自动将读请求路由到只读实例以提升数据库性能,部署 VPC、ECS、RDS 主实例+只读副本和代理,适用于读多写少、需要提升数据库查询吞吐量的应用 | 已完成 | rds-read-write-splitting | https://registry.terraform.io/modules/alibabacloud-automation/rds-read-write-splitting/alicloud/latest | |
| read-write-splitting-through-tair-proxy | 通过 Tair 代理实现 Redis 读写分离,自动将读请求路由到只读节点以提升 Redis 并发性能,部署 VPC、ECS 和 Tair(Redis 企业版)实例,适用于 Redis 高并发读多写少场景 | 已完成 | redis-read-write-splitting-tair-proxy | https://registry.terraform.io/modules/alibabacloud-automation/redis-read-write-splitting-tair-proxy/alicloud/latest | |
| real-time-log-analysis-with-selectdb | 使用 SelectDB 构建高效实时日志存储与分析平台,部署 VPC、ECS 日志处理实例和 SelectDB 数据库,适用于需要对海量日志进行实时分析和多维查询的业务场景 | 已完成 | real-time-log-analysis-selectdb | https://registry.terraform.io/modules/alibabacloud-automation/real-time-log-analysis-selectdb/alicloud/latest | |
| rocketmq-data-consistency | 使用 RocketMQ 事务消息实现分布式事务与跨服务数据一致性,部署 VPC、ECS、RDS 和 RocketMQ 资源,适用于电商订单、支付等需要保证多服务间数据强一致性的分布式系统 | 已完成 | rocketmq-data-consistency | https://registry.terraform.io/modules/alibabacloud-automation/rocketmq-data-consistency/alicloud/latest | |
| rocketmq-for-multi-agent-communication | 基于 RocketMQ 实现多智能体(Multi-Agent)系统异步通信,创建 VPC、VSwitch、ECS 和安全组等基础设施,适用于 AI 多 Agent 协同工作时的消息传递和任务协调场景 | 已完成 | rocketmq-multi-agent-communication | https://registry.terraform.io/modules/alibabacloud-automation/rocketmq-multi-agent-communication/alicloud/latest | |
| serverless-ha | 基于 PolarDB MySQL Serverless、ALB 和 SAE 构建 Serverless 高可用架构,支持自动弹性伸缩和多可用区高可用,适用于需要极简运维、按需付费的 Serverless Web 应用场景 | 已完成 | serverless-high-availability | https://registry.terraform.io/modules/alibabacloud-automation/serverless-high-availability/alicloud/latest | |
| the-headless-architecture-solution-of-alibaba-cloud-ecs | 基于 ECS 实现前后端分离(Headless)架构,前端 Nginx 与后端 Java 服务跨多可用区部署,通过 ALB 实现流量分发,适用于需要高可用前后端分离 Web 应用的场景 | 已完成 | ecs-headless-architecture | https://registry.terraform.io/modules/alibabacloud-automation/ecs-headless-architecture/alicloud/latest | |
| the-headless-architecture-solution-of-alibaba-cloud-sae | 基于 SAE Serverless 应用引擎实现前后端分离(Headless)架构,通过 SLB 负载均衡分发流量,适用于需要无需管理服务器即可快速部署前后端分离 Web 应用的场景 | 已完成 | sae-headless-architecture | https://registry.terraform.io/modules/alibabacloud-automation/sae-headless-architecture/alicloud/latest | |
| tltcamanidl | 构建多地域同城双活灾备架构,通过 CEN 云企业网跨区域互联、DTS 数据同步和 PolarDB 集群实现 RPO/RTO 极低的高可用容灾,适用于金融、电商等需要跨地域容灾保障的关键业务系统 | 已完成 | multi-region-active-active-disaster-recovery | https://registry.terraform.io/modules/alibabacloud-automation/multi-region-active-active-disaster-recovery/alicloud/latest | |
| tongyi-langchain | 基于通义千问和 LangChain 框架构建智能对话服务,使用 PAI-EAS 部署 AI 模型推理服务、NAS 文件存储等资源,适用于快速构建企业级 AI 问答和对话应用的场景 | 已完成 | tongyi-langchain | https://registry.terraform.io/modules/alibabacloud-automation/tongyi-langchain/alicloud/latest | |
| use-mse-to-implement-comprehensive-traffic-protection | 基于 MSE 微服务引擎实现全面流量防护,提供限流降级、熔断、服务发现和配置管理能力,适用于微服务架构下需要保障服务稳定性、防止流量洪峰打垮下游服务的场景 | 已完成 | mse-traffic-protection | https://registry.terraform.io/modules/alibabacloud-automation/mse-traffic-protection/alicloud/latest | |
| mysql-rds | 使用 MySQL RDS 数据库部署 WordPress 的完整建站解决方案,自动化创建 VPC、ECS Web 服务器和 RDS MySQL 数据库并配置 WordPress,适用于中小企业和个人快速搭建网站或博客的场景 | 已完成 | mysql-rds-wordpress | https://registry.terraform.io/modules/alibabacloud-automation/mysql-rds-wordpress/alicloud/latest |
# -*- coding: utf-8 -*-
"""Diagnose an Alibaba Cloud CLI command error.
Usage:
python3 scripts/diagnose_cli_command.py <command> <error>
Example:
python3 scripts/diagnose_cli_command.py 'aliyun ecs DescribeInstances' 'InvalidAccessKeyId.NotFound'
"""
import sys
import json
from alibabacloud_tea_openapi.client import Client as OpenApiClient
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
def validate_input(value, name, max_length=2000):
"""Validate input value for length and non-empty."""
if not value or len(value) > max_length:
print(f"Error: {name} exceeds {max_length} chars or is empty", file=sys.stderr)
sys.exit(1)
def sanitize_response(obj):
"""Recursively sanitize sensitive fields in response object."""
sensitive_keys = {'accesskeyid', 'accesskeysecret', 'securitytoken', 'password', 'secret', 'accountid', 'credential'}
if isinstance(obj, dict):
sanitized = {}
for key, value in obj.items():
if key.lower() in sensitive_keys:
sanitized[key] = "***REDACTED***"
else:
sanitized[key] = sanitize_response(value)
return sanitized
elif isinstance(obj, list):
return [sanitize_response(item) for item in obj]
else:
return obj
def create_client() -> OpenApiClient:
credential = CredentialClient()
config = open_api_models.Config(credential=credential)
config.endpoint = 'openapi-mcp.cn-hangzhou.aliyuncs.com'
config.user_agent = 'AlibabaCloud-Agent-Skills'
return OpenApiClient(config)
def diagnose_cli(command: str, error: str) -> dict:
client = create_client()
params = open_api_models.Params(
action='DiagnoseCLI',
version='2024-11-30',
protocol='HTTPS',
method='POST',
auth_type='AK',
style='ROA',
pathname='/diagnoseCLI',
req_body_type='json',
body_type='json'
)
body = {'command': command, 'error': error}
runtime = util_models.RuntimeOptions(read_timeout=60000)
request = open_api_models.OpenApiRequest(body=body)
return client.call_api(params, request, runtime)
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Usage: python3 scripts/diagnose_cli_command.py <command> <error>", file=sys.stderr)
sys.exit(1)
command = sys.argv[1]
error = sys.argv[2]
validate_input(command, 'command', max_length=2000)
validate_input(error, 'error', max_length=4000)
result = diagnose_cli(command, error)
sanitized = sanitize_response(result)
print(json.dumps(sanitized, ensure_ascii=False, indent=2))
# -*- coding: utf-8 -*-
"""List API overviews for a given Alibaba Cloud product.
Usage:
python3 scripts/lsit_api_overview.py <product> <version> [filter]
Example:
python3 scripts/lsit_api_overview.py Ecs 2014-05-26
python3 scripts/lsit_api_overview.py Ecs 2014-05-26 '云助手'
"""
import sys
import json
import re
from alibabacloud_tea_openapi.client import Client as OpenApiClient
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
def validate_product(product):
"""Validate product matches ^[a-zA-Z][a-zA-Z0-9-]{0,49}$."""
if not re.match(r'^[a-zA-Z][a-zA-Z0-9-]{0,49}$', product):
print(f"Error: product must start with letter and contain only alphanumeric or hyphen, max 50 chars", file=sys.stderr)
sys.exit(1)
def validate_version(version):
r"""Validate version matches ^\d{4}-\d{2}-\d{2}$."""
if not re.match(r'^\d{4}-\d{2}-\d{2}$', version):
print(f"Error: version must be in YYYY-MM-DD format", file=sys.stderr)
sys.exit(1)
def validate_input(value, name, max_length=2000):
"""Validate input value for length and non-empty."""
if not value or len(value) > max_length:
print(f"Error: {name} exceeds {max_length} chars or is empty", file=sys.stderr)
sys.exit(1)
def sanitize_response(obj):
"""Recursively sanitize sensitive fields in response object."""
sensitive_keys = {'accesskeyid', 'accesskeysecret', 'securitytoken', 'password', 'secret', 'accountid', 'credential'}
if isinstance(obj, dict):
sanitized = {}
for key, value in obj.items():
if key.lower() in sensitive_keys:
sanitized[key] = "***REDACTED***"
else:
sanitized[key] = sanitize_response(value)
return sanitized
elif isinstance(obj, list):
return [sanitize_response(item) for item in obj]
else:
return obj
def create_client() -> OpenApiClient:
credential = CredentialClient()
config = open_api_models.Config(credential=credential)
config.endpoint = 'openapi-mcp.cn-hangzhou.aliyuncs.com'
config.user_agent = 'AlibabaCloud-Agent-Skills'
return OpenApiClient(config)
def list_api_overviews(product: str, version: str, filter_keyword: str = '') -> dict:
client = create_client()
params = open_api_models.Params(
action='ListApiOverviews',
version='2024-11-30',
protocol='HTTPS',
method='GET',
auth_type='AK',
style='ROA',
pathname='/listApiOverviews',
req_body_type='json',
body_type='json'
)
queries = {'product': product, 'version': version}
if filter_keyword:
queries['filter'] = filter_keyword
runtime = util_models.RuntimeOptions(read_timeout=30000)
request = open_api_models.OpenApiRequest(
query=OpenApiUtilClient.query(queries)
)
return client.call_api(params, request, runtime)
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Usage: python3 scripts/lsit_api_overview.py <product> <version> [filter]", file=sys.stderr)
sys.exit(1)
product = sys.argv[1]
version = sys.argv[2]
filter_kw = sys.argv[3] if len(sys.argv) > 3 else ''
validate_product(product)
validate_version(version)
if filter_kw:
validate_input(filter_kw, 'filter', max_length=200)
result = list_api_overviews(product, version, filter_kw)
sanitized = sanitize_response(result)
print(json.dumps(sanitized, ensure_ascii=False, indent=2))
# -*- coding: utf-8 -*-
"""List Alibaba Cloud products by keyword filter.
Usage:
python3 scripts/lsit_products.py <filter_keyword>
Example:
python3 scripts/lsit_products.py '云网络'
python3 scripts/lsit_products.py 'ECS'
"""
import sys
import json
from alibabacloud_tea_openapi.client import Client as OpenApiClient
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
def validate_input(value, name, max_length=2000):
"""Validate input value for length and non-empty."""
if not value or len(value) > max_length:
print(f"Error: {name} exceeds {max_length} chars or is empty", file=sys.stderr)
sys.exit(1)
def sanitize_response(obj):
"""Recursively sanitize sensitive fields in response object."""
sensitive_keys = {'accesskeyid', 'accesskeysecret', 'securitytoken', 'password', 'secret', 'accountid', 'credential'}
if isinstance(obj, dict):
sanitized = {}
for key, value in obj.items():
if key.lower() in sensitive_keys:
sanitized[key] = "***REDACTED***"
else:
sanitized[key] = sanitize_response(value)
return sanitized
elif isinstance(obj, list):
return [sanitize_response(item) for item in obj]
else:
return obj
def create_client() -> OpenApiClient:
credential = CredentialClient()
config = open_api_models.Config(credential=credential)
config.endpoint = 'openapi-mcp.cn-hangzhou.aliyuncs.com'
config.user_agent = 'AlibabaCloud-Agent-Skills'
return OpenApiClient(config)
def list_products(filter_keyword: str) -> dict:
client = create_client()
params = open_api_models.Params(
action='ListProducts',
version='2024-11-30',
protocol='HTTPS',
method='GET',
auth_type='AK',
style='ROA',
pathname='/listProducts',
req_body_type='json',
body_type='json'
)
queries = {}
if filter_keyword:
queries['filter'] = filter_keyword
runtime = util_models.RuntimeOptions(read_timeout=30000)
request = open_api_models.OpenApiRequest(
query=OpenApiUtilClient.query(queries)
)
return client.call_api(params, request, runtime)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python3 scripts/lsit_products.py <filter_keyword>", file=sys.stderr)
sys.exit(1)
filter_keyword = sys.argv[1]
validate_input(filter_keyword, 'filter_keyword', max_length=200)
result = list_products(filter_keyword)
sanitized = sanitize_response(result)
print(json.dumps(sanitized, ensure_ascii=False, indent=2))
# -*- coding: utf-8 -*-
"""Search Alibaba Cloud APIs by natural language prompt.
Usage:
python3 scripts/search_apis.py <prompt> [limit]
Example:
python3 scripts/search_apis.py '创建ECS实例'
python3 scripts/search_apis.py '创建ECS实例' 5
"""
import sys
import json
from alibabacloud_tea_openapi.client import Client as OpenApiClient
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
def validate_input(value, name, max_length=2000):
"""Validate input value for length and non-empty."""
if not value or len(value) > max_length:
print(f"Error: {name} exceeds {max_length} chars or is empty", file=sys.stderr)
sys.exit(1)
def validate_int_range(value, name, min_val, max_val):
"""Validate integer is within range."""
if value < min_val or value > max_val:
print(f"Error: {name} must be between {min_val} and {max_val}", file=sys.stderr)
sys.exit(1)
def sanitize_response(obj):
"""Recursively sanitize sensitive fields in response object."""
sensitive_keys = {'accesskeyid', 'accesskeysecret', 'securitytoken', 'password', 'secret', 'accountid', 'credential'}
if isinstance(obj, dict):
sanitized = {}
for key, value in obj.items():
if key.lower() in sensitive_keys:
sanitized[key] = "***REDACTED***"
else:
sanitized[key] = sanitize_response(value)
return sanitized
elif isinstance(obj, list):
return [sanitize_response(item) for item in obj]
else:
return obj
def create_client() -> OpenApiClient:
credential = CredentialClient()
config = open_api_models.Config(credential=credential)
config.endpoint = 'openapi-mcp.cn-hangzhou.aliyuncs.com'
config.user_agent = 'AlibabaCloud-Agent-Skills'
return OpenApiClient(config)
def search_apis(prompt: str, limit: int = 5) -> dict:
client = create_client()
params = open_api_models.Params(
action='SearchApis',
version='2024-11-30',
protocol='HTTPS',
method='POST',
auth_type='AK',
style='ROA',
pathname='/searchApis',
req_body_type='json',
body_type='json'
)
body = {'prompt': prompt, 'limit': limit}
runtime = util_models.RuntimeOptions(read_timeout=60000)
request = open_api_models.OpenApiRequest(body=body)
return client.call_api(params, request, runtime)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python3 scripts/search_apis.py <prompt> [limit]", file=sys.stderr)
sys.exit(1)
prompt = sys.argv[1]
limit = int(sys.argv[2]) if len(sys.argv) > 2 else 5
validate_input(prompt, 'prompt', max_length=2000)
validate_int_range(limit, 'limit', 1, 100)
result = search_apis(prompt, limit)
sanitized = sanitize_response(result)
print(json.dumps(sanitized, ensure_ascii=False, indent=2))
# -*- coding: utf-8 -*-
"""Search Alibaba Cloud documents by keyword.
Usage:
python3 scripts/search_documents.py <query> [limit]
Example:
python3 scripts/search_documents.py 'ECS实例规格'
python3 scripts/search_documents.py 'VPC网络配置' 5
"""
import sys
import json
from alibabacloud_tea_openapi.client import Client as OpenApiClient
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
def validate_input(value, name, max_length=2000):
"""Validate input value for length and non-empty."""
if not value or len(value) > max_length:
print(f"Error: {name} exceeds {max_length} chars or is empty", file=sys.stderr)
sys.exit(1)
def validate_int_range(value, name, min_val, max_val):
"""Validate integer is within range."""
if value < min_val or value > max_val:
print(f"Error: {name} must be between {min_val} and {max_val}", file=sys.stderr)
sys.exit(1)
def sanitize_response(obj):
"""Recursively sanitize sensitive fields in response object."""
sensitive_keys = {'accesskeyid', 'accesskeysecret', 'securitytoken', 'password', 'secret', 'accountid', 'credential'}
if isinstance(obj, dict):
sanitized = {}
for key, value in obj.items():
if key.lower() in sensitive_keys:
sanitized[key] = "***REDACTED***"
else:
sanitized[key] = sanitize_response(value)
return sanitized
elif isinstance(obj, list):
return [sanitize_response(item) for item in obj]
else:
return obj
def create_client() -> OpenApiClient:
credential = CredentialClient()
config = open_api_models.Config(credential=credential)
config.endpoint = 'openapi-mcp.cn-hangzhou.aliyuncs.com'
config.user_agent = 'AlibabaCloud-Agent-Skills'
return OpenApiClient(config)
def search_documents(query: str, limit: int = 5) -> dict:
client = create_client()
params = open_api_models.Params(
action='SearchDocuments',
version='2024-11-30',
protocol='HTTPS',
method='POST',
auth_type='AK',
style='ROA',
pathname='/searchDocuments',
req_body_type='json',
body_type='json'
)
body = {'query': query, 'limit': limit}
runtime = util_models.RuntimeOptions(read_timeout=60000)
request = open_api_models.OpenApiRequest(body=body)
return client.call_api(params, request, runtime)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python3 scripts/search_documents.py <query> [limit]", file=sys.stderr)
sys.exit(1)
query = sys.argv[1]
limit = int(sys.argv[2]) if len(sys.argv) > 2 else 5
validate_input(query, 'query', max_length=2000)
validate_int_range(limit, 'limit', 1, 100)
result = search_documents(query, limit)
sanitized = sanitize_response(result)
print(json.dumps(sanitized, ensure_ascii=False, indent=2))
#!/usr/bin/env bash
set -euo pipefail
# terraform_runtime_online.sh - Execute Terraform via Alibaba Cloud IaCService
#
# Usage:
# terraform_runtime_online.sh validate <hcl_file_or_code>
# terraform_runtime_online.sh plan <hcl_file_or_code> [existing_state_id]
# terraform_runtime_online.sh apply <hcl_file_or_code> # fresh apply (first time)
# terraform_runtime_online.sh apply <hcl_file_or_code> --state-id <id> # retry failed apply / update existing state
# terraform_runtime_online.sh apply --state-id <id> # apply a previously planned state
# terraform_runtime_online.sh destroy <state_id> [--force]
# terraform_runtime_online.sh poll <state_id> [max_attempts] [interval_seconds]
#
# ⚠️ STATE_ID REUSE RULE:
# - plan → apply: do NOT pass the plan stateId to apply (IaCService locks plan states)
# - Once a STATE_ID exists (from a previous apply), ALL subsequent changes to the same
# deployment MUST reuse it via --state-id, including:
# • Retrying after a failed/partial apply
# • Adding new resources to main.tf
# • Modifying existing resource configuration
# Only the very first apply of a brand-new deployment runs without --state-id.
# A fresh apply without --state-id creates a NEW state and causes duplicate resources.
ENDPOINT="iac.cn-zhangjiakou.aliyuncs.com"
SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
# ---------------------------------------------------------------------------
# Color helpers (degrade gracefully if tput unavailable)
# ---------------------------------------------------------------------------
_green() { command -v tput &>/dev/null && tput setaf 2; }
_red() { command -v tput &>/dev/null && tput setaf 1; }
_yellow() { command -v tput &>/dev/null && tput setaf 3; }
_reset() { command -v tput &>/dev/null && tput sgr0; }
# ---------------------------------------------------------------------------
# Shared helper: resolve file-or-inline input to CODE variable
# ---------------------------------------------------------------------------
_read_input() {
local input="$1"
if [[ -f "$input" ]]; then
cat "$input"
else
printf '%s' "$input"
fi
}
# ---------------------------------------------------------------------------
# cmd: validate
# ---------------------------------------------------------------------------
cmd_validate() {
if [[ $# -lt 1 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
echo "Usage: $0 validate <hcl_file_or_code>"
echo "Exit 0 = Validated, 1 = Errored"
exit 1
fi
local input="$1"
local code
code=$(_read_input "$input")
echo "Validating: $input" >&2
local token response status message
token="$(uuidgen)"
response=$(aliyun iacservice validate-module \
--endpoint "$ENDPOINT" \
--client-token "$token" \
--source Upload \
--code "$code" 2>&1) || { echo "$(_red)Error: validate-module failed$(_reset)" >&2; echo "$response" >&2; exit 1; }
status=$(echo "$response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('status','Unknown'))
except: print('Unknown')
" 2>/dev/null) || status="Unknown"
message=$(echo "$response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('message',''))
except: print('')
" 2>/dev/null) || message=""
echo "" >&2
if [[ "$status" == "Validated" ]]; then
echo "$(_green)Validated$(_reset)" >&2
[[ -n "$message" ]] && echo "$message" >&2
exit 0
else
echo "$(_red)Validation failed: $status$(_reset)" >&2
[[ -n "$message" ]] && echo "$message" >&2
exit 1
fi
}
# ---------------------------------------------------------------------------
# cmd: poll
# ---------------------------------------------------------------------------
cmd_poll() {
if [[ $# -lt 1 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
echo "Usage: $0 poll <state_id> [max_attempts] [interval_seconds]"
echo "Exit 0 = terminal state reached, 1 = timeout or Errored"
exit 1
fi
local state_id="$1"
local max="${2:-60}"
local interval="${3:-10}"
local terminal_states=("Planned" "PlannedAndFinished" "Applied" "Errored" "Canceled" "Discarded")
_is_terminal() {
local s="$1"
for t in "${terminal_states[@]}"; do [[ "$s" == "$t" ]] && return 0; done
return 1
}
local attempt=0 response status
while [[ $attempt -lt $max ]]; do
attempt=$((attempt + 1))
response=$(aliyun iacservice get-execute-state --endpoint "$ENDPOINT" --state-id "$state_id" 2>&1) || true
status=$(echo "$response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('status','Unknown'))
except: print('Unknown')
" 2>/dev/null) || status="Unknown"
if [[ "$status" == "Errored" ]]; then
echo "[$attempt/$max] $(_red)Status: $status$(_reset)" >&2
elif _is_terminal "$status"; then
echo "[$attempt/$max] $(_green)Status: $status$(_reset)" >&2
else
echo "[$attempt/$max] $(_yellow)Status: $status$(_reset)" >&2
fi
if _is_terminal "$status"; then
if [[ "$status" == "Errored" ]]; then
local errmsg
errmsg=$(echo "$response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('errorMessage','Unknown error'))
except: print('Unknown error')
" 2>/dev/null) || errmsg="Unknown error"
echo "$(_red)Error: $errmsg$(_reset)" >&2
exit 1
fi
exit 0
fi
[[ $attempt -lt $max ]] && sleep "$interval"
done
echo "$(_red)Timeout: $max attempts reached$(_reset)" >&2
exit 1
}
# ---------------------------------------------------------------------------
# cmd: plan
# ---------------------------------------------------------------------------
cmd_plan() {
if [[ $# -lt 1 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
echo "Usage: $0 plan <hcl_file_or_code> [existing_state_id]"
echo "Output: STATE_ID=<id> PLAN_OUTPUT_FILE=<path>"
echo "Exit 0 = Planned/PlannedAndFinished, 1 = Errored"
exit 1
fi
local input="$1"
local state_id="${2:-}"
local code token aliyun_cmd response new_state_id
code=$(_read_input "$input")
echo "Planning: $input" >&2
[[ -n "$state_id" ]] && echo "Using existing state: $state_id" >&2
token="$(uuidgen)"
aliyun_cmd="aliyun iacservice execute-terraform-plan --endpoint $ENDPOINT --client-token $token --code \"\$code\""
[[ -n "$state_id" ]] && aliyun_cmd="$aliyun_cmd --state-id $state_id"
response=$(eval "$aliyun_cmd" 2>&1) || { echo "$(_red)Error: execute-terraform-plan failed$(_reset)" >&2; echo "$response" >&2; exit 1; }
new_state_id=$(echo "$response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('stateId',''))
except: print('')
" 2>/dev/null) || new_state_id=""
[[ -z "$new_state_id" ]] && { echo "$(_red)Error: no stateId in response$(_reset)" >&2; echo "$response" >&2; exit 1; }
echo "STATE_ID=$new_state_id"
echo "" >&2; echo "Plan started. stateId: $new_state_id" >&2; echo "Polling..." >&2; echo "" >&2
"$SELF" poll "$new_state_id" || { echo "$(_red)Plan failed$(_reset)" >&2; exit 1; }
local final_response final_status error_message
final_response=$(aliyun iacservice get-execute-state --endpoint "$ENDPOINT" --state-id "$new_state_id" 2>&1) || true
final_status=$(echo "$final_response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('status','Unknown'))
except: print('Unknown')
" 2>/dev/null) || final_status="Unknown"
echo "" >&2
if [[ "$final_status" == "Planned" || "$final_status" == "PlannedAndFinished" ]]; then
echo "$(_green)Plan completed: $final_status$(_reset)" >&2
local plan_file="/tmp/tf_plan_${new_state_id}.txt"
local plan_summary
plan_summary=$(echo "$final_response" | python3 -c "
import sys,json,re
plan_file=sys.argv[1]
try:
data=json.loads(sys.stdin.read(),strict=False)
lf=data.get('logFile',{})
log=lf.get('tf-plan.run.log','') if isinstance(lf,dict) else (lf if isinstance(lf,str) else '')
if not log: print(' No plan details available'); sys.exit(0)
clean=re.sub(r'\x1b\[[0-9;]*[a-zA-Z]','',log)
open(plan_file,'w').write(clean)
lines=clean.split('\n')
summary=[l for l in lines if ('# ' in l and ('will be' in l or 'must be' in l)) or l.strip().startswith('Plan:') or 'No changes' in l]
for s in (summary or [' (see full output for details)']): print(' '+s.strip())
except Exception as e: print(f' Could not parse: {e}')
" "$plan_file" 2>/dev/null) || plan_summary=" Could not parse plan details"
echo "" >&2
echo "=== Plan Summary ===" >&2
echo "$plan_summary" >&2
[[ -f "$plan_file" ]] && { echo "" >&2; echo "Full output: cat $plan_file" >&2; }
echo "====================" >&2
echo "PLAN_OUTPUT_FILE=$plan_file"
exit 0
elif [[ "$final_status" == "Errored" ]]; then
error_message=$(echo "$final_response" | python3 -c "
import sys,json
try: m=json.load(sys.stdin).get('errorMessage',''); m and print(m)
except: pass
" 2>/dev/null) || error_message=""
echo "$(_red)Plan failed: $final_status$(_reset)" >&2
[[ -n "$error_message" ]] && echo "$(_red)Error: $error_message$(_reset)" >&2
exit 1
else
echo "$(_yellow)Plan status: $final_status$(_reset)" >&2
exit 0
fi
}
# ---------------------------------------------------------------------------
# cmd: apply
# ---------------------------------------------------------------------------
cmd_apply() {
if [[ $# -lt 1 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
echo "Usage:"
echo " $0 apply <hcl_file_or_code> # first apply of a brand-new deployment"
echo " $0 apply <hcl_file_or_code> --state-id <id> # any subsequent change to an existing deployment"
echo " $0 apply --state-id <id> # apply a previously planned state"
echo ""
echo " STATE_ID REUSE RULE:"
echo " Once a STATE_ID exists, ALL subsequent operations on the same deployment MUST"
echo " pass --state-id, including: retry after failure, add resources, modify config."
echo " Starting a fresh apply (without --state-id) creates a NEW state and causes"
echo " duplicate resource creation."
echo ""
echo "Output: STATE_ID=<id>"
echo "Exit 0 = Applied, 1 = Errored"
exit 1
fi
local input="" state_id="" code=""
while [[ $# -gt 0 ]]; do
case "$1" in
--state-id) state_id="${2:-}"; shift 2 ;;
--help|-h) cmd_apply --help ;;
*) input="$1"; shift ;;
esac
done
[[ -z "$input" && -z "$state_id" ]] && { echo "$(_red)Error: provide HCL code/file or --state-id$(_reset)" >&2; exit 1; }
[[ -n "$input" ]] && { code=$(_read_input "$input"); echo "Applying: $input" >&2; }
[[ -n "$state_id" ]] && echo "Using existing state: $state_id" >&2
local token aliyun_cmd response new_state_id
local max_retries=6 retry_delay=10 retry=0
token="$(uuidgen)"
_build_cmd() {
local cmd="aliyun iacservice execute-terraform-apply --endpoint $ENDPOINT --client-token $token"
[[ -n "$code" ]] && cmd="$cmd --code \"\$code\""
[[ -n "$state_id" ]] && cmd="$cmd --state-id $state_id"
echo "$cmd"
}
aliyun_cmd=$(_build_cmd)
while true; do
response=$(eval "$aliyun_cmd" 2>&1) && break
if echo "$response" | grep -q "InvalidOperation.TaskStatus"; then
retry=$((retry + 1))
if [[ $retry -ge $max_retries ]]; then
echo "$(_red)Error: state lock not released after $max_retries retries$(_reset)" >&2
echo "$response" >&2; exit 1
fi
echo "$(_yellow)[Retry $retry/$max_retries] State lock not released, waiting ${retry_delay}s...$(_reset)" >&2
sleep "$retry_delay"
token="$(uuidgen)"; aliyun_cmd=$(_build_cmd)
else
echo "$(_red)Error: execute-terraform-apply failed$(_reset)" >&2; echo "$response" >&2; exit 1
fi
done
new_state_id=$(echo "$response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('stateId',''))
except: print('')
" 2>/dev/null) || new_state_id=""
[[ -z "$new_state_id" ]] && { echo "$(_red)Error: no stateId in response$(_reset)" >&2; echo "$response" >&2; exit 1; }
echo "STATE_ID=$new_state_id"
echo "" >&2; echo "Apply started. stateId: $new_state_id" >&2; echo "Polling..." >&2; echo "" >&2
"$SELF" poll "$new_state_id" || { echo "$(_red)Apply failed$(_reset)" >&2; exit 1; }
local final_response final_status error_message
final_response=$(aliyun iacservice get-execute-state --endpoint "$ENDPOINT" --state-id "$new_state_id" 2>&1) || true
final_status=$(echo "$final_response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('status','Unknown'))
except: print('Unknown')
" 2>/dev/null) || final_status="Unknown"
echo "" >&2
if [[ "$final_status" == "Applied" ]]; then
echo "$(_green)Apply completed: $final_status$(_reset)" >&2
echo "" >&2; echo "Resources:" >&2
echo "$final_response" | python3 -c "
import sys,json
try:
data=json.load(sys.stdin)
s=data.get('state','')
state=json.loads(s) if isinstance(s,str) else s
resources=state.get('resources',[]) if state else []
if resources:
for r in resources:
for i in r.get('instances',[]):
print(f' {r[\"type\"]}.{r[\"name\"]}: {i.get(\"attributes\",{}).get(\"id\",\"N/A\")}')
else: print(' No resources found')
except Exception as e: print(f' Could not parse resources: {e}')
" 2>/dev/null || echo " Could not parse resources" >&2
exit 0
elif [[ "$final_status" == "Errored" ]]; then
error_message=$(echo "$final_response" | python3 -c "
import sys,json
try: m=json.load(sys.stdin).get('errorMessage',''); m and print(m)
except: pass
" 2>/dev/null) || error_message=""
echo "$(_red)Apply failed: $final_status$(_reset)" >&2
[[ -n "$error_message" ]] && echo "$(_red)Error: $error_message$(_reset)" >&2
exit 1
else
echo "$(_yellow)Apply status: $final_status$(_reset)" >&2; exit 0
fi
}
# ---------------------------------------------------------------------------
# cmd: destroy
# ---------------------------------------------------------------------------
cmd_destroy() {
if [[ $# -lt 1 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
echo "Usage: $0 destroy <state_id> [--force]"
echo "Exit 0 = Destroyed, 1 = Failed or not confirmed"
exit 1
fi
local state_id="" force=false
while [[ $# -gt 0 ]]; do
case "$1" in
--force) force=true; shift ;;
--help|-h) cmd_destroy --help ;;
*) state_id="$1"; shift ;;
esac
done
[[ -z "$state_id" ]] && { echo "$(_red)Error: state_id required$(_reset)" >&2; exit 1; }
# Pre-check: get current state and list resources
echo "Pre-check: querying state $state_id ..." >&2
local pre_response pre_status
pre_response=$(aliyun iacservice get-execute-state --endpoint "$ENDPOINT" --state-id "$state_id" 2>&1) || {
echo "$(_red)Error: cannot query state $state_id$(_reset)" >&2
echo "$pre_response" >&2; exit 1
}
pre_status=$(echo "$pre_response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('status','Unknown'))
except: print('Unknown')
" 2>/dev/null) || pre_status="Unknown"
echo "" >&2
echo "$(_yellow)⚠️ The following resources will be DESTROYED:$(_reset)" >&2
echo "$pre_response" | python3 -c "
import sys,json
try:
data=json.load(sys.stdin)
s=data.get('state','')
state=json.loads(s) if isinstance(s,str) else s
resources=state.get('resources',[]) if state else []
if resources:
for r in resources:
for i in r.get('instances',[]):
print(f' {r[\"type\"]}.{r[\"name\"]}: {i.get(\"attributes\",{}).get(\"id\",\"N/A\")}')
else: print(' (no resources found in state)')
except Exception as e: print(f' Could not parse resources: {e}')
" 2>/dev/null || echo " Could not parse resources" >&2
echo "" >&2
if [[ "$force" != true ]]; then
echo "$(_red)Destruction not confirmed. Add --force to proceed.$(_reset)" >&2
exit 1
fi
echo "Destroying resources for state: $state_id" >&2
local token response destroy_state_id
token="$(uuidgen)"
response=$(aliyun iacservice execute-terraform-destroy \
--endpoint "$ENDPOINT" \
--client-token "$token" \
--state-id "$state_id" 2>&1) || { echo "$(_red)Error: execute-terraform-destroy failed$(_reset)" >&2; echo "$response" >&2; exit 1; }
destroy_state_id=$(echo "$response" | python3 -c "
import sys,json
try:
sid=json.load(sys.stdin).get('stateId','')
print(sid if sid else '$state_id')
except: print('$state_id')
" 2>/dev/null) || destroy_state_id="$state_id"
echo "Polling..." >&2; echo "" >&2
"$SELF" poll "$destroy_state_id" || { echo "$(_red)Destroy failed$(_reset)" >&2; exit 1; }
local final_response final_status
final_response=$(aliyun iacservice get-execute-state --endpoint "$ENDPOINT" --state-id "$destroy_state_id" 2>&1) || true
final_status=$(echo "$final_response" | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('status','Unknown'))
except: print('Unknown')
" 2>/dev/null) || final_status="Unknown"
echo "" >&2
if [[ "$final_status" == "Applied" || "$final_status" == "Canceled" || "$final_status" == "Discarded" ]]; then
echo "$(_green)Destroy completed: $final_status$(_reset)" >&2; exit 0
elif [[ "$final_status" == "Errored" ]]; then
local errmsg
errmsg=$(echo "$final_response" | python3 -c "
import sys,json
try: m=json.load(sys.stdin).get('errorMessage',''); m and print(m)
except: pass
" 2>/dev/null) || errmsg=""
echo "$(_red)Destroy failed: $final_status$(_reset)" >&2
[[ -n "$errmsg" ]] && echo "$(_red)Error: $errmsg$(_reset)" >&2
exit 1
else
echo "$(_yellow)Destroy status: $final_status$(_reset)" >&2; exit 0
fi
}
# ---------------------------------------------------------------------------
# Dispatch
# ---------------------------------------------------------------------------
usage() {
echo "Usage: $0 <command> [args]"
echo ""
echo "Commands:"
echo " validate <hcl_file_or_code> Validate HCL syntax"
echo " plan <hcl_file_or_code> [state_id] Preview changes"
echo " apply <hcl_file_or_code> [--state-id id] Create/update infrastructure"
echo " apply --state-id <id> Apply planned state"
echo " destroy <state_id> [--force] Destroy resources"
echo " poll <state_id> [max] [interval] Poll execution status"
echo ""
echo "Run '$0 <command> --help' for per-command usage."
exit 1
}
COMMAND="${1:-}"
shift || true
case "$COMMAND" in
validate) cmd_validate "$@" ;;
plan) cmd_plan "$@" ;;
apply) cmd_apply "$@" ;;
destroy) cmd_destroy "$@" ;;
poll) cmd_poll "$@" ;;
*) usage ;;
esac
#!/bin/bash
# Alibaba Cloud CLI Environment Verification Script
# Usage: bash scripts/verify_env.sh
if [ -z "$BASH_VERSION" ]; then
echo "Please run this script with bash: bash $0"
exit 1
fi
TOTAL=0
PASSED=0
MISSING_ITEMS=()
check() {
local name="$1"
local result="$2"
local fix_hint="$3"
TOTAL=$((TOTAL + 1))
if [ "$result" = "0" ]; then
PASSED=$((PASSED + 1))
echo " ✅ PASS $name"
else
echo " ❌ FAIL $name"
if [ -n "$fix_hint" ]; then
MISSING_ITEMS+=("$fix_hint")
fi
fi
}
echo "========================================="
echo " Alibaba Cloud CLI Environment Check"
echo "========================================="
echo ""
# 1. Check aliyun CLI installed
echo "--- 1. Aliyun CLI ---"
if command -v aliyun &>/dev/null; then
CLI_VERSION=$(aliyun version 2>&1 | head -1)
echo " Version: $CLI_VERSION"
# Check version >= 3.3.0
MAJOR=$(echo "$CLI_VERSION" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 | cut -d. -f1)
MINOR=$(echo "$CLI_VERSION" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 | cut -d. -f2)
PATCH=$(echo "$CLI_VERSION" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 | cut -d. -f3)
if [ -n "$MAJOR" ] && [ "$MAJOR" -ge 3 ] && [ "$MINOR" -ge 3 ]; then
check "Aliyun CLI >= 3.3.0" "0" ""
elif [ -n "$MAJOR" ] && [ "$MAJOR" -gt 3 ]; then
check "Aliyun CLI >= 3.3.0" "0" ""
else
check "Aliyun CLI >= 3.3.0" "1" "[CLI] Upgrade aliyun CLI to 3.3.0+: brew upgrade aliyun-cli (macOS) or download from https://aliyuncli.alicdn.com/"
fi
else
check "Aliyun CLI installed" "1" "[CLI] Install aliyun CLI: brew install aliyun-cli (macOS) or see https://help.aliyun.com/zh/cli/"
fi
echo ""
# 2. Check CLI credentials (via STS GetCallerIdentity)
echo "--- 2. CLI Credentials ---"
if command -v aliyun &>/dev/null; then
STS_OUTPUT=$(aliyun sts GetCallerIdentity 2>&1)
if echo "$STS_OUTPUT" | grep -q '"AccountId"'; then
ACCOUNT_ID=$(echo "$STS_OUTPUT" | python3 -c "import sys,json;print(json.load(sys.stdin)['AccountId'])" 2>/dev/null)
ARN=$(echo "$STS_OUTPUT" | python3 -c "import sys,json;print(json.load(sys.stdin)['Arn'])" 2>/dev/null)
MASKED_ACCOUNT="${ACCOUNT_ID:0:4}****${ACCOUNT_ID: -4}"
MASKED_ARN=$(echo "$ARN" | sed "s/$ACCOUNT_ID/${MASKED_ACCOUNT}/g")
echo " Account: $MASKED_ACCOUNT"
echo " Identity: $MASKED_ARN"
check "CLI credentials valid" "0" ""
else
echo " Error: $STS_OUTPUT"
check "CLI credentials valid" "1" "[Config] Run: aliyun configure set --mode AK --access-key-id <your-ak> --access-key-secret <your-sk> --region cn-hangzhou"
fi
else
check "CLI credentials" "1" "[CLI] Install aliyun CLI first"
fi
echo ""
# 3. Check auto-plugin-install
echo "--- 3. Auto Plugin Install ---"
if command -v aliyun &>/dev/null; then
CONFIG_JSON="$HOME/.aliyun/config.json"
if [ -f "$CONFIG_JSON" ]; then
AUTO_INSTALL=$(python3 -c "
import json
with open('$CONFIG_JSON') as f:
cfg = json.load(f)
# Check current profile
profiles = cfg.get('profiles', [])
current = cfg.get('current', 'default')
for p in profiles:
if p.get('name') == current:
print(str(p.get('auto_plugin_install', False)).lower())
break
else:
print('false')
" 2>/dev/null || echo "false")
if [ "$AUTO_INSTALL" = "true" ]; then
check "Auto plugin install enabled" "0" ""
else
check "Auto plugin install enabled" "1" "[Config] Run: aliyun configure set --auto-plugin-install true"
fi
else
check "Auto plugin install enabled" "1" "[Config] Run: aliyun configure set --auto-plugin-install true"
fi
else
check "Auto plugin install" "1" "[CLI] Install aliyun CLI first"
fi
echo ""
# 4. Check Python3 (needed for helper scripts)
echo "--- 4. Python3 (for helper scripts) ---"
if command -v python3 &>/dev/null; then
PY_VERSION=$(python3 --version 2>&1 || echo "unknown")
echo " Version: $PY_VERSION"
check "Python3 available" "0" ""
else
check "Python3 available" "1" "[Python3] Install Python 3.8+: https://www.python.org/downloads/"
fi
echo ""
# 5. Check Python SDK (needed for helper scripts only)
echo "--- 5. Python SDK (for helper scripts) ---"
if command -v python3 &>/dev/null; then
SDK_PACKAGES=(
"alibabacloud_tea_openapi"
"alibabacloud_credentials"
"alibabacloud_tea_util"
"alibabacloud_openapi_util"
)
MISSING_SDK=()
for pkg in "${SDK_PACKAGES[@]}"; do
if ! python3 -c "import $pkg" &>/dev/null; then
MISSING_SDK+=("$pkg")
fi
done
if [ ${#MISSING_SDK[@]} -eq 0 ]; then
check "SDK packages for helper scripts" "0" ""
else
check "SDK packages for helper scripts (missing: ${MISSING_SDK[*]})" "1" "[SDK] Run: pip3 install alibabacloud-tea-openapi alibabacloud-credentials alibabacloud-tea-util alibabacloud-openapi-util"
fi
else
check "SDK packages check" "1" "[Python3] Install Python 3.8+ first"
fi
echo ""
echo "========================================="
echo " Result: $PASSED/$TOTAL passed"
echo "========================================="
if [ "$PASSED" -eq "$TOTAL" ]; then
echo " ✅ All CLI environment checks passed!"
exit 0
else
echo ""
IFS=$'\n' UNIQUE_MISSING=($(sort -u <<<"${MISSING_ITEMS[*]}")); unset IFS
echo " ❌ $((TOTAL - PASSED)) item(s) failed. How to fix:"
echo ""
for item in "${UNIQUE_MISSING[@]}"; do
echo " $item"
done
echo ""
exit 1
fi