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
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,33 @@ 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).

## [0.0.9] - 2026-04-14

### Added

- **Environment variable overrides**: `ZCP_PROJECT`, `ZCP_REGION`, `ZCP_CLOUD_PROVIDER`, `ZCP_OUTPUT`, `ZCP_DEBUG` — reduces repetitive flags in CI/CD and scripting
- **Zero-config mode**: CLI can now operate with only `ZCP_BEARER_TOKEN` and `ZCP_API_URL` env vars — no config file or profile required
- **`ZCP_PROFILE` env var**: Selects the active profile without `--profile` flag
- **`ZCP_BEARER_TOKEN` env var**: Overrides profile credentials at runtime
- **`ZCP_API_URL` env var**: Overrides the API base URL at runtime
- **Env var tests**: 14 new tests covering all resolution helpers and config env overrides

### Fixed

- **Kubernetes create**: Restored missing `--billing-cycle` validation (was accidentally removed)
- **Kubernetes create**: Fixed resolve order — `resolveRegion/resolveProject/resolveCloudProvider` now called before validation checks so env vars are applied correctly
- **All create commands**: Consistent resolve order — env var resolution always runs before required-field validation across all 18 command files

### Changed

- **`config.ResolveProfile`**: Now checks `ZCP_PROFILE` env var before falling back to `active_profile` in config file
- **`config.ActiveAPIURL`**: Now checks `ZCP_API_URL` env var before falling back to profile URL
- **Documentation**: Updated `docs/configuration.md` and `README.md` with all new environment variables and CI/CD usage examples

**Full Changelog**: https://github.com/zsoftly/zcp-cli/compare/0.0.8...0.0.9

---

## [0.0.8] - 2026-04-09

### Fixed
Expand Down
56 changes: 35 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ zcp profile rename staging prod
zcp profile delete old-profile
```

### Environment Variables

You can override configuration and flags using environment variables:

- `ZCP_BEARER_TOKEN`: Overrides profile credentials.
- `ZCP_API_URL`: Overrides the API base URL.
- `ZCP_PROJECT`: Sets the default project slug.
- `ZCP_REGION`: Sets the default region slug.
- `ZCP_CLOUD_PROVIDER`: Sets the default cloud provider.
- `ZCP_OUTPUT`: Sets the default output format (`json`, `yaml`, `table`).
- `ZCP_DEBUG`: Set to `true` to enable verbose debug output.

See [docs/configuration.md](docs/configuration.md) for the full list and usage examples.

---

## Commands Reference
Expand Down Expand Up @@ -183,9 +197,9 @@ zcp instance get <slug>
# Create — use --wait to block until the instance is Running
zcp instance create \
--name my-vm \
--cloud-provider nimbo \
--cloud-provider zcp \
--project my-project \
--region noida \
--region yow-1 \
--template ubuntu-22f \
--plan bp-4vc-8gb \
--billing-cycle hourly \
Expand Down Expand Up @@ -248,8 +262,8 @@ zcp volume list
zcp volume create \
--name my-disk \
--project my-project \
--cloud-provider nimbo \
--region noida \
--cloud-provider zcp \
--region yow-1 \
--billing-cycle hourly \
--storage-category nvme \
--plan 50-gb-2
Expand All @@ -263,8 +277,8 @@ zcp snapshot create \
--volume <slug> \
--name my-snapshot \
--plan snapshot-per-gb \
--cloud-provider nimbo \
--region noida \
--cloud-provider zcp \
--region yow-1 \
--billing-cycle hourly \
--project my-project
zcp snapshot revert <snapshot-slug> --volume <volume-slug>
Expand All @@ -277,8 +291,8 @@ zcp vm-snapshot create \
--plan basic \
--billing-cycle hourly \
--project my-project \
--cloud-provider nimbo \
--region noida
--cloud-provider zcp \
--region yow-1
zcp vm-snapshot revert <slug>
```

Expand All @@ -288,11 +302,11 @@ zcp vm-snapshot revert <slug>
# Networks
zcp network list
zcp network categories
zcp network create --name my-net --category <slug> --cloud-provider nimbo --region noida --project default-124
zcp network create --name my-net --category <slug> --cloud-provider zcp --region yow-1 --project my-project
zcp network update <slug> --name "New Name"

# VPC tier networks
zcp network create --name public-tier --cloud-provider nimbo --region noida --project default-124 \
zcp network create --name public-tier --cloud-provider zcp --region yow-1 --project my-project \
--vpc <vpc-slug> --type Vpc --gateway 10.1.1.1 --netmask 255.255.255.0 --acl-id <acl-id>

# Public IP addresses
Expand Down Expand Up @@ -327,9 +341,9 @@ zcp portforward create \
zcp vpc list
zcp vpc create \
--name my-vpc \
--cloud-provider nimbo \
--region noida \
--project default-124 \
--cloud-provider zcp \
--region yow-1 \
--project my-project \
--plan vpc-1 \
--network-address 10.1.0.1 \
--size 16 \
Expand Down Expand Up @@ -373,7 +387,7 @@ zcp dns list
zcp dns show <slug>

# Create a domain
zcp dns create --name example.com --project my-project --cloud-provider nimbo --region noida --dns-provider powerdns
zcp dns create --name example.com --project my-project --cloud-provider zcp --region yow-1 --dns-provider dns-provider

# Create a record
zcp dns record-create --domain <domain-slug> --name www --type A --content 192.0.2.1
Expand All @@ -399,7 +413,7 @@ zcp backup delete <slug>
```bash
zcp autoscale list
zcp autoscale get <slug>
zcp autoscale create --name my-policy --min 1 --max 5 --cloud-provider nimbo --region noida --project default-124
zcp autoscale create --name my-policy --min 1 --max 5 --cloud-provider zcp --region yow-1 --project my-project
zcp autoscale delete <slug>
```

Expand Down Expand Up @@ -438,9 +452,9 @@ zcp kubernetes create \
--name my-cluster \
--version v1.28.4 \
--plan k8s-plan-1 \
--region noida \
--project default-59 \
--cloud-provider nimbo \
--region yow-1 \
--project my-project \
--cloud-provider zcp \
--billing-cycle monthly \
--workers 3 \
--ssh-key mykey
Expand All @@ -450,9 +464,9 @@ zcp kubernetes create \
--name ha-cluster \
--version v1.28.4 \
--plan k8s-plan-1 \
--region noida \
--project default-59 \
--cloud-provider nimbo \
--region yow-1 \
--project my-project \
--cloud-provider zcp \
--billing-cycle monthly \
--workers 3 \
--control-nodes 3 \
Expand Down
73 changes: 33 additions & 40 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,53 @@
# zcp 0.0.8 Release Notes
# zcp 0.0.9 Release Notes

## What's New

### VPC create fixed
### Environment variable support

VPC creation now works with the correct payload structure:
All create commands now respect environment variables for the three most commonly repeated flags. Set them once and every command picks them up:

```bash
zcp vpc create \
--name my-vpc \
--cloud-provider nimbo \
--region noida \
--project default-124 \
--plan vpc-1 \
--network-address 10.1.0.1 \
--size 16 \
--billing-cycle hourly \
--storage-category nvme
```

Key: `--network-address` is just the IP (not CIDR notation), `--size` is the mask separately.

### ACL list creation fixed
export ZCP_CLOUD_PROVIDER=zcp
export ZCP_REGION=yow-1
export ZCP_PROJECT=my-project

`zcp vpc acl-create` and `zcp acl create` now correctly create ACL lists:
# Before: every command needed all 3 flags
zcp instance create --name my-vm --cloud-provider zcp --region yow-1 --project my-project --template ubuntu-22f --plan bp-4vc-8gb --billing-cycle hourly --storage-category nvme --blockstorage-plan 50-gb-2

```bash
zcp vpc acl-create my-vpc --name allow-web --description "Allow HTTP"
zcp acl create my-vpc --name private-acl --description "Deny all inbound"
# Now: just the resource-specific flags
zcp instance create --name my-vm --template ubuntu-22f --plan bp-4vc-8gb --billing-cycle hourly --storage-category nvme --blockstorage-plan 50-gb-2
```

### Create commands gain required flags

`--cloud-provider`, `--region`, `--project` added to: network, vpc, virtualrouter, dns, vpn, autoscale create commands.
Works across all create commands: instance, volume, vpc, network, kubernetes, dns, loadbalancer, autoscale, snapshot, vm-snapshot, vm-backup, virtual-router, vpn, iso, affinity-group, template, backup.

### Volume Size type fix
### Zero-config mode

Volume list no longer fails when the API returns size as a number.
The CLI can now run with just environment variables — no config file needed:

### Roadmap published

See `docs/roadmap.md` for what's working, what's coming, and what's blocked on the platform.
```bash
export ZCP_BEARER_TOKEN=your-token
export ZCP_API_URL=https://api.zcp.zsoftly.ca
zcp region list
```

---
### All new environment variables

## Known limitations (blocked on platform)
| Variable | Overrides | Example |
| -------------------- | ----------------------------------------- | -------------------------------- |
| `ZCP_BEARER_TOKEN` | Profile `bearer_token` | `export ZCP_BEARER_TOKEN=abc123` |
| `ZCP_API_URL` | Profile `api_url` | `export ZCP_API_URL=https://...` |
| `ZCP_PROFILE` | Active profile (when `--profile` not set) | `export ZCP_PROFILE=staging` |
| `ZCP_PROJECT` | `--project` flag | `export ZCP_PROJECT=my-project` |
| `ZCP_REGION` | `--region` flag | `export ZCP_REGION=yow-1` |
| `ZCP_CLOUD_PROVIDER` | `--cloud-provider` flag | `export ZCP_CLOUD_PROVIDER=zcp` |
| `ZCP_OUTPUT` | `--output` flag | `export ZCP_OUTPUT=json` |
| `ZCP_DEBUG` | `--debug` flag | `export ZCP_DEBUG=true` |

These require API changes from the STKCNSL team:
Precedence: CLI flag > environment variable > profile config > default.

- **No DELETE endpoints** for VPCs, networks, virtual routers, IP addresses, or ACL lists
- **No ACL rule CRUD** — can create ACL lists but not rules inside them
- **Network create (isolated)** — `networkofferingid` not resolvable for nimbo/noida
- **DNS create** — needs admin-side `cloud_provider_setup` provisioning
- **billing cancel-service for VPCs** — returns "service not found"
### Bug fix: Kubernetes create

See `docs/roadmap.md` for full details.
`--billing-cycle` validation was accidentally removed in v0.0.8. Restored — the API requires it (confirmed via Postman collection).

---

Expand All @@ -72,4 +65,4 @@ curl -fsSL https://github.com/zsoftly/zcp-cli/releases/latest/download/install.s
irm https://github.com/zsoftly/zcp-cli/releases/latest/download/install.ps1 | iex
```

**Full Changelog**: https://github.com/zsoftly/zcp-cli/compare/0.0.7...0.0.8
**Full Changelog**: https://github.com/zsoftly/zcp-cli/compare/0.0.8...0.0.9
8 changes: 4 additions & 4 deletions docs/command-taxonomy.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ZCP CLI Command Taxonomy (v0.0.6)

**CLI name**: `zcp`
**Base URL**: `https://portal.webberstop.com/backend/api`
**Base URL**: `https://api.zcp.zsoftly.ca`
**Authentication**: Bearer token (`--bearer-token` during profile add)

---
Expand Down Expand Up @@ -351,14 +351,14 @@ Each API request sends the token as an `Authorization: Bearer <token>` header.
## Identifier Conventions

v0.0.6 uses **slug-based identifiers** for most resources. Slugs are human-readable
strings assigned by the API (e.g., `my-vm-123`, `root-4153`, `example-com-1`).
strings assigned by the API (e.g., `my-vm-123`, `root-1234`, `example-com-1`).

| Context | Flag / Argument | Example |
| --------------- | --------------------------------- | ---------------------------------------- |
| VM instance | positional `<slug>` or `--vm` | `zcp instance get my-vm-123` |
| Volume | `--volume` | `zcp snapshot create --volume root-4153` |
| Volume | `--volume` | `zcp snapshot create --volume root-1234` |
| DNS domain | positional `<slug>` or `--domain` | `zcp dns show example-com-1` |
| Project | `--project` | `--project default-60` |
| Project | `--project` | `--project my-project` |
| Region | `--region` | `--region yow-1` |
| VPC | `--vpc` | `zcp ip list --vpc my-vpc` |
| IP | `--ip` | `zcp firewall list --ip my-ip-slug` |
Expand Down
33 changes: 22 additions & 11 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,33 @@ https://api.zcp.zsoftly.ca

## Environment Variable Overrides

The following environment variables are evaluated at runtime and take precedence over the corresponding config file values.

| Variable | Overrides | Description |
| ------------------ | ----------------------------------- | ------------------------------------------------- |
| `ZCP_PROFILE` | `--profile` flag / active profile | Profile name to use for the current invocation. |
| `ZCP_BEARER_TOKEN` | Profile `bearer_token` | Bearer token, bypassing the config file entirely. |
| `ZCP_API_URL` | Profile `api_url` / default URL | API base URL override. |
| `XDG_CONFIG_HOME` | Config file directory (Linux/macOS) | Overrides the base directory for the config file. |

Environment variables are useful for CI/CD pipelines where you do not want credentials stored in a file on disk.
The following environment variables are evaluated at runtime and take precedence over the corresponding config file values and global flags.

| Variable | Overrides | Description |
| -------------------- | ----------------------------------- | ------------------------------------------------- |
| `ZCP_PROFILE` | `--profile` flag / active profile | Profile name to use for the current invocation. |
| `ZCP_BEARER_TOKEN` | Profile `bearer_token` | Bearer token, bypassing the config file entirely. |
| `ZCP_API_URL` | Profile `api_url` / default URL | API base URL override. |
| `ZCP_PROJECT` | `--project` flag | Default project slug for all resource commands. |
| `ZCP_REGION` | `--region` flag | Default region slug for all resource commands. |
| `ZCP_CLOUD_PROVIDER` | `--cloud-provider` flag | Default cloud provider slug (e.g., `zcp`). |
| `ZCP_OUTPUT` | `--output` / `-o` flag | Default output format (`table`, `json`, `yaml`). |
| `ZCP_DEBUG` | `--debug` flag | Set to `true` to enable debug output (stderr). |
| `XDG_CONFIG_HOME` | Config file directory (Linux/macOS) | Overrides the base directory for the config file. |

Environment variables are useful for CI/CD pipelines and scripting where you do not want to pass repetitive flags or store credentials in a file on disk.

Example usage in a pipeline:

```bash
export ZCP_BEARER_TOKEN=ci-bearer-token
zcp region list --output json
export ZCP_PROJECT=prod-project
export ZCP_REGION=yow-1
export ZCP_CLOUD_PROVIDER=zcp
export ZCP_OUTPUT=json

# Create a volume without passing repetitive flags
zcp volume create --name my-disk --plan 50-gb-2 --billing-cycle hourly
```

---
Expand Down
8 changes: 4 additions & 4 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Features planned, in progress, or blocked on platform support.
- [ ] `portforward create` — add `--public-end-port` and `--private-end-port` flags (API requires them)
- [ ] `instance change-hostname` — fix request body field name (`vm_label` instead of `label`)
- [ ] `region` command — add `use` subcommand to set default region in profile
- [ ] Default `--cloud-provider`, `--region`, `--project` from profile config to reduce flag repetition
- [x] Default `--cloud-provider`, `--region`, `--project` via `ZCP_CLOUD_PROVIDER`, `ZCP_REGION`, `ZCP_PROJECT` env vars (v0.0.9)

### Blocked on STKCNSL platform

Expand All @@ -50,11 +50,11 @@ The UI has "Add Rule" with Number, CIDR, Action, Protocol, Traffic Type fields,
- [ ] `DELETE /vpcs/{slug}/network-acl-list/{acl_id}/rules/{rule_id}` — delete ACL rule
- [ ] `GET /vpcs/{slug}/network-acl-list/{acl_id}/rules` — list ACL rules

#### Network create (isolated) — noida region
#### Network create (isolated) — target region

`POST /networks` returns `missing parameter networkofferingid` for the nimbo/noida region. The API doesn't expose the network offering field. Likely a region configuration issue.
`POST /networks` returns `missing parameter networkofferingid` for the the target region region. The API doesn't expose the network offering field. Likely a region configuration issue.

- [ ] Network offering mapping for nimbo/noida
- [ ] Network offering mapping for the target region

#### DNS provisioning

Expand Down
5 changes: 4 additions & 1 deletion internal/commands/affinitygroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,23 @@ func newAffinityGroupCreateCmd() *cobra.Command {
Use: "create",
Short: "Create an affinity group",
Example: ` zcp affinity-group create --name my-group --type "host affinity" \
--cloud-provider nimbo --project default-1 --region yow-1`,
--cloud-provider zcp --project my-project --region yow-1`,
RunE: func(cmd *cobra.Command, args []string) error {
if name == "" {
return fmt.Errorf("--name is required")
}
if groupType == "" {
return fmt.Errorf("--type is required")
}
cloudProvider = resolveCloudProvider(cloudProvider)
if cloudProvider == "" {
return fmt.Errorf("--cloud-provider is required")
}
project = resolveProject(project)
if project == "" {
return fmt.Errorf("--project is required")
}
region = resolveRegion(region)
if region == "" {
return fmt.Errorf("--region is required")
}
Expand Down
Loading
Loading