Skip to content

Repository files navigation

mk - Infrastructure Deployment CLI Tool

A CLI tool written in Rust for managing infrastructure deployments across multiple technologies (Terraform, Helm, Kustomize, and Ansible).

Features

  • 🔍 Auto-detection - Automatically detects technology type (terraform/helm/kustomize/ansible)
  • Environment validation - Validates environment names before execution
  • 🔒 Kubernetes context safety - Prevents deploying to wrong clusters (Helm/Kustomize)
  • 🎨 Color-coded output - Clear, readable terminal output
  • 🚀 Direct command execution - No intermediate make calls
  • 🔧 Special commands - Support for unlock, and duplicate
  • 🐚 Shell completions - Bash and Zsh support

Installation

From Release

Download pre-built binaries from the releases page:

# Download and install (example for Linux/macOS)
curl -L https://github.com/baprx/mk/releases/latest/download/mk-<platform> -o mk
chmod +x mk
mv mk ~/.local/bin/

From Source

cargo build --release --locked
cp target/release/mk ~/.local/bin/

Shell Completions

Generate completions for your shell:

# Bash
mk completions bash >~/.local/share/bash-completion/completions/mk
source~/.local/share/bash-completion/completions/mk
# Zshsource<(mk completions zsh)

The completions include dynamic environment completion based on your project structure:

  • For Terraform projects: Completes from tfvars/*.tfvars files
  • For Helm projects: Completes from values/*/ directories
  • For Kustomize projects: Completes from overlays/*/ directories
  • For Ansible projects: Completes from inventories/*.yml files

Example usage:

mk apply infrastructure/iam/terraform <TAB># Suggests: dev prod staging (based on actual tfvars files)

Usage

Basic Commands

# Apply infrastructure changes
mk apply <project-path><environment> [options]
# Plan/check changes
mk check <project-path><environment> [options]
mk plan <project-path><environment> [options] # Alias for check# Show diff
mk diff <project-path><environment> [options]
# Destroy/delete infrastructure
mk delete <project-path><environment> [options]
mk destroy <project-path><environment> [options] # Alias
mk uninstall <project-path><environment> [options] # Alias# Update dependencies
mk deps <project-path><environment> [options]
# Render templates
mk template <project-path><environment> [options]
# Get terraform output
mk output <project-path><environment><key># Autocompletion works for <key>, also a --all flag is available# List ansible inventory
mk list <project-path><environment> [options]
# Duplicate environment
mk duplicate <project-path><source-env><target-env># Check for dependency updates (Terraform & Helm)
mk bump <project-path> [--include-prereleases] [--recursive]

Special Commands

# Force unlock terraform state
mk unlock <project-path><environment><lock-id>

Dependency Management

The bump command helps you keep Terraform modules and Helm charts up to date:

# Scan a single project for outdated dependencies
mk bump infrastructure/terraform/my-project
# Scan recursively across multiple projects (max depth: 5)
mk bump infrastructure --recursive
# Include pre-release versions (alpha, beta, rc)
mk bump infrastructure --include-prereleases --recursive
# Show verbose output during scanning
mk bump infrastructure --verbose --recursive

Features:

  • Interactive selection of dependencies to update
  • Support for Terraform registry modules and Helm chart repositories
  • Caching of version lookups to avoid redundant API calls when scanning recursively
  • Respects .gitignore patterns when scanning recursively
  • Configurable maximum scan depth via ~/.config/mk/config.toml

Configuration:

Create or update ~/.config/mk/config.toml:

[bump]
# Maximum directory depth for recursive scanning (default: 5)max_depth = 5

Example output:

$ mk bump infrastructure/pubsub --recursive
INFO: Scanning recursively (max depth: 5): infrastructure/pubsub
INFO: Found 3 Terraform project(s), 0 Helm project(s)
INFO: Found 2 dependencies with updates available
Select dependencies to update (Space to select, Enter to confirm):
> [x] terraform-google-modules/pubsub/google (pubsub.tf:3) 8.2.0 → 8.3.2
[ ] terraform-google-modules/iam/google//modules/pubsub_topics_iam (pubsub.tf:15) 8.0.0 → 8.1.0
INFO: Updating selected dependencies...
✓ Updated terraform-google-modules/pubsub/google in pubsub.tf
SUCCESS: 1 dependencies updated across 3 project(s)

Drift Detection

Scan infrastructure for configuration drift across multiple projects and environments:

# Scan a directory for drift (Terraform & Helm)
mk drift infrastructure
# Filter by technology
mk drift infrastructure --tech terraform
# Filter by environment(s)
mk drift infrastructure --env prod --env staging
# Capture detailed output to logs
mk drift infrastructure --capture --verbose
# Scan with custom depth and ignore .gitignore
mk drift infrastructure --max-depth 10 --no-ignore

Exit codes:

  • 0: No drift detected
  • 2: Drift detected
  • 1: Errors occurred

Global Options

-v, --verbose Enable verbose output
-h, --help Show help information
-V, --version Show version information

Technology Detection

The tool automatically detects the technology based on project structure:

  • Terraform: Directory named terraform or contains tfvars/ directory
  • Helm: Contains values.yaml file
  • Kustomize: Contains overlays/ directory
  • Ansible: Directory named ansible or contains inventories/ directory

Environment Detection

Environments are detected from:

  • Terraform: Files in tfvars/ directory (e.g., tfvars/dev.tfvarsdev)
  • Helm: Directories in values/ (e.g., values/dev/dev)
  • Kustomize: Directories in overlays/ (e.g., overlays/dev/dev)
  • Ansible: Files in inventories/ (e.g., inventories/dev.ymldev)

Examples

Terraform

# Plan infrastructure changes
mk plan infrastructure/iam/terraform demo-env
# Apply changes
mk apply infrastructure/iam/terraform demo-env
# Get output value
mk output infrastructure/iam/terraform demo-env vpc_id
# Duplicate environment
mk duplicate infrastructure/iam/terraform demo-env staging-env
# Unlock state
mk unlock infrastructure/iam/terraform demo-env 196787809097

Helm

# Update dependencies
mk deps manifests/monitoring/prometheus demo-env
# Show diff
mk diff manifests/monitoring/prometheus demo-env
# Install/upgrade
mk apply manifests/monitoring/prometheus demo-env
# Uninstall
mk uninstall manifests/monitoring/prometheus demo-env
# Render templates
mk template manifests/monitoring/prometheus demo-env

Kustomize

# Build manifests
mk template manifests/monitoring/stackdriver-exporter demo-env
# Show diff
mk diff manifests/monitoring/stackdriver-exporter demo-env
# Apply
mk apply manifests/monitoring/stackdriver-exporter demo-env
# Delete
mk delete manifests/monitoring/stackdriver-exporter demo-env

Ansible

# Install dependencies
mk deps infrastructure/sftp/instance/ansible demo-env
# Check playbook (dry-run)
mk check infrastructure/sftp/instance/ansible demo-env
# Run playbook
mk apply infrastructure/sftp/instance/ansible demo-env
# List inventory
mk list infrastructure/sftp/instance/ansible demo-env

Command Mapping

Terraform

Terraform init is automatically run before apply, plan, destroy, and output commands.

ActionCommand
applyterraform apply -var-file=tfvars/{env}.tfvars
plan/checkterraform plan -var-file=tfvars/{env}.tfvars
destroyterraform destroy -var-file=tfvars/{env}.tfvars
outputterraform output {key}

Helm

Helm dependencies are automatically updated before apply, diff, and template if needed (based on Chart.lock & charts/*.tgz).

ActionCommand
applyhelmfile sync -e {env} --skip-deps
diffhelmfile diff -e {env} --skip-deps
depshelmfile deps -e {env}
templatehelmfile template -e {env} --skip-deps
uninstallhelmfile destroy -e {env} --skip-deps

Kustomize

ActionCommand
applykustomize build overlays/{env} | kubectl apply -f -
diffkustomize build overlays/{env} | kubectl diff -f -
templatekustomize build overlays/{env}
deletekustomize build overlays/{env} | kubectl delete -f -

Ansible

ActionCommand
applyansible-playbook -i inventories/{env}.yml playbook.yml -D
check/diffansible-playbook -i inventories/{env}.yml playbook.yml -DC
depsansible-galaxy install -r roles/requirements.yml -f
listansible-inventory -i inventories/{env}.yml --list | jq .

Configuration

Configuration File

Initialize a configuration file with examples:

mk init

This creates ~/.config/mk/config.toml with the following options:

Technology Priority

Set the priority order when multiple technologies are detected:

# Prioritize Terraform over other technologiestechnology_priority = ["terraform", "kustomize", "helm", "ansible"]

Bump Configuration

Configure the dependency bump command:

[bump]
# Maximum directory depth for recursive scanning (default: 5)max_depth = 5

Kubernetes Context Safety (Helm/Kustomize)

Automatically validates that you're using the correct kubectl context before applying or diffing changes:

[context]
# Disable context validation checks (default: false)disable_context_check = false# Context mappings: repository -> environment -> kubectl context# Example:
[context.mappings."github.com/user/infra"]
prod = "gke_project_cluster-prod"staging = "gke_project_cluster-staging"

How it works:

  1. When you run mk apply or mk diff for Helm/Kustomize:

    • The tool checks if a context mapping exists for your git repository and environment
    • If a mapping exists, it verifies your current kubectl context matches the expected one
    • If no mapping exists, it prompts you to save the current context for future use
  2. Example workflow:

# First time running for a new environment
$ mk apply ./my-helm-chart prod
WARNING: No Kubernetes context configured for:
Repository: github.com/user/infra
Environment: prod
Current kubectl context: gke_project_cluster-prod
Continue and save this context for future use? [Y/n]: y
SUCCESS: Context mapping saved to ~/.config/mk/config.toml
# Future runs validate automatically
$ mk apply ./my-helm-chart prod
✓ Context validated: gke_project_cluster-prod
# If you accidentally use wrong context
$ kubectl config use-context gke_project_cluster-staging
$ mk apply ./my-helm-chart prod
ERROR: Kubernetes context mismatch!
Repository: github.com/user/infra
Environment: prod
Expected context: gke_project_cluster-prod
Current context: gke_project_cluster-staging
Please switch to the correct context with:
kubectl config use-context gke_project_cluster-prod
  1. Team sharing:

You can also create a .mk/contexts.toml file in your git repository to share context mappings with your team:

[mappings."github.com/user/infra"]
prod = "gke_project_cluster-prod"staging = "gke_project_cluster-staging"dev = "gke_project_cluster-dev"

The tool prioritizes repo-level configs over user-level configs, allowing teams to establish consistent context mappings.

Development

Building

cargo build --release --locked
# or continuously with
watchexec -r -e rs --bell -- 'cargo build --release --locked'

Testing

cargo test

Linting

cargo clippy

License

MIT License. See LICENSE for details.

About

IaC swiss army knife

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages