Skip to content

AaronSaikovski/armv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ARMV - Azure Resource Moveability Validator

v1.2.2

Build Status Licence

A lightweight, high-performance CLI utility for validating Azure resource moveability without performing the actual move operation.

โš ๏ธ NOTE: THIS TOOL PERFORMS READ-ONLY VALIDATION AND WILL NOT PERFORM ANY ACTUAL MOVE OPERATIONS. IT GENERATES A DETAILED VALIDATION REPORT FOR ANALYSIS.

Overview

ARMV is a production-ready Go CLI utility that validates whether Azure resources can be moved between resource groups and subscriptions. It acts as a comprehensive wrapper around Azure's Validate Move Resources API, providing intelligent polling, detailed error reporting, and secure file operations.

This tool is a complete rewrite of the deprecated pyazvalidatemoveresources Python utility, now delivered as a fully standalone, self-contained Go binary with zero external dependencies.

Key Features

  • Non-Destructive Validation: Tests moveability without making any changes
  • Cross-Subscription Support: Validate moves across different subscriptions (same tenant only)
  • Intelligent Polling: Long-running operation polling with timeout protection (max 30 minutes)
  • Comprehensive Error Reporting: Detailed JSON diagnostics including tracking IDs and timestamps
  • Progress Visualization: Real-time progress bar during validation operations
  • Secure File Operations: Timestamped output files with secure permissions
  • Debug Mode: Optional verbose logging and timing information
  • Production-Ready: Fully tested, optimized memory usage, and comprehensive error handling
  • Multi-Platform Support: Cross-platform binaries for Linux, Windows, and macOS
  • Security Focused: Vulnerability scanning (govulncheck), static analysis (staticcheck), and comprehensive testing
  • Continuous Integration: Automated builds, tests, and security checks on every commit

How It Works

  1. Input Validation: Validates subscription IDs and resource group references
  2. Authentication: Uses Azure CLI's stored credentials (az login context)
  3. Resource Discovery: Enumerates all resources in the source resource group
  4. Validation: Calls Azure's Validate Move Resources API
  5. Polling: Polls the long-running operation with visual progress indication
  6. Output Generation: Writes timestamped results to the output directory

Response Codes

  • HTTP 204 (Success): All resources are eligible for move
  • HTTP 409 (Conflict): One or more resources cannot be moved - detailed error report is generated

Example Error Report

When validation fails, a detailed JSON report is generated:

{
  "error": {
    "code": "ResourceMoveValidationFailed",
    "message": "The resource batch move request has '1' validation errors. Diagnostic information: timestamp '20240520T034539Z', tracking Id '8f53448f-e108-4f51-85d4-259e2137761d', request correlation Id '0a88b427-06ea-4045-98f1-7d2c4aaf2867'.",
    "details": [
      {
        "code": "ResourceMoveNotSupported",
        "target": "/subscriptions/<subID>/resourceGroups/src-rsg/providers/Microsoft.ContainerInstance/containerGroups/aciresource",
        "message": "Resource move is not supported for resource types 'Microsoft.ContainerInstance/containerGroups'."
      }
    ]
  }
}

Architecture

ARMV follows a clean, layered architecture for maintainability and extensibility:

Core Layers

Layer Location Responsibility
CLI Layer cmd/armv/app/ Command-line interface, flag parsing, orchestration
Authentication internal/pkg/auth/ Azure credential management and SDK clients
Validation internal/pkg/validation/ Resource move validation API wrapper
Resource Management internal/pkg/resourcegroups/, internal/pkg/resources/ Azure resource group and resource operations
Polling cmd/armv/poller/ Long-running operation polling and result handling
Utilities pkg/utils/ Input validation, error handling, file I/O, JSON processing

Project Structure

armv/
โ”œโ”€โ”€ cmd/armv/                          # Application entry points
โ”‚   โ”œโ”€โ”€ main.go                        # CLI entry point with version embedding
โ”‚   โ”œโ”€โ”€ app/                           # Application logic
โ”‚   โ”‚   โ”œโ”€โ”€ root.go                   # Cobra CLI command setup
โ”‚   โ”‚   โ”œโ”€โ”€ command.go                # Main validation workflow orchestration
โ”‚   โ”‚   โ”œโ”€โ”€ login.go                  # Azure authentication verification
โ”‚   โ”‚   โ””โ”€โ”€ resourcegroup.go          # Resource group operations
โ”‚   โ””โ”€โ”€ poller/                        # Long-running operation handling
โ”‚       โ”œโ”€โ”€ pollapi.go                # API polling logic with timeout
โ”‚       โ”œโ”€โ”€ pollresponse.go           # Response handling and output
โ”‚       โ”œโ”€โ”€ pollerresponsedata.go     # Response data structures
โ”‚       โ”œโ”€โ”€ progressbar.go            # Progress bar visualization
โ”‚       โ””โ”€โ”€ constants.go              # Configuration constants
โ”‚
โ”œโ”€โ”€ internal/pkg/                      # Private internal packages
โ”‚   โ”œโ”€โ”€ auth/                          # Azure authentication
โ”‚   โ”‚   โ””โ”€โ”€ auth.go                   # Credential and client creation
โ”‚   โ”œโ”€โ”€ validation/                    # Resource move validation
โ”‚   โ”‚   โ”œโ”€โ”€ azureresourcemoveinfo.go  # Validation parameters struct
โ”‚   โ”‚   โ””โ”€โ”€ validatemove.go           # Validation API wrapper
โ”‚   โ”œโ”€โ”€ resourcegroups/                # Resource group operations
โ”‚   โ”‚   โ””โ”€โ”€ resourcegroups.go         # RG client and operations
โ”‚   โ””โ”€โ”€ resources/                     # Resource operations
โ”‚       โ””โ”€โ”€ resources.go              # Resource enumeration and filtering
โ”‚
โ”œโ”€โ”€ pkg/utils/                         # Public utility functions
โ”‚   โ”œโ”€โ”€ args.go                       # CLI argument structures
โ”‚   โ”œโ”€โ”€ validateinput.go              # UUID/subscription ID validation
โ”‚   โ”œโ”€โ”€ errorhandler.go               # Error handling utilities
โ”‚   โ”œโ”€โ”€ output.go                     # Console output formatting
โ”‚   โ”œโ”€โ”€ outputfile.go                 # File I/O with secure permissions
โ”‚   โ””โ”€โ”€ jsonutils.go                  # JSON marshaling/unmarshaling
โ”‚
โ”œโ”€โ”€ test/                              # Comprehensive test suite
โ”‚   โ”œโ”€โ”€ args_test.go
โ”‚   โ”œโ”€โ”€ validateinput_test.go
โ”‚   โ”œโ”€โ”€ azureresourcemoveinfo_test.go
โ”‚   โ”œโ”€โ”€ command_test.go
โ”‚   โ”œโ”€โ”€ pollerresponsedata_test.go
โ”‚   โ”œโ”€โ”€ jsonutils_test.go
โ”‚   โ””โ”€โ”€ outputfile_test.go
โ”‚
โ”œโ”€โ”€ go.mod                             # Go module definition
โ”œโ”€โ”€ go.sum                             # Dependency checksums
โ”œโ”€โ”€ Taskfile.yml                       # Build task automation
โ”œโ”€โ”€ README.md                          # This file
โ”œโ”€โ”€ LICENSE                            # MIT License
โ”œโ”€โ”€ CHANGELOG.md                       # Version history
โ””โ”€โ”€ TODO.md                            # Future enhancements

Dependencies

The project uses the following key Go packages:

Package Version Purpose
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 Azure SDK core functionality
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 Azure credential authentication
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 Azure resources API client
github.com/spf13/cobra v1.10.1 CLI command framework
github.com/schollz/progressbar/v3 v3.18.0 Progress bar visualization

Requirements

  • Go: v1.25.3 or later for building from source
  • Azure CLI: v2.50 or later
  • Taskfile: v3.0+ for build automation (optional but recommended)
  • Azure Credentials: Valid Azure CLI login context (az login)

CI/CD & Quality Assurance

The project uses comprehensive GitHub Actions workflows for:

  • Multi-Platform Testing: Automated builds and tests on Ubuntu, Windows, and macOS
  • Multi-Architecture Support: Cross-platform binary releases for amd64, arm64, armv7, and 386
  • Code Quality: Automated vulnerability scanning, static analysis, and linting
  • Release Automation: GoReleaser for building and publishing multi-platform binaries

Quality Checks

All commits run through:

  • โœ… govulncheck: Vulnerability scanning
  • โœ… staticcheck: Advanced static code analysis
  • โœ… go vet: Go's built-in static analysis
  • โœ… go test: Comprehensive unit tests (38+ test cases, 100% pass rate)

Installation & Setup

Prerequisites: Azure Authentication

Before using ARMV, you must authenticate with Azure:

# Log in to Azure
az login

# Set the active subscription (replace XXXX-XXXX-XXXX-XXXX with your subscription ID)
az account set --subscription "XXXX-XXXX-XXXX-XXXX"

ARMV uses the DefaultAzureCredential chain from the Azure SDK, which will use your authenticated Azure CLI context.

Building from Source

This project uses Taskfile for build automation. All build commands are defined in Taskfile.yml.

Available Tasks

build            # Build debug version for your platform
clean            # Remove builds and debug artifacts
debug            # Run debug version with environment variables
deploy           # Deploy test Azure resources using Bicep
destroy          # Destroy test Azure resources
deps             # Fetch and update dependencies
generate         # Update binary version using go:generate
goreleaser       # Build cross-platform release binaries
lint             # Format, lint, and tidy code
release          # Build optimized release binary (outputs to /bin)
run              # Build and run the application
seccheck         # Security vulnerability scanner
staticcheck      # Static code analysis
test             # Run unit tests
version          # Display Go version
vet              # Examine code for suspicious constructs
watch            # Enable hot reload with air

Quick Start

# 1. Fetch dependencies
task deps

# 2. Build debug version
task build

# 3. Build release version (outputs to ./bin)
task release

Testing

# Run all unit tests
task test

# Run tests with verbose output
go test ./... -v

# Run tests with coverage report
go test ./... -cover

Usage

Basic Command

./armv --SourceSubscriptionId <SOURCE_SUB_ID> \
       --SourceResourceGroup <SOURCE_RG> \
       --TargetSubscriptionId <TARGET_SUB_ID> \
       --TargetResourceGroup <TARGET_RG>

Command-Line Flags

Required Flags

Flag Description Example
--SourceSubscriptionId Source Azure subscription ID (UUID format) 00000000-0000-0000-0000-000000000000
--SourceResourceGroup Source resource group name my-source-rg
--TargetSubscriptionId Target Azure subscription ID (UUID format) 00000000-0000-0000-0000-000000000001
--TargetResourceGroup Target resource group name my-target-rg

Optional Flags

Flag Description Default
--outpath Directory path for output files ./output
--debug Enable debug mode with timing information false
--help Display help information -
--version Display version information -

Examples

Example 1: Validate Move (Same Tenant, Different Subscription)

./armv \
  --SourceSubscriptionId "12345678-1234-1234-1234-123456789012" \
  --SourceResourceGroup "rg-prod-east" \
  --TargetSubscriptionId "87654321-4321-4321-4321-210987654321" \
  --TargetResourceGroup "rg-dev-west"

Example 2: Validate Move with Custom Output Directory

./armv \
  --SourceSubscriptionId "12345678-1234-1234-1234-123456789012" \
  --SourceResourceGroup "source-rg" \
  --TargetSubscriptionId "12345678-1234-1234-1234-123456789012" \
  --TargetResourceGroup "target-rg" \
  --outpath "/var/log/armv-reports"

Example 3: Validate Move with Debug Output

./armv \
  --SourceSubscriptionId "12345678-1234-1234-1234-123456789012" \
  --SourceResourceGroup "source-rg" \
  --TargetSubscriptionId "12345678-1234-1234-1234-123456789012" \
  --TargetResourceGroup "target-rg" \
  --debug

Output

When validation completes, a timestamped report file is created in the output directory:

./output/output-2024-10-30-14-30-45.txt

Success Output (HTTP 204):

Validation succeeded with HTTP code: 204
All resources are eligible for move

Failure Output (HTTP 409): The output file contains a detailed JSON error report with:

  • Error code and message
  • Diagnostic information (timestamp, tracking ID, correlation ID)
  • Per-resource validation failures with specific reasons

Testing

The project includes comprehensive unit tests with 38+ test cases covering:

Test Modules

Test File Focus Test Cases
validateinput_test.go UUID/subscription ID validation 8 tests
args_test.go Command-line argument parsing 3 tests
azureresourcemoveinfo_test.go Validation parameter initialization 5 tests
command_test.go Cobra command configuration 10 tests
pollerresponsedata_test.go API response processing 4 tests
jsonutils_test.go JSON serialization/deserialization 14 tests
outputfile_test.go File I/O and permissions 7 tests

Test Status: โœ… 100% Pass Rate

Run tests with:

# Run all tests
task test

# Verbose output
go test ./... -v

# With coverage
go test ./... -cover

# Run security checks
task seccheck          # govulncheck
task staticcheck       # Static analysis
task vet               # go vet

Limitations

  • Single Tenant: Currently supports only subscriptions and resource groups within the same Azure tenant
  • Source Resource Group: All resources to be moved must be in the same source resource group
  • Target Flexibility: Target resource group can be in a different subscription (within the same tenant)

Troubleshooting

Azure Authentication Issues

Error: No credentials found

Solution: Ensure you're logged in to Azure CLI:

az login
az account show  # Verify active subscription

Input Validation Errors

Error: Invalid subscription ID format

Solution: Ensure subscription IDs are valid UUIDs:

Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Example: 12345678-1234-1234-1234-123456789012

Resource Group Not Found

Error: Resource group not found

Solution:

  1. Verify the resource group exists in the specified subscription
  2. Ensure you have permissions to access the resource group
  3. Check that you're using the correct subscription context

API Timeout

Error: Validation operation timed out after 30 minutes

Solution:

  • This indicates the Azure API is taking longer than expected
  • Check Azure service health: https://status.azure.com/
  • Retry the validation operation
  • Consider validating smaller batches of resources

Reporting Issues

Found a bug or have a feature request? Please report it on GitHub:

๐Ÿ“‹ Report Issues Here

Include the following information:

  • ARMV version (./armv --version)
  • Go version (go version)
  • Error message and output file
  • Steps to reproduce

Development

Code Quality

The project maintains high code quality standards:

# Format and lint
task lint

# Security vulnerability scan
task seccheck

# Static analysis
task staticcheck

# Vet (examines code for suspicious constructs)
task vet

Git Workflow

  1. Create a feature branch: git checkout -b feature/my-feature
  2. Make changes and commit: git commit -am "Add new feature"
  3. Push to remote: git push origin feature/my-feature
  4. Create a pull request

GitHub Actions Workflows

The project includes automated CI/CD workflows:

Build Workflow (.github/workflows/build.yml)

Runs on every push and pull request to main:

  • Multi-platform matrix testing (Ubuntu, Windows, macOS)
  • Dependency verification
  • Code quality checks (go vet, staticcheck, govulncheck)
  • Comprehensive unit tests
  • Binary build verification

GoReleaser Workflow (.github/workflows/goreleaser.yml)

Runs on release creation:

  • Pre-release multi-platform testing
  • Cross-platform binary compilation (amd64, arm64, armv7, 386)
  • Automatic release notes generation
  • Binary artifact publishing

Releases & Binary Availability

Pre-compiled binaries are available for multiple platforms:

OS Architectures
Linux amd64, arm64, armv7, 386
Windows amd64, 386
macOS amd64, arm64

Download latest binaries from GitHub Releases

License

This project is licensed under the MIT License - see the LICENSE file for details.

Related Projects


Questions or feedback? Please open an issue or check the project repository