vm-tool 1.0.32__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. examples/README.md +5 -0
  2. examples/__init__.py +1 -0
  3. examples/cloud/README.md +3 -0
  4. examples/cloud/__init__.py +1 -0
  5. examples/cloud/ssh_identity_file.py +27 -0
  6. examples/cloud/ssh_password.py +27 -0
  7. examples/cloud/template_cloud_setup.py +36 -0
  8. examples/deploy_full_setup.py +44 -0
  9. examples/docker-compose.example.yml +47 -0
  10. examples/ec2-setup.sh +95 -0
  11. examples/github-actions-ec2.yml +245 -0
  12. examples/github-actions-full-setup.yml +58 -0
  13. examples/local/.keep +1 -0
  14. examples/local/README.md +3 -0
  15. examples/local/__init__.py +1 -0
  16. examples/local/template_local_setup.py +27 -0
  17. examples/production-deploy.sh +70 -0
  18. examples/rollback.sh +52 -0
  19. examples/setup.sh +52 -0
  20. examples/ssh_key_management.py +22 -0
  21. examples/version_check.sh +3 -0
  22. vm_tool/__init__.py +0 -0
  23. vm_tool/alerting.py +274 -0
  24. vm_tool/audit.py +118 -0
  25. vm_tool/backup.py +125 -0
  26. vm_tool/benchmarking.py +200 -0
  27. vm_tool/cli.py +761 -0
  28. vm_tool/cloud.py +125 -0
  29. vm_tool/completion.py +200 -0
  30. vm_tool/compliance.py +104 -0
  31. vm_tool/config.py +92 -0
  32. vm_tool/drift.py +98 -0
  33. vm_tool/generator.py +462 -0
  34. vm_tool/health.py +197 -0
  35. vm_tool/history.py +131 -0
  36. vm_tool/kubernetes.py +89 -0
  37. vm_tool/metrics.py +183 -0
  38. vm_tool/notifications.py +152 -0
  39. vm_tool/plugins.py +119 -0
  40. vm_tool/policy.py +197 -0
  41. vm_tool/rbac.py +140 -0
  42. vm_tool/recovery.py +169 -0
  43. vm_tool/reporting.py +218 -0
  44. vm_tool/runner.py +445 -0
  45. vm_tool/secrets.py +285 -0
  46. vm_tool/ssh.py +150 -0
  47. vm_tool/state.py +122 -0
  48. vm_tool/strategies/__init__.py +16 -0
  49. vm_tool/strategies/ab_testing.py +258 -0
  50. vm_tool/strategies/blue_green.py +227 -0
  51. vm_tool/strategies/canary.py +277 -0
  52. vm_tool/validation.py +267 -0
  53. vm_tool/vm_setup/cleanup.yml +27 -0
  54. vm_tool/vm_setup/docker/create_docker_service.yml +63 -0
  55. vm_tool/vm_setup/docker/docker_setup.yml +7 -0
  56. vm_tool/vm_setup/docker/install_docker_and_compose.yml +92 -0
  57. vm_tool/vm_setup/docker/login_to_docker_hub.yml +6 -0
  58. vm_tool/vm_setup/github/git_configuration.yml +68 -0
  59. vm_tool/vm_setup/inventory.yml +1 -0
  60. vm_tool/vm_setup/k8s.yml +15 -0
  61. vm_tool/vm_setup/main.yml +27 -0
  62. vm_tool/vm_setup/monitoring.yml +42 -0
  63. vm_tool/vm_setup/project_service.yml +17 -0
  64. vm_tool/vm_setup/push_code.yml +40 -0
  65. vm_tool/vm_setup/setup.yml +17 -0
  66. vm_tool/vm_setup/setup_project_env.yml +7 -0
  67. vm_tool/webhooks.py +83 -0
  68. vm_tool-1.0.32.dist-info/METADATA +213 -0
  69. vm_tool-1.0.32.dist-info/RECORD +73 -0
  70. vm_tool-1.0.32.dist-info/WHEEL +5 -0
  71. vm_tool-1.0.32.dist-info/entry_points.txt +2 -0
  72. vm_tool-1.0.32.dist-info/licenses/LICENSE +21 -0
  73. vm_tool-1.0.32.dist-info/top_level.txt +2 -0
examples/README.md ADDED
@@ -0,0 +1,5 @@
1
+ ## SSH Key Management
2
+ - `ssh_key_management.py`: Generate/manage SSH keys and configure VM for SSH access
3
+
4
+ ## Version Check
5
+ - `version_check.sh`: Check installed version of vm_tool
examples/__init__.py ADDED
@@ -0,0 +1 @@
1
+ # Example scripts package
@@ -0,0 +1,3 @@
1
+ # Cloud Examples
2
+
3
+ Use `template_cloud_setup.py` as your starting point for any cloud VM setup scenario. Other files are legacy or specific examples and can be removed if you only want the template.
@@ -0,0 +1 @@
1
+ # Cloud VM setup examples package
@@ -0,0 +1,27 @@
1
+ """
2
+ Example: Cloud VM setup using SSH key authentication (public GitHub repo).
3
+ - Connects to a remote VM using SSH key and runs setup from a public repo.
4
+ """
5
+
6
+ from vm_tool.runner import SetupRunner, SetupRunnerConfig, SSHConfig
7
+
8
+
9
+ def main():
10
+ config = SetupRunnerConfig(
11
+ github_project_url="https://github.com/username/public-repo",
12
+ github_branch="main",
13
+ docker_compose_file_path="docker-compose.yml",
14
+ )
15
+ runner = SetupRunner(config)
16
+ ssh_configs = [
17
+ SSHConfig(
18
+ ssh_username="your_ssh_username",
19
+ ssh_hostname="your_ssh_hostname",
20
+ ssh_identity_file="/path/to/your/ssh_key",
21
+ )
22
+ ]
23
+ runner.run_cloud_setup(ssh_configs)
24
+
25
+
26
+ if __name__ == "__main__":
27
+ main()
@@ -0,0 +1,27 @@
1
+ """
2
+ Example: Cloud VM setup using SSH password authentication (public GitHub repo).
3
+ - Connects to a remote VM using SSH username/password and runs setup from a public repo.
4
+ """
5
+
6
+ from vm_tool.runner import SetupRunner, SetupRunnerConfig, SSHConfig
7
+
8
+
9
+ def main():
10
+ config = SetupRunnerConfig(
11
+ github_project_url="https://github.com/username/public-repo",
12
+ github_branch="main",
13
+ docker_compose_file_path="docker-compose.yml",
14
+ )
15
+ runner = SetupRunner(config)
16
+ ssh_configs = [
17
+ SSHConfig(
18
+ ssh_username="your_ssh_username",
19
+ ssh_hostname="your_ssh_hostname",
20
+ ssh_password="your_ssh_password",
21
+ )
22
+ ]
23
+ runner.run_cloud_setup(ssh_configs)
24
+
25
+
26
+ if __name__ == "__main__":
27
+ main()
@@ -0,0 +1,36 @@
1
+ """
2
+ Template: Cloud VM setup (customize for your use case)
3
+ - Use this template to create your own cloud VM setup script.
4
+ - Supports public/private GitHub, DockerHub, SSH key or password authentication, and multiple VMs.
5
+ - Fill in only the fields you need for your scenario.
6
+ """
7
+
8
+ from vm_tool.runner import SetupRunner, SetupRunnerConfig, SSHConfig
9
+
10
+
11
+ def main():
12
+ # Fill in only the fields you need for your use case
13
+ config = SetupRunnerConfig(
14
+ github_username=None, # e.g., 'your_github_username' (for private repos)
15
+ github_token=None, # e.g., 'your_github_token' (for private repos)
16
+ github_project_url="https://github.com/username/your-repo",
17
+ github_branch="main", # Optional, defaults to 'main'
18
+ docker_compose_file_path="docker-compose.yml", # Optional
19
+ dockerhub_username=None, # e.g., 'your_dockerhub_username' (if DockerHub login needed)
20
+ dockerhub_password=None, # e.g., 'your_dockerhub_password' (if DockerHub login needed)
21
+ )
22
+ runner = SetupRunner(config)
23
+ ssh_configs = [
24
+ SSHConfig(
25
+ ssh_username="your_ssh_username",
26
+ ssh_hostname="your_ssh_hostname",
27
+ ssh_identity_file=None, # e.g., '/path/to/your/ssh_key' (for SSH key auth)
28
+ ssh_password=None, # e.g., 'your_ssh_password' (for SSH password auth)
29
+ )
30
+ # Add more SSHConfig instances for multiple VMs if needed
31
+ ]
32
+ runner.run_cloud_setup(ssh_configs)
33
+
34
+
35
+ if __name__ == "__main__":
36
+ main()
@@ -0,0 +1,44 @@
1
+ """
2
+ Example deployment script using run_cloud_setup for full VM provisioning.
3
+ This approach installs Docker, clones your repo, and sets up everything.
4
+ """
5
+
6
+ import os
7
+ from vm_tool.runner import SetupRunner, SetupRunnerConfig, SSHConfig
8
+
9
+ # Configuration
10
+ config = SetupRunnerConfig(
11
+ github_username=os.environ.get("GITHUB_USERNAME"),
12
+ github_token=os.environ.get("GITHUB_TOKEN"),
13
+ github_project_url=os.environ.get(
14
+ "GITHUB_PROJECT_URL", "https://github.com/user/repo.git"
15
+ ),
16
+ github_branch=os.environ.get("GITHUB_BRANCH", "main"),
17
+ docker_compose_file_path=os.environ.get(
18
+ "DOCKER_COMPOSE_FILE", "docker-compose.yml"
19
+ ),
20
+ dockerhub_username=os.environ.get("DOCKERHUB_USERNAME"),
21
+ dockerhub_password=os.environ.get("DOCKERHUB_PASSWORD"),
22
+ )
23
+
24
+ # Initialize runner
25
+ runner = SetupRunner(config)
26
+
27
+ # SSH configuration for target VM(s)
28
+ ssh_configs = [
29
+ SSHConfig(
30
+ ssh_username=os.environ.get("EC2_USER", "ubuntu"),
31
+ ssh_hostname=os.environ.get("EC2_HOST"),
32
+ ssh_identity_file=os.environ.get("SSH_IDENTITY_FILE", "~/.ssh/id_rsa"),
33
+ ),
34
+ ]
35
+
36
+ # Run full cloud setup
37
+ print("🚀 Starting full VM setup...")
38
+ print(f" Target: {ssh_configs[0].ssh_hostname}")
39
+ print(f" Repository: {config.github_project_url}")
40
+ print(f" Branch: {config.github_branch}")
41
+
42
+ runner.run_cloud_setup(ssh_configs)
43
+
44
+ print("✅ VM setup complete!")
@@ -0,0 +1,47 @@
1
+ version: "3.8"
2
+
3
+ services:
4
+ web:
5
+ image: nginx:alpine
6
+ ports:
7
+ - "80:80"
8
+ volumes:
9
+ - ./html:/usr/share/nginx/html
10
+ restart: unless-stopped
11
+ healthcheck:
12
+ test:
13
+ ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
14
+ interval: 30s
15
+ timeout: 10s
16
+ retries: 3
17
+ start_period: 40s
18
+
19
+ api:
20
+ image: python:3.11-slim
21
+ working_dir: /app
22
+ volumes:
23
+ - ./app:/app
24
+ command: python -m http.server 8000
25
+ ports:
26
+ - "8000:8000"
27
+ restart: unless-stopped
28
+ healthcheck:
29
+ test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
30
+ interval: 30s
31
+ timeout: 10s
32
+ retries: 3
33
+ start_period: 40s
34
+ environment:
35
+ - ENVIRONMENT=production
36
+ - LOG_LEVEL=info
37
+
38
+ redis:
39
+ image: redis:alpine
40
+ ports:
41
+ - "6379:6379"
42
+ restart: unless-stopped
43
+ healthcheck:
44
+ test: ["CMD", "redis-cli", "ping"]
45
+ interval: 30s
46
+ timeout: 3s
47
+ retries: 3
examples/ec2-setup.sh ADDED
@@ -0,0 +1,95 @@
1
+ #!/bin/bash
2
+
3
+ # EC2 Setup Script for GitHub Actions Deployment
4
+ # Run this on your EC2 instance
5
+
6
+ set -e
7
+
8
+ echo "🚀 Setting up EC2 for GitHub Actions Deployment"
9
+ echo "================================================"
10
+
11
+ # Update system
12
+ echo "📦 Updating system packages..."
13
+ sudo apt update && sudo apt upgrade -y
14
+
15
+ # Install Docker
16
+ echo "🐳 Installing Docker..."
17
+ if ! command -v docker &> /dev/null; then
18
+ curl -fsSL https://get.docker.com -o get-docker.sh
19
+ sudo sh get-docker.sh
20
+ rm get-docker.sh
21
+ echo "✅ Docker installed"
22
+ else
23
+ echo "✅ Docker already installed"
24
+ fi
25
+
26
+ # Install Docker Compose
27
+ echo "🐳 Installing Docker Compose..."
28
+ if ! command -v docker-compose &> /dev/null; then
29
+ sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
30
+ sudo chmod +x /usr/local/bin/docker-compose
31
+ echo "✅ Docker Compose installed"
32
+ else
33
+ echo "✅ Docker Compose already installed"
34
+ fi
35
+
36
+ # Create deploy user
37
+ echo "👤 Creating deploy user..."
38
+ if ! id "deploy" &>/dev/null; then
39
+ sudo adduser --disabled-password --gecos "" deploy
40
+ sudo usermod -aG docker deploy
41
+ sudo usermod -aG sudo deploy
42
+ echo "✅ Deploy user created"
43
+ else
44
+ echo "✅ Deploy user already exists"
45
+ fi
46
+
47
+ # Add current user to docker group
48
+ echo "👤 Adding $USER to docker group..."
49
+ sudo usermod -aG docker $USER
50
+
51
+ # Create app directory
52
+ echo "📁 Creating app directory..."
53
+ sudo mkdir -p /home/deploy/app
54
+ sudo chown -R deploy:deploy /home/deploy/app
55
+
56
+ # Create backups directory
57
+ echo "📁 Creating backups directory..."
58
+ sudo mkdir -p /home/deploy/backups
59
+ sudo chown -R deploy:deploy /home/deploy/backups
60
+
61
+ # Install useful tools
62
+ echo "🛠️ Installing useful tools..."
63
+ sudo apt install -y git curl wget htop ncdu
64
+
65
+ # Configure firewall
66
+ echo "🔒 Configuring firewall..."
67
+ if command -v ufw &> /dev/null; then
68
+ sudo ufw allow 22/tcp # SSH
69
+ sudo ufw allow 80/tcp # HTTP
70
+ sudo ufw allow 443/tcp # HTTPS
71
+ sudo ufw allow 8000/tcp # App port (adjust as needed)
72
+ echo "✅ Firewall configured (not enabled yet)"
73
+ echo "⚠️ To enable: sudo ufw enable"
74
+ else
75
+ echo "⚠️ UFW not installed"
76
+ fi
77
+
78
+ # Print SSH public key location
79
+ echo ""
80
+ echo "================================================"
81
+ echo "✅ EC2 Setup Complete!"
82
+ echo "================================================"
83
+ echo ""
84
+ echo "Next steps:"
85
+ echo "1. Add your GitHub Actions public key to ~/.ssh/authorized_keys"
86
+ echo "2. Test SSH connection from your local machine"
87
+ echo "3. Configure your GitHub repository secrets"
88
+ echo ""
89
+ echo "To add SSH key:"
90
+ echo " mkdir -p ~/.ssh"
91
+ echo " echo 'YOUR_PUBLIC_KEY' >> ~/.ssh/authorized_keys"
92
+ echo " chmod 600 ~/.ssh/authorized_keys"
93
+ echo " chmod 700 ~/.ssh"
94
+ echo ""
95
+ echo "Logout and login again to apply docker group changes"
@@ -0,0 +1,245 @@
1
+ name: Deploy to EC2 with vm_tool
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ workflow_dispatch:
7
+
8
+ env:
9
+ EC2_HOST: ${{ secrets.EC2_HOST }}
10
+ EC2_USER: ${{ secrets.EC2_USER }}
11
+
12
+ jobs:
13
+ deploy:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Validate Required Secrets
21
+ run: |
22
+ echo "🔐 Validating GitHub Secrets..."
23
+ MISSING_SECRETS=()
24
+
25
+ # Check EC2_HOST
26
+ if [ -z "${{ secrets.EC2_HOST }}" ]; then
27
+ MISSING_SECRETS+=("EC2_HOST")
28
+ fi
29
+
30
+ # Check EC2_USER
31
+ if [ -z "${{ secrets.EC2_USER }}" ]; then
32
+ MISSING_SECRETS+=("EC2_USER")
33
+ fi
34
+
35
+ # Check EC2_SSH_KEY
36
+ if [ -z "${{ secrets.EC2_SSH_KEY }}" ]; then
37
+ MISSING_SECRETS+=("EC2_SSH_KEY")
38
+ fi
39
+
40
+ # If any secrets are missing, show detailed instructions
41
+ if [ ${#MISSING_SECRETS[@]} -ne 0 ]; then
42
+ echo ""
43
+ echo "❌ ERROR: Missing required GitHub Secrets!"
44
+ echo ""
45
+ echo "Missing secrets: ${MISSING_SECRETS[*]}"
46
+ echo ""
47
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
48
+ echo "📝 How to add GitHub Secrets:"
49
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
50
+ echo ""
51
+ echo "1. Go to your GitHub repository"
52
+ echo "2. Click: Settings → Secrets and variables → Actions"
53
+ echo "3. Click: New repository secret"
54
+ echo "4. Add each secret:"
55
+ echo ""
56
+
57
+ if [[ " ${MISSING_SECRETS[*]} " =~ " EC2_HOST " ]]; then
58
+ echo " 📍 EC2_HOST"
59
+ echo " Value: Your EC2 instance IP address"
60
+ echo " Example: 54.123.45.67"
61
+ echo ""
62
+ fi
63
+
64
+ if [[ " ${MISSING_SECRETS[*]} " =~ " EC2_USER " ]]; then
65
+ echo " 👤 EC2_USER"
66
+ echo " Value: SSH username for your EC2 instance"
67
+ echo " Example: ubuntu (for Ubuntu) or ec2-user (for Amazon Linux)"
68
+ echo ""
69
+ fi
70
+
71
+ if [[ " ${MISSING_SECRETS[*]} " =~ " EC2_SSH_KEY " ]]; then
72
+ echo " 🔑 EC2_SSH_KEY"
73
+ echo " Value: Your SSH private key"
74
+ echo ""
75
+ echo " To get your SSH private key, run on your LOCAL machine:"
76
+ echo " $ cat ~/.ssh/id_rsa"
77
+ echo ""
78
+ echo " OR if you use ed25519:"
79
+ echo " $ cat ~/.ssh/id_ed25519"
80
+ echo ""
81
+ echo " Copy the ENTIRE output (including BEGIN and END lines)"
82
+ echo ""
83
+ echo " Don't have an SSH key? Generate one:"
84
+ echo " $ ssh-keygen -t ed25519 -C 'github-actions'"
85
+ echo " $ cat ~/.ssh/id_ed25519.pub # Add to EC2 ~/.ssh/authorized_keys"
86
+ echo " $ cat ~/.ssh/id_ed25519 # Add to GitHub Secrets"
87
+ echo ""
88
+ fi
89
+
90
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
91
+ echo "📚 For detailed instructions, see:"
92
+ echo " - docs/ec2-github-actions-guide.md"
93
+ echo " - docs/ssh-key-setup.md"
94
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
95
+ echo ""
96
+ exit 1
97
+ fi
98
+
99
+ echo "✅ All required secrets are configured"
100
+ echo " - EC2_HOST: ${{ secrets.EC2_HOST }}"
101
+ echo " - EC2_USER: ${{ secrets.EC2_USER }}"
102
+ echo " - EC2_SSH_KEY: ✓ (configured)"
103
+
104
+ - name: Set up Python
105
+ uses: actions/setup-python@v4
106
+ with:
107
+ python-version: '3.11'
108
+
109
+ - name: Install vm_tool
110
+ run: pip install vm-tool
111
+
112
+ - name: Set up SSH
113
+ run: |
114
+ mkdir -p ~/.ssh
115
+ echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/deploy_key
116
+ chmod 600 ~/.ssh/deploy_key
117
+ ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
118
+
119
+ - name: Validate SSH Connection
120
+ run: |
121
+ if [ ! -s ~/.ssh/deploy_key ]; then
122
+ echo "❌ ERROR: EC2_SSH_KEY is empty!"
123
+ echo ""
124
+ echo "📝 To get your SSH key, run on your local machine:"
125
+ echo " cat ~/.ssh/id_rsa"
126
+ echo ""
127
+ echo "Then add it to GitHub Secrets as EC2_SSH_KEY"
128
+ echo "See: docs/ssh-key-setup.md for detailed instructions"
129
+ exit 1
130
+ fi
131
+
132
+ echo "✅ Testing SSH connection..."
133
+ ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no \
134
+ ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} "echo 'Connection successful'" || {
135
+ echo "❌ SSH connection failed!"
136
+ echo "Check: docs/ssh-key-setup.md for troubleshooting"
137
+ exit 1
138
+ }
139
+
140
+ - name: Copy project files to EC2
141
+ run: |
142
+ # Create app directory if it doesn't exist
143
+ ssh -i ~/.ssh/deploy_key ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} \
144
+ 'mkdir -p ~/app'
145
+
146
+ # Copy docker-compose and related files
147
+ scp -i ~/.ssh/deploy_key docker-compose.yml \
148
+ ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }}:~/app/
149
+
150
+ # Copy application code
151
+ rsync -avz -e "ssh -i ~/.ssh/deploy_key" \
152
+ --exclude '.git' \
153
+ --exclude 'node_modules' \
154
+ --exclude '.env' \
155
+ ./ ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }}:~/app/
156
+
157
+ - name: Create backup before deployment
158
+ run: |
159
+ ssh -i ~/.ssh/deploy_key ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF'
160
+ mkdir -p ~/backups
161
+ BACKUP_FILE=~/backups/backup-$(date +%Y%m%d-%H%M%S).tar.gz
162
+ if [ -d ~/app ]; then
163
+ cd ~/app && tar -czf $BACKUP_FILE . || true
164
+ echo "Backup created: $BACKUP_FILE"
165
+ fi
166
+ EOF
167
+
168
+ - name: Deploy with Docker Compose
169
+ run: |
170
+ ssh -i ~/.ssh/deploy_key ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF'
171
+ cd ~/app
172
+
173
+ # Pull latest images
174
+ docker-compose pull
175
+
176
+ # Stop old containers
177
+ docker-compose down
178
+
179
+ # Start new containers
180
+ docker-compose up -d --build
181
+
182
+ # Wait for services to start
183
+ sleep 10
184
+ EOF
185
+
186
+ - name: Health check
187
+ run: |
188
+ # Wait for application to be ready
189
+ for i in {1..30}; do
190
+ if curl -f http://${{ secrets.EC2_HOST }}:8000/health 2>/dev/null; then
191
+ echo "✅ Health check passed"
192
+ exit 0
193
+ fi
194
+ echo "Waiting for application... ($i/30)"
195
+ sleep 2
196
+ done
197
+ echo "❌ Health check failed"
198
+ exit 1
199
+
200
+ - name: Verify deployment
201
+ run: |
202
+ ssh -i ~/.ssh/deploy_key ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF'
203
+ cd ~/app
204
+ echo "📊 Container status:"
205
+ docker-compose ps
206
+ echo ""
207
+ echo "📝 Recent logs:"
208
+ docker-compose logs --tail=50
209
+ EOF
210
+
211
+ - name: Rollback on failure
212
+ if: failure()
213
+ run: |
214
+ echo "⚠️ Deployment failed, attempting rollback..."
215
+ ssh -i ~/.ssh/deploy_key ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF'
216
+ cd ~/app
217
+ LATEST_BACKUP=$(ls -t ~/backups/*.tar.gz 2>/dev/null | head -1)
218
+ if [ -n "$LATEST_BACKUP" ]; then
219
+ echo "Rolling back to: $LATEST_BACKUP"
220
+ tar -xzf $LATEST_BACKUP
221
+ docker-compose up -d
222
+ echo "✅ Rollback complete"
223
+ else
224
+ echo "❌ No backup found for rollback"
225
+ fi
226
+ EOF
227
+
228
+ - name: Cleanup old backups
229
+ if: success()
230
+ run: |
231
+ ssh -i ~/.ssh/deploy_key ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF'
232
+ # Keep only last 5 backups
233
+ cd ~/backups
234
+ ls -t *.tar.gz 2>/dev/null | tail -n +6 | xargs rm -f || true
235
+ echo "✅ Cleanup complete"
236
+ EOF
237
+
238
+ - name: Send notification
239
+ if: always()
240
+ run: |
241
+ if [ "${{ job.status }}" == "success" ]; then
242
+ echo "✅ Deployment successful to ${{ secrets.EC2_HOST }}"
243
+ else
244
+ echo "❌ Deployment failed to ${{ secrets.EC2_HOST }}"
245
+ fi
@@ -0,0 +1,58 @@
1
+ name: Full VM Setup and Deploy
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v4
18
+ with:
19
+ python-version: '3.11'
20
+
21
+ - name: Install vm_tool
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install vm-tool
25
+
26
+ - name: Create SSH identity file
27
+ run: |
28
+ mkdir -p ~/.ssh
29
+ echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/id_rsa
30
+ chmod 600 ~/.ssh/id_rsa
31
+ ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
32
+
33
+ - name: Full VM Setup and Deploy
34
+ env:
35
+ GITHUB_USERNAME: ${{ secrets.GITHUB_USERNAME }}
36
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
+ GITHUB_PROJECT_URL: ${{ github.server_url }}/${{ github.repository }}
38
+ GITHUB_BRANCH: ${{ github.ref_name }}
39
+ DOCKER_COMPOSE_FILE: docker-compose.prod.yml
40
+ DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
41
+ DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
42
+ EC2_USER: ${{ secrets.EC2_USER }}
43
+ EC2_HOST: ${{ secrets.EC2_HOST }}
44
+ SSH_IDENTITY_FILE: ~/.ssh/id_rsa
45
+ run: python scripts/deploy_to_vm.py
46
+
47
+ - name: Clean up SSH identity file
48
+ if: always()
49
+ run: rm -f ~/.ssh/id_rsa
50
+
51
+ - name: Notify
52
+ if: always()
53
+ run: |
54
+ if [ "${{ job.status }}" == "success" ]; then
55
+ echo "✅ Full setup and deployment successful!"
56
+ else
57
+ echo "❌ Deployment failed"
58
+ fi
examples/local/.keep ADDED
@@ -0,0 +1 @@
1
+ # Keep this directory for local examples and templates.
@@ -0,0 +1,3 @@
1
+ # Local Examples
2
+
3
+ Use `template_local_setup.py` as your starting point for any local VM setup scenario. Other files are legacy or specific examples and can be removed if you only want the template.
@@ -0,0 +1 @@
1
+ # Local VM setup examples package
@@ -0,0 +1,27 @@
1
+ """
2
+ Template: Local VM setup (customize for your use case)
3
+ - Use this template to create your own local VM setup script.
4
+ - Supports public/private GitHub, DockerHub, and custom Docker Compose file path.
5
+ - Fill in only the fields you need for your scenario.
6
+ """
7
+
8
+ from vm_tool.runner import SetupRunner, SetupRunnerConfig
9
+
10
+
11
+ def main():
12
+ # Fill in only the fields you need for your use case
13
+ config = SetupRunnerConfig(
14
+ github_username=None, # e.g., 'your_github_username' (for private repos)
15
+ github_token=None, # e.g., 'your_github_token' (for private repos)
16
+ github_project_url="https://github.com/username/your-repo",
17
+ github_branch="main", # Optional, defaults to 'main'
18
+ docker_compose_file_path="docker-compose.yml", # Optional
19
+ dockerhub_username=None, # e.g., 'your_dockerhub_username' (if DockerHub login needed)
20
+ dockerhub_password=None, # e.g., 'your_dockerhub_password' (if DockerHub login needed)
21
+ )
22
+ runner = SetupRunner(config)
23
+ runner.run_setup()
24
+
25
+
26
+ if __name__ == "__main__":
27
+ main()