# Huawei Iac

> Use whenever the user wants to DEPLOY, host, or purchase anything on Huawei Cloud that creates billable resources: application deployments (部署应用到华为云, deploy my app, 上线, 搭建), architecture proposals, cost estimation, multi-resource provisioning (VPC, subnet, security group, ECS, EIP, RDS, OBS, CDN, DNS, FunctionGraph, CCE, GaussDB and more), session-scoped state tracking, and reverse-order destroy. Trigger words: 部署, 部署到华为云, 上线, 购买, 搭建, 开通, 成本估算, 多少钱, 销毁, deploy, deploy to Huawei Cloud, provision, purchase, architecture, hosting. Reusing an existing VPC does NOT make it single-resource - any purchase (ECS, EIP, disk, keypair, rules) must pass the cost+balance gate here. NOT for: sandbox preview (huawei-sandbox - free, no purchase), read-only or lifecycle operations on EXISTING resources (query/reboot/resize/delete - use the service skill directly).

- Skill: `huaweicloud/huawei-iac` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add huaweicloud/huawei-iac`
- Raw SKILL.md: https://api.skillmd.com/api/skills/huaweicloud/huawei-iac/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: huaweicloud (https://skillmd.com/u/huaweicloud)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/huaweicloud/huawei-iac

---


# Huawei Cloud IaC Orchestration

**STOP - Do not answer from general knowledge.** Follow the 8-stage workflow below in strict order.

Always run `hcloud <Service> <Operation> --help` before constructing commands to discover exact parameter names and requirements.

## Scope and Routing Guard

- This skill orchestrates the **purchase lifecycle of ALL supported resources**: proposal → pricing → provisioning → destroy, across every service in the plugin catalog.
- **Web app deployment keeps sandbox as the first choice** (see `huaweicloud-core` Deployment Target Options). Route here only when the user wants billed, long-term, or multi-resource cloud infrastructure, or explicitly asks for an architecture + cost proposal.
- Single-resource tasks go directly to the service skill. This skill adds value for **multi-resource orchestration, mandatory cost gating, and ordered destroy**.
- **A user-specified hosting target (e.g. "部署到 ECS") does NOT exempt the flow**: stages 1-5 (code inspection, cost estimate, balance check, risk warnings) still run in full - the user's target choice only narrows stage 2/3 options, it never skips the gates.

## Workflow (strict order)

**Proactive by design**: any deployment intent ("部署一个博客", "搭一套环境", "买个服务器") automatically triggers stages 1-5 BEFORE anything is created. The user NEVER needs to ask for an architecture proposal, cost estimate, or risk warnings - they are built into the flow. Only stages 6-8 (create / verify / manage) wait for explicit user confirmation at the approval gates.

| Stage                      | What happens                                                                                                                                                                                                                      | Hard rule                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. Scale assessment        | **FIRST inspect the project code** (clone remote repos to a temp dir, or read the local path): tech stack, data services (Redis/MySQL/SQLite...), build artifacts, existing Dockerfile/k8s manifests → then classify or ask scale | **NEVER present deployment options (sandbox/ECS/OBS...) before the codebase has been inspected** - options without code analysis are guesses. If scale is not stated or clearly inferable, ASK - present the 3 tiers as options with what each includes and its monthly cost band (see `references/architectures.md`), and let the user choose. Never assume a tier. The scale question and the hosting-target question are SEPARATE questions on separate axes. FunctionGraph filesystem is ephemeral - never recommend SQLite/local files for persistent data                                                                                                                                                                                                                                                                                                                                                                                             |
| 2. Frontend hosting choice | Present BOTH options: (a) OBS+CDN+DNS custom domain, (b) ECS+EIP                                                                                                                                                                  | For SPA/static frontends (Vue/React dist), **OBS hosting must always appear as an option** with cost comparison against same-host Nginx - do not silently merge the frontend into a compute node. For option (a) three prerequisites: domain ownership verification (CDN requires a DNS record or file upload first - `CDN.00010185` otherwise), ICP filing check, DNS hosting check; domain registration link: https://www.huaweicloud.com/product/domain.html                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| 3. Architecture proposal   | ASCII topology tree with dependencies                                                                                                                                                                                             | User confirms before continuing. **Architecture decision points must be surfaced as explicit choices, never silently made**: (a) app depends on Redis/MySQL/Kafka etc. → managed service (DCS/RDS/DMS, billed) vs same-host install (cheap, ops burden) - state the trade-off and ask; (b) repo ships a Dockerfile / SWR image / k8s manifests → offer container path (Docker on ECS or CCE) alongside source-build path; (c) frontend hosting layer (Nginx same-host vs OBS+CDN). Silent defaults here are a correctness failure                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 4. Parameter discovery     | `ListFlavors` / `ListImages` / `huaweicloud_list_regions`                                                                                                                                                                         | Never hardcode flavor/image names                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 5. Cost + balance gate     | Price every resource via BSS `ListOnDemandResourceRatings`, then query balance                                                                                                                                                    | Balance = 0 → the FIRST message must state: "您的余额为 0，按时长计费的资源（ECS/EIP/RDS 等）下单将失败（Ecs.7000），请先充值或使用免费额度"。充值入口：https://account.huaweicloud.com/usercenter/?region=cn-north-4#/userindex/balanceRecharge 。Remedy priority: (1) FIRST claim the one-time incentive voucher (huaweicloud_voucher_status → huaweicloud_voucher_claim) to offset usage fees; (2) then instruct the user to top up balance (via the link above) if pay-per-use orders are needed, otherwise orders fail with `Ecs.7000`; (3) free-tier resources (FunctionGraph, small OBS) proceed without any balance. Balance > 0 → report how long it can sustain (balance ÷ monthly estimate). **权限降级（实测）**：IAM 用户无 `billing:balance:view` 时余额查询报 `CBC.0151` → 不阻塞流程，明确告知"余额无法程序化查询，请自行核对；若下单报 Ecs.7000 即余额不足"，领券后继续。定价编码逐服务查证，见 `references/resource-catalog.md` § Pricing |
| 6. Provision               | deployment_id, session state, batch approval, ordered creation                                                                                                                                                                    | See "Provisioning Rules" below                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| 7. Verify                  | `curl -I` the site / API; expect 200                                                                                                                                                                                              | DNS CNAME may take minutes to propagate - not an error                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 8. Manage                  | Session-scoped status query and destroy                                                                                                                                                                                           | See "Destroy Rules" below                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

## Provisioning Rules (Stage 6)

1. Generate `deployment_id` (`d-xxx`), initialize the session state file (path and schema: `references/state-file.md`).
2. **Batch approval: show the RESOURCE LIST (name / type / purpose), never the raw commands.** Present the numbered manifest BEFORE any `huaweicloud_plan_cli_command` call and get ONE explicit list-level approval. After the user approves the manifest, execute each resource via `huaweicloud_plan_cli_command` → `huaweicloud_run_approved_command` without re-asking list-level consent (per-command approval tokens are still required by the tool gate). Never execute anything outside the approved list.
3. Create in dependency-topological order (network → compute/db → bindings). After each success, extract the resource ID and write it to state immediately.
4. Any failure: stop immediately, mark state `partial`, report the error, offer destroy of already-created resources. No automatic rollback.

## Destroy Rules (Stage 8, current session only)

Preconditions - all required:

1. Session state file exists and contains the deployment_id (state dies with the session; a fresh session cannot destroy past deployments - direct the user to the console instead).
2. Status is `deployed` or `partial` (`destroyed` is terminal).
3. The user explicitly names the target deployment. Ambiguous "delete it" → list deployments and ask. Never guess.
4. Every delete command still goes through plan → approve → run.

Execution: show the to-be-deleted list for final confirmation → delete in **reverse creation order** → a "resource not found" error counts as already deleted, continue → mark `destroyed`. OBS: recursive sweeps (`OBS rm obs://<bucket>/ -r -f`) are DENIED by the safety rule `hwc-destructive-delete-force` even after manifest approval - do not plan them. Instead list objects (`hcloud OBS ls obs://<bucket>/ -s`) and delete per-object (watch for folder-marker objects like `assets/` that outlive the files), then delete the bucket (a non-empty bucket fails with 409 `BucketNotEmpty`). CDN: disable then delete. DNS: delete the record set (only if hosted in Huawei Cloud DNS).

## Critical Warnings

| Trap                                                 | Why / Rule                                                                                                                                                                                                                                                                                                                                                |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Stale `securityToken` poisons every hcloud call      | Symptom: every API returns `APIGW.0301 Incorrect IAM authentication information` while OBS/obsutil still works. `configure set` refuses empty values and auth-sync never clears the field. Fix: `hcloud configure delete --cli-profile=default`, then re-run auth init with AK/SK only (no token)                                                         |
| OBS writes bypass the REST write-prefix policy       | `mb` / `cp` / `rm` / `chattri` are obsutil-style commands. ALWAYS route them through `huaweicloud_plan_cli_command` → approval → `huaweicloud_run_approved_command`. Never treat them as read-only                                                                                                                                                        |
| `OBS mb` flag rules differ from cp/rm                | `mb` does NOT accept `-f` (flag parse error) and REQUIRES explicit `-location=<region>` even with a regional endpoint (else `IllegalLocationConstraintException`)                                                                                                                                                                                         |
| Duplicate `OBS mb` is idempotent success             | Same-account same-name bucket creation returns success, not an error - never treat a second create as failure. OBS deletes are also idempotent (deleting a nonexistent object succeeds)                                                                                                                                                                   |
| Bucket ACL does not cascade to objects               | Every uploaded object needs `-acl=public-read` at upload time (`-f` IS valid on cp/rm)                                                                                                                                                                                                                                                                    |
| OBS static website bucket name must equal the domain | e.g. bucket `www.example.com` for domain `www.example.com`                                                                                                                                                                                                                                                                                                |
| VPC v3 API differs from older docs                   | v3 `CreateSecurityGroup` has NO `vpc_id` (account-scoped); `CreateSecurityGroupRule` uses `multiport=80` not `port_range_min/max`; `DeleteSubnet` requires `vpc_id` too. Always `--help` first                                                                                                                                                            |
| Public exposure is auto-blocked                      | Risk rules deny `0.0.0.0/0` port rules at plan time. For test/dev use a narrower `remote_ip_prefix` (e.g. the VPC CIDR) or get user consent for a documented exception                                                                                                                                                                                    |
| ECS CreateServers hidden required params             | Besides flavor/image/nics/az it also needs `--server.vpcid` and `--server.root_volume.volumetype` - order submission fails without them                                                                                                                                                                                                                   |
| FunctionGraph runtime/code enums are strict          | runtime must be exact (`Node.js18.15`, `Python3.9`, `Go1.x`, ...); inline code is the PAIR `--package=default --code_type=inline` (`--package=inline` → `FSS.1006`); TIMER triggers use `--event_data.schedule_type=Rate --event_data.schedule=1m` (`@every` style → `FSS.1109`); DeleteFunction takes `--function_urn` WITHOUT `:latest`                 |
| Keypairs: `NovaCreateKeypair`, not CreateKeypair     | `ECS CreateKeypair` does NOT exist - use `hcloud ECS NovaCreateKeypair`; delete takes `--keypair_name` (not `--keypair.name`). The API-generated `private_key` is MASKED in tool output - for SSH access create the keypair in the console or import the user's own public key, then bind with `--server.key_name=<n>`                                    |
| Long inline args break MCP JSON                      | Values >~2KB inline (e.g. `--server.user_data=<base64 cloud-init>`) fail JSON parsing silently. Write a local JSON file and pass `--cli-jsonInput=<file>` (see `references/resource-catalog.md` header note)                                                                                                                                              |
| EIP quota fails at RUN stage, not at plan            | `EIP.7905 Quota exceeded` appears only after plan+approval - pre-check quota during stage 5 (and count precisely: `ListPublicips --limit=50` truncates, a "50/50" read on a 59-EIP account is wrong). Released quotas may lag minutes before `EIP.7905` clears                                                                                            |
| Zero balance blocks order submission                 | ECS creation fails with `Ecs.7000 Insufficient account balance` when cash + voucher accounts are 0. This is the stage-5 gate materialized: stop, mark `partial`, tell the user pay-by-duration resources need a balance top-up. Free-tier resources (FunctionGraph, small OBS) DO work at 0 balance - the gate applies to order-submission resources only |
| CDN mainland acceleration requires ICP filing        | Unregistered domains cannot go live on CDN - check before stage 3. CDN create ALSO requires domain ownership verification first (`CDN.00010185 Verify domain ownership failed` - user must add a DNS record or upload a verification file)                                                                                                                |
| CDN is a global service in KooCLI                    | CDN operations only accept `--cli-region=cn-north-1` or `ap-southeast-1` - never the resource region                                                                                                                                                                                                                                                      |
| OBS static website hosting has NO CLI path           | `chattri` only sets ACL/storage-class; obsutil has no website command. Options: console setup, or CDN OBS-origin with `--domain.sources.1.enable_obs_web_hosting=1`. Without website hosting, verify via direct object URLs (still public HTTP 200)                                                                                                       |
| DNS hosting location                                 | `hcloud DNS ListPublicZones` decides: hosted in Huawei Cloud → auto-create CNAME record set; hosted elsewhere → output the CNAME value for manual setup at the user's DNS provider                                                                                                                                                                        |
| EIP bills when idle; stopped ECS still bills         | Include in cost estimate; destroy unattached EIPs                                                                                                                                                                                                                                                                                                         |
| ECS delete defaults leak resources                   | `--delete_publicip` and `--delete_volume` are false by default - set `true` when tearing down                                                                                                                                                                                                                                                             |
| EIP binding type is non-obvious                      | `--publicip.associate_instance_type=PORT` (not INSTANCE)                                                                                                                                                                                                                                                                                                  |
| State is session-only                                | Temp-dir file, dies with the session. Never promise cross-session deploy management                                                                                                                                                                                                                                                                       |
| State file must be UTF-8 WITHOUT BOM                 | PowerShell `Set-Content -Encoding utf8` adds a BOM that breaks JSON parsers - write state with Node or another BOM-less writer                                                                                                                                                                                                                            |
| HTTPS needs a certificate                            | CDN serves plain HTTP by default; SSL cert (upload or SCM) required for HTTPS                                                                                                                                                                                                                                                                             |

## MCP Tools

- `huaweicloud_plan_cli_command` → classify and plan each write command
- `huaweicloud_run_approved_command` → execute after explicit approval (approvedCommand must match the planned command exactly - use the `command` field verbatim, never retype it)
- `huaweicloud_run_readonly_command` → discovery (flavors, images, zones, prices)
- `huaweicloud_list_regions` / `huaweicloud_get_regional_availability` → region intent
- `huaweicloud_hook_check_deploy_plan` → risk-check the plan before approval
- Balance and pricing: `huawei-billing` skill. Balance operation (BSS is pinned to cn-north-1 in KooCLI): `hcloud BSS ShowCustomerAccountBalances --cli-region=cn-north-1` (domain-id auto-resolves from the AK/SK). If an IAM business param genuinely needs the account-id, run `hcloud STS GetCallerIdentity --cli-region=<region>`

## Cross-Skill References

- Per-resource commands: `huawei-vpc` (VPC / subnet / security group / EIP), `huawei-ecs`, `huawei-rds`, `huawei-gaussdb`, `huawei-dds-dcs`, `huawei-cce`, `huawei-obs`, `huawei-functiongraph`, `huawei-apig`, `huawei-smn-dms`, `huawei-cbr`, `huawei-cloud-eye`, `huawei-cts`, `huawei-dew`, `huawei-modelarts`, `huawei-waf-aad`, `huawei-iam`
- **CDN and DNS have no dedicated skill** - discover operations with `hcloud CDN <Operation> --help` and `hcloud DNS <Operation> --help`
- Full purchase catalog: `references/resource-catalog.md`
- Architecture templates by scale: `references/architectures.md`
- State file spec: `references/state-file.md`

