Skip to content

Add CLI tool for querying VDC service availability from command line #21

Description

@comnam90

CLI Tool for VDC Service Availability Queries

Overview

Create a lightweight Node.js CLI tool (vdc command) that allows DevOps engineers, SREs, and developers to query Veeam Data Cloud service availability directly from the command line or scripts. This eliminates the need for curl commands, external tools, or manual API integration for common discovery tasks.

Scope

Included:

  • Query all regions or filter by provider (AWS/Azure)
  • Search for specific services
  • Filter by tier/edition for VDC Vault
  • Find nearest regions by coordinates
  • Display results in human-readable table format
  • Support JSON output for scripting
  • Interactive search/discovery mode
  • Help documentation

Explicitly Excluded:

  • GraphQL query support
  • Authentication/API key management
  • Caching local data
  • Custom output formatters (beyond JSON and table)

Technical Requirements

Core Functionality

# List all regions
vdc regions

# Filter by provider
vdc regions --provider AWS
vdc regions --provider Azure

# Filter by service
vdc regions --service vdc_vault
vdc regions --service vdc_m365

# Combine filters
vdc regions --provider AWS --service vdc_vault --tier Core

# Find nearest regions
vdc nearest --lat 35.6762 --lng 139.6503 --limit 5

# List all services
vdc services

# Get service details
vdc services vdc_vault

# Search by country/alias
vdc search "North Virginia"
vdc search "Frankfurt"

# JSON output
vdc regions --json
vdc nearest --lat 0 --lng 0 --json

# Help
vdc --help
vdc regions --help

Installation & Distribution

  • Published as npm package: @veeam/vdc-cli
  • Can also be run directly with npx: npx @veeam/vdc-cli regions
  • Packaged in npm workspace at packages/cli/ (or as separate package)
  • Include pre-built binaries for popular platforms (optional, phase 2)

Implementation Plan

Step 1: Project Structure

packages/cli/
├── package.json
├── README.md
├── src/
│   ├── index.ts            # CLI entry point
│   ├── commands/
│   │   ├── regions.ts      # Query regions
│   │   ├── services.ts     # Query services
│   │   ├── nearest.ts      # Find nearest regions
│   │   └── search.ts       # Search regions
│   ├── utils/
│   │   ├── api.ts          # API client (fetch from public API)
│   │   ├── format.ts       # Output formatting (table/JSON)
│   │   └── validate.ts     # Input validation
│   └── types.ts            # Shared TypeScript types
├── bin/
│   └── vdc.js              # Executable entry point
└── dist/                    # Compiled output

package.json:
{
  "name": "@veeam/vdc-cli",
  "version": "1.0.0",
  "bin": { "vdc": "./dist/bin/vdc.js" },
  "scripts": {
    "build": "tsc",
    "dev": "tsx src/index.ts",
    "test": "vitest"
  }
}

Step 2: CLI Framework & Command Structure

Use Commander.js (lightweight, no dependencies) for command parsing:

// src/index.ts
import { Command } from 'commander'
import { regionsCommand } from './commands/regions'
import { servicesCommand } from './commands/services'
import { nearestCommand } from './commands/nearest'
import { searchCommand } from './commands/search'

const program = new Command()
  .name('vdc')
  .description('Query Veeam Data Cloud service availability')
  .version('1.0.0')

program.addCommand(regionsCommand)
program.addCommand(servicesCommand)
program.addCommand(nearestCommand)
program.addCommand(searchCommand)

program.parse(process.argv)

Step 3: API Client Module

// src/utils/api.ts
const API_BASE = 'https://vdcmap.bcthomas.com/api/v1'

export async function queryRegions(filters: RegionFilters): Promise<Region[]> {
  const params = new URLSearchParams()
  if (filters.provider) params.append('provider', filters.provider)
  if (filters.service) params.append('service', filters.service)
  if (filters.tier) params.append('tier', filters.tier)
  
  const res = await fetch(`${API_BASE}/regions?${params}`)
  if (!res.ok) throw new Error(`API error: ${res.statusText}`)
  return res.json()
}

export async function queryNearest(lat: number, lng: number, limit: number) {
  const res = await fetch(`${API_BASE}/regions/nearest?lat=${lat}&lng=${lng}&limit=${limit}`)
  if (!res.ok) throw new Error(`API error: ${res.statusText}`)
  return res.json()
}

Step 4: Output Formatting

Use cli-table3 for human-readable output:

// src/utils/format.ts
import Table from 'cli-table3'

export function formatRegionsAsTable(regions: Region[]): void {
  const table = new Table({
    head: ['ID', 'Name', 'Provider', 'Services', 'Coordinates'],
    style: { head: [], border: ['grey'] }
  })
  
  regions.forEach(r => {
    const serviceCount = Object.keys(r.services).length
    table.push([
      r.id,
      r.name,
      r.provider,
      serviceCount.toString(),
      `${r.coords[0]}, ${r.coords[1]}`
    ])
  })
  
  console.log(table.toString())
}

export function formatAsJSON(data: any): void {
  console.log(JSON.stringify(data, null, 2))
}

Step 5: Command Implementations

Simple example for regions command:

// src/commands/regions.ts
import { Command } from 'commander'
import { queryRegions } from '../utils/api'
import { formatRegionsAsTable, formatAsJSON } from '../utils/format'

export const regionsCommand = new Command('regions')
  .description('List cloud regions with optional filters')
  .option('--provider <type>', 'Filter by cloud provider (AWS|Azure)')
  .option('--service <id>', 'Filter by service ID')
  .option('--tier <tier>', 'Filter by tier (Core|Non-Core)')
  .option('--json', 'Output as JSON')
  .action(async (options) => {
    try {
      const regions = await queryRegions(options)
      
      if (options.json) {
        formatAsJSON(regions)
      } else {
        formatRegionsAsTable(regions)
      }
    } catch (error) {
      console.error(`Error: ${error.message}`)
      process.exit(1)
    }
  })

Acceptance Criteria

  • CLI installs successfully via npm install -g @veeam/vdc-cli or npx @veeam/vdc-cli
  • vdc --help displays comprehensive help with all commands
  • vdc regions lists all 63 regions in table format
  • vdc regions --provider AWS filters to only AWS regions
  • vdc nearest --lat 35.6762 --lng 139.6503 returns Tokyo first
  • vdc search "Virginia" finds aws-us-east-1
  • vdc --json outputs valid JSON for all commands
  • Error handling returns clear messages for invalid inputs (e.g., invalid lat/lng range)
  • CLI runs successfully in Node.js 18+ and modern npm
  • Package documentation (README) includes usage examples
  • TypeScript types are strict and compilation passes with tsc --noEmit

Priority

User Impact: 3/5 (useful for DevOps automation scripts)
Strategic Alignment: 4/5 (reduces friction for API adoption)
Feasibility: 5/5 (straightforward implementation)
Overall Score: 12.0 (highest priority)

Justification: This is the highest-impact feature. Developers frequently ask "how do I query this programmatically" and a CLI tool is the most accessible entry point. It requires minimal infrastructure changes and leverages the existing REST API.

Dependencies

  • Blocks: None
  • Blocked by: None (uses existing API)

Implementation Size

  • Estimated effort: Small (3-4 days)
  • Complexity: Low
  • Testing effort: Low (mostly integration tests against live API)

Implementation Order

Implement in this sequence:

  1. Project structure & dependency setup
  2. API client module
  3. Output formatting utilities
  4. Core commands (regions, services, nearest)
  5. Search command (most complex filtering logic)
  6. Tests & documentation

Additional Notes

  • Start with published npm package; pre-built binaries (windows/mac/linux) can be phase 2
  • Consider auto-update mechanism later (e.g., vdc update)
  • The CLI can be a great onboarding tool for new users discovering the API
  • Future enhancement: Shell completion support (bash/zsh)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions