Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Normalize all text files to LF, including on Windows checkouts.
#
# gofmt requires LF; on windows-latest runners actions/checkout inherits
# core.autocrlf=true from the runner image, which rewrites every file to CRLF
# at checkout and makes the CI formatting gate flag the whole repo. Checkout
# attributes take precedence over core.autocrlf, so this pins LF everywhere.
# Every tracked blob is already LF (verified 2026-07-06), so no renormalization
# is needed.
* text=auto eol=lf
6 changes: 5 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,12 @@ jobs:
shell: bash
run: |
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
# .gitattributes pins eol=lf at checkout; this is the fallback.
# checkout-index --force rewrites every file from the index,
# unlike 'git checkout HEAD -- .', which skips paths the stat
# cache considers clean and silently leaves CRLF in place.
git config core.autocrlf false
git checkout HEAD -- .
git checkout-index --force --all
fi

UNFORMATTED=$(gofmt -s -l .)
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ All notable changes to zcp will be documented in this file.
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), using
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v0.0.22] - 2026-07-06

### Fixed

- **DNS record display was blank and `dns record-delete` could not work against the live API.** The live PowerDNS-backed API returns record **sets** (RRsets): no record IDs at all, and values under a `contents` array rather than a `content` string. The SDK's `Record` decoded neither, so `zcp dns show` and `record-create` printed empty ID and CONTENT columns, and `record-delete --record-id` demanded a numeric ID the API never exposes. Record deletion was impossible. Fixed end to end: `Record` now decodes both shapes (joined values in `Content` for display, individual values in a new `Contents` field); the record tables drop the dead ID column and show real content; and `zcp dns record-delete` now addresses records the way the API does: by `--name` and `--type` (`zcp dns record-delete --domain <slug> --name www --type A`). Names may be relative (`www`) or fully qualified; the CLI resolves the stored FQDN via the new `dns.CanonicalRecordFQDN` helper (`@` selects the zone apex). The legacy `--record-id` path remains for deployments whose DNS backend exposes IDs; the SDK's ID-based `DeleteRecord` is deprecated in favor of the new `DeleteRecordByName`. Verified live: create record → contents visible in `dns show` → delete by name/type → gone.
- **`dns record-create --name` help now states the name is relative.** The backend appends the zone to whatever you pass, so supplying an FQDN silently created `www.example.com.example.com.` (found live). The help text and docs now say to pass the label only (e.g. `www`).
- **`egress create` no longer misreports eventual consistency as failure, and is honest when the backend drops the rule.** The create endpoint returns no body, so the SDK resolves the new rule from the list; it now retries that lookup (3 attempts over ~4s) before giving up. When the rule never appears at all (the API returns 200 but silently creates nothing on some networks, reproduced live on an isolated network), the error now says the backend may have dropped the rule instead of implying a transient issue. The silent drop itself is a platform bug and needs a backend fix.
- **`docs/commands.md` corrected against the real command tree. Every example is now machine-validated.** Six sections documented commands that do not exist or missed required flags: `monitoring` (documented `list/get/create/delete`; the real surface is read-only metrics: `global`, `charts`, `cpu`/`memory`/`disk`/`disk-io`/`network <vm-slug>`); VPN (documented a nonexistent `zcp vpn create --vpc`; now shows the real trees: `vpc vpn-gateway *` and `vpn customer-gateway *` for site-to-site, `ip vpn enable/list/disable` plus `vpn user *` for remote access); `support` (documented `list/get/create/close`; real tree is `support ticket list/show/create/reply/replies/summary/delete` and `support faq list`); `dashboard` (documented a nonexistent `status`; `cancel-service` takes `--slug`); Kubernetes (added the missing `scale`, `get-config`, `upgrade-version`, and `delete`; deleting no longer routes through `billing cancel-service`); `ip allocate` (was missing the required `--plan` and `--billing-cycle`). Also fixed a phantom `--network` flag on `ip static-nat enable`, added the previously undocumented `loadbalancer attach-vm`/`detach-vm`/`delete-rule`, and noted the egress silent-drop issue. All 264 examples in the reference are now validated automatically against the built CLI (command paths and flags).

### Added

- **SDK (`pkg/api/dns`):** `DeleteRecordByName(domain, fqdn, type)`, `CanonicalRecordFQDN(name, zone)`, and `Record.Contents []string`. These are the primitives the Terraform provider's `zcp_dns_record` resource also relies on.

## [v0.0.21] - 2026-07-02

### Fixed
Expand Down
172 changes: 75 additions & 97 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,130 +1,108 @@
# zcp v0.0.21 Release Notes
# zcp v0.0.22 Release Notes

## Profile defaults now work everywhere, including create commands
## DNS records now display and delete correctly

`zcp profile add default --region yul-1 --project default-9` stores your default scope
so you never repeat `--region`/`--project`. Until now that promise only held for
list/get commands: create and mutate commands (e.g. `network create`, `instance create`)
resolved their own scope from flags and environment variables only, so a fully
configured user still hit `--region is required`. That gap is closed: configure once,
and scoped commands pick the defaults up.
The live DNS backend (PowerDNS) models records as record **sets** addressed by
name and type. PowerDNS exposes no record IDs and returns values in a
`contents` array. The CLI previously decoded neither, so on PowerDNS-backed
deployments record tables printed blank ID and CONTENT columns, and
`dns record-delete` demanded a numeric `--record-id` those deployments never
expose. Record deletion was impossible there. Backends that do expose record
IDs keep the legacy `--record-id` path.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
This release aligns the CLI with how the backend actually works, verified live
end to end (create → show → delete → confirm gone).

Highlights:

- **Profile default region/project are honored by create/mutate commands.** The root
scope gate now injects the resolved scope (flag > env > profile default, respecting
`--profile`) onto the command's flags. Verified end-to-end against the production API.
- **First-run setup points at the production defaults.** The installers print
copy-paste setup for `zcp profile add default --region yul-1 --project default-9`;
every account's initial project is `default-9` (like `us-east-1` on AWS).
- **All command examples use slugs verified against the live production catalog.**
Broken template, backup, and virtual-router plan slugs are fixed.
- **Record content is visible again.** `zcp dns show` and `record-create`
tables show real values (multi-value sets joined, e.g.
`ns1.zsoftly.ca., ns2.zsoftly.ca.`), and the dead ID column is gone.
- **`dns record-delete` works, by name and type.**
- **Record names are relative.** The backend appends the zone; the help text
now says so (passing an FQDN used to silently create
`www.example.com.example.com.`).
- **`egress create` retries its lookup and reports honestly** when the backend
silently drops an accepted rule (a platform-side issue found while testing).
- **`docs/commands.md` is now machine-validated:** all 264 examples checked
against the built CLI. Six sections documented commands that did not exist
and are rewritten to the real trees.

---

## Fixed
## Installation and upgrade

### Profile default region/project honored by create/mutate commands
The install script installs the latest release and upgrades an existing
installation in place.

```bash
zcp profile add default --region yul-1 --project default-9
zcp auth validate
**Linux / macOS**

# Previously: Error: --region is required
# Now: creates the network in yul-1 / default-9 from your profile defaults
zcp network create --name my-net --network-plan inet-yul --billing-cycle hourly
```bash
curl -fsSL https://github.com/zsoftly/zcp-cli/releases/latest/download/install.sh | bash
```

Explicit `--region`/`--project` flags and `ZCP_REGION`/`ZCP_PROJECT` still take
precedence over the profile default, and `--profile <name>` selects which profile's
defaults apply. Two command groups manage their own scope by design and are
unaffected: `dns create` (fixed `default` region; still needs an explicit
`--project`) and `object-storage create/list` (object-storage `os-*` regions).

### First-run examples point at the production defaults

The Unix and Windows installers now end with copy-paste setup commands
(`zcp profile add default --region yul-1 --project default-9`, `zcp auth validate`)
plus matching `ZCP_REGION`/`ZCP_PROJECT` examples for scripts. README,
configuration docs, and command examples consistently use `yul-1` as the primary
compute region and YUL-compatible plan slugs.
**Windows (PowerShell)**

### Command examples verified against the live production catalog
```powershell
irm https://github.com/zsoftly/zcp-cli/releases/latest/download/install.ps1 | iex
```

Examples that referenced nonexistent slugs are fixed:
**Manual download:** grab your platform's binary from the
[Releases](https://github.com/zsoftly/zcp-cli/releases) page, `chmod +x`, and
place it on your `PATH`.

| Was | Now | Where |
| --------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------ |
| `ubuntu-2604-lts` | `ubuntu-2604-lts-1` | instance/autoscale `--template` (template slugs are region-specific; this is yul-1's) |
| `backup-1`, `backup-basic` | `backup-yul` | `backup create`, `vm-backup create` `--plan` (backup plans are now enabled in the catalog) |
| `virtual-private-cloud-vpc` | `virtual-private-cloud-vpc-1` | `virtual-router create --plan` |
**Verify:**

The docs Backup section was rewritten to show the real `backup create` flags
(`--volume`/`--interval`/`--plan` …) and to drop nonexistent `backup get`/`backup
restore` subcommands. Verified live in yul-1: `ca2sl`/`ca2sm`/`ca2sxs`, `b2g1`,
`pro-nvme`, `inet-yul`, `l2net-yul`, `k8s-la-yul-1`, `k8s-xla-yul-1`,
`vm-snapshot-yul`, `ipv4-yul`, `lb-yul`, `backup-yul`, `virtual-private-cloud-vpc-1`,
`ubuntu-2604-lts-1`.
```bash
zcp version # zcp version v0.0.22
```

## Upgrade notes
First-time setup after installing:

No breaking changes. If you have profile defaults configured (`zcp profile add`
with `--region`/`--project`), create/mutate commands that previously errored
without explicit flags now use those defaults automatically; pass `--region`/
`--project` (or set `ZCP_REGION`/`ZCP_PROJECT`) to override per invocation.
```bash
zcp profile add default --region yul-1 --project default-9 # prompts for bearer token
zcp auth validate
```

---

## Installation
## Fixed

### Linux / macOS / WSL (one-liner)
### DNS record display and deletion

```bash
curl -fsSL https://github.com/zsoftly/zcp-cli/releases/latest/download/install.sh | bash
```

Installs `zcp` to `/usr/local/bin` (you may be prompted for `sudo`). Set `INSTALL_DIR` to
choose another location, e.g. `INSTALL_DIR="$HOME/.local/bin"`.
# Records show their content; sets are addressed by NAME + TYPE (no IDs)
zcp dns show example-com
# NAME TYPE CONTENT TTL
# www.example.com. A 192.0.2.50 3600
# example.com. NS ns1.zsoftly.ca., ns2.zsoftly.ca. 3600

### Windows (PowerShell)
# Create with a RELATIVE name (the backend appends the zone)
zcp dns record-create --domain example-com --name www --type A --content 192.0.2.50

```powershell
irm https://github.com/zsoftly/zcp-cli/releases/latest/download/install.ps1 | iex
# Delete by name and type (relative or fully qualified both work)
zcp dns record-delete --domain example-com --name www --type A
```

Installs `zcp.exe` to `%LOCALAPPDATA%\Programs\zcp`.
The legacy `--record-id` flag remains for deployments whose DNS backend exposes
record IDs. SDK consumers get `DeleteRecordByName`, `CanonicalRecordFQDN`, and
`Record.Contents`; the ID-based `DeleteRecord` is deprecated.

### Manual download
### Egress rule creation reporting

Grab the binary for your platform from the
[Releases page](https://github.com/zsoftly/zcp-cli/releases), make it executable, and put it on
your `PATH`.
The create endpoint returns no body, so the CLI resolves the new rule from the
rule list. It now retries that lookup (3 attempts over ~4s) before giving up,
and when the rule never appears (the API can return 200 yet create nothing on
some networks), the error says the backend may have dropped the rule, pointing
at the platform rather than the CLI.

| OS | Arch | Asset |
| ------- | ------------- | ----------------------- |
| Linux | x86_64 | `zcp-linux-amd64` |
| Linux | ARM64 | `zcp-linux-arm64` |
| macOS | Intel | `zcp-darwin-amd64` |
| macOS | Apple Silicon | `zcp-darwin-arm64` |
| Windows | x86_64 | `zcp-windows-amd64.exe` |
| Windows | ARM64 | `zcp-windows-arm64.exe` |
### Command reference corrected and machine-validated

```bash
# Linux amd64 example
curl -Lo zcp https://github.com/zsoftly/zcp-cli/releases/latest/download/zcp-linux-amd64
chmod +x zcp
sudo mv zcp /usr/local/bin/zcp
```

```powershell
# Windows amd64 example (PowerShell)
irm https://github.com/zsoftly/zcp-cli/releases/latest/download/zcp-windows-amd64.exe -OutFile zcp.exe
# then move zcp.exe to a directory on your PATH
```

### Verify

```bash
zcp version
zcp --help
```
Six sections of `docs/commands.md` documented commands that do not exist
(`monitoring create`, `vpn create --vpc`, `support close`, `dashboard status`,
among others) or missed required flags (`ip allocate` without `--plan`/
`--billing-cycle`). All are rewritten to the real command trees, including
the previously undocumented `kubernetes scale/get-config/upgrade-version/delete`
and `loadbalancer attach-vm/detach-vm/delete-rule`. Every example in the
reference is now validated automatically against the CLI (command paths and
flags; 264 examples).
Loading
Loading