vagrant-ssh-config-manager 0.8.3 → 1.0.0.alpha
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.
- checksums.yaml +4 -4
- data/.bundle/config +1 -1
- data/.gitignore +2 -1
- data/.rspec +2 -0
- data/.rubocop.yml +62 -0
- data/Gemfile +11 -9
- data/README.md +2 -2
- data/Rakefile +10 -8
- data/TESTING.md +82 -0
- data/lib/vagrant/ssh/config/manager.rb +5 -0
- data/lib/vagrant_ssh_config_manager/action/destroy.rb +82 -0
- data/lib/vagrant_ssh_config_manager/action/halt.rb +66 -0
- data/lib/vagrant_ssh_config_manager/action/provision.rb +81 -0
- data/lib/vagrant_ssh_config_manager/action/reload.rb +105 -0
- data/lib/vagrant_ssh_config_manager/action/up.rb +98 -0
- data/lib/{vagrant-ssh-config-manager → vagrant_ssh_config_manager}/config.rb +45 -49
- data/lib/{vagrant-ssh-config-manager → vagrant_ssh_config_manager}/file_locker.rb +35 -37
- data/lib/{vagrant-ssh-config-manager → vagrant_ssh_config_manager}/file_manager.rb +90 -80
- data/lib/{vagrant-ssh-config-manager → vagrant_ssh_config_manager}/include_manager.rb +54 -53
- data/lib/{vagrant-ssh-config-manager → vagrant_ssh_config_manager}/plugin.rb +15 -13
- data/lib/vagrant_ssh_config_manager/ssh_config_manager.rb +1152 -0
- data/lib/{vagrant-ssh-config-manager → vagrant_ssh_config_manager}/ssh_info_extractor.rb +129 -141
- data/lib/vagrant_ssh_config_manager/version.rb +7 -0
- data/lib/{vagrant-ssh-config-manager.rb → vagrant_ssh_config_manager.rb} +15 -12
- data/test-all.sh +11 -0
- data/test-integration.sh +4 -0
- data/test-unit.sh +4 -0
- data/vagrant-ssh-config-manager.gemspec +25 -21
- metadata +28 -18
- data/lib/vagrant-ssh-config-manager/action/destroy.rb +0 -84
- data/lib/vagrant-ssh-config-manager/action/halt.rb +0 -68
- data/lib/vagrant-ssh-config-manager/action/provision.rb +0 -82
- data/lib/vagrant-ssh-config-manager/action/reload.rb +0 -106
- data/lib/vagrant-ssh-config-manager/action/up.rb +0 -99
- data/lib/vagrant-ssh-config-manager/ssh_config_manager.rb +0 -2150
- data/lib/vagrant-ssh-config-manager/version.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47f9a813e321f5ad9c85a343e9caf8d1fff7c220e91e5276f54ce306677d0264
|
4
|
+
data.tar.gz: 92261bf77ca112add8fe96b3c35c613ea7bc461022008b75a9aff879c5a146a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6807f6309de0a625b8773a98c696a9e40e6b74465a009f1b2fa57d355cfc6007cab440ff468e98590fa84e6aaca5bc3bce3dc65ad9219e432620370640dfa60a
|
7
|
+
data.tar.gz: bb1dc4515944ae88da5a621a8e48d87ca16c9ef60c5a2ee717f3c6eaef64bbc6dded204d90d006d79808473a02d4971cfbe380e67d2d81e7fbbcbc6d5d441295
|
data/.bundle/config
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
BUNDLE_PATH: "vendor/bundle"
|
2
|
+
BUNDLE_PATH: "/home/runner/work/vagrant-ssh-config-manager/vagrant-ssh-config-manager/vendor/bundle"
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Custom RuboCop configuration for vagrant-ssh-config-manager
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
NewCops: enable
|
5
|
+
|
6
|
+
# Disable metrics and complexity cops for large methods/classes
|
7
|
+
Metrics/BlockLength:
|
8
|
+
Enabled: false
|
9
|
+
Metrics/MethodLength:
|
10
|
+
Enabled: false
|
11
|
+
Metrics/AbcSize:
|
12
|
+
Enabled: false
|
13
|
+
Metrics/CyclomaticComplexity:
|
14
|
+
Enabled: false
|
15
|
+
Metrics/PerceivedComplexity:
|
16
|
+
Enabled: false
|
17
|
+
Metrics/ClassLength:
|
18
|
+
Enabled: false
|
19
|
+
Metrics/BlockNesting:
|
20
|
+
Enabled: false
|
21
|
+
Layout/LineLength:
|
22
|
+
Enabled: false
|
23
|
+
Max: 120
|
24
|
+
|
25
|
+
# Disable accessor naming cop for spec files (get_ prefix methods allowed in tests)
|
26
|
+
Naming/AccessorMethodName:
|
27
|
+
Enabled: true
|
28
|
+
Exclude:
|
29
|
+
- 'spec/**/*'
|
30
|
+
|
31
|
+
# Require documentation comments on public classes/modules
|
32
|
+
Style/Documentation:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
# Ensure super is called in initializers
|
36
|
+
Lint/MissingSuper:
|
37
|
+
Enabled: true
|
38
|
+
|
39
|
+
# Disable single-line modifier offenses for now
|
40
|
+
Style/IfUnlessModifier:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
# Disable constant scoping and access modifier false positives
|
44
|
+
Lint/UselessConstantScoping:
|
45
|
+
Enabled: false
|
46
|
+
Lint/UselessAccessModifier:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
# Disable staffing of gemspec checks
|
50
|
+
Gemspec/RequireMFA:
|
51
|
+
Enabled: false
|
52
|
+
Gemspec/DevelopmentDependencies:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
# Spec-specific configurations - allow more flexible patterns in tests
|
56
|
+
Lint/NoReturnInBeginEndBlocks:
|
57
|
+
Exclude:
|
58
|
+
- 'spec/**/*'
|
59
|
+
|
60
|
+
Naming/PredicateMethod:
|
61
|
+
Exclude:
|
62
|
+
- 'spec/**/*'
|
data/Gemfile
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
# Specify your gem's dependencies in vagrant-ssh-config-manager.gemspec
|
4
6
|
gemspec
|
5
7
|
|
6
8
|
group :development, :test do
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
10
|
-
gem
|
11
|
-
gem
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem
|
9
|
+
gem 'bundler', '~> 2.0'
|
10
|
+
gem 'rake', '~> 13.0'
|
11
|
+
gem 'rspec', '~> 3.0'
|
12
|
+
gem 'rspec-mocks', '~> 3.0'
|
13
|
+
gem 'rubocop', '~> 1.0'
|
14
|
+
gem 'rubocop-rspec', '~> 2.0'
|
15
|
+
gem 'simplecov', '~> 0.21'
|
16
|
+
gem 'vagrant', git: 'https://github.com/hashicorp/vagrant.git', tag: 'v2.4.1'
|
15
17
|
end
|
data/README.md
CHANGED
@@ -25,7 +25,7 @@ vagrant plugin install vagrant-ssh-config-manager
|
|
25
25
|
### Install from Source
|
26
26
|
|
27
27
|
```bash
|
28
|
-
git clone https://github.com/
|
28
|
+
git clone https://github.com/marekruzicka/vagrant-ssh-config-manager.git
|
29
29
|
cd vagrant-ssh-config-manager
|
30
30
|
gem build vagrant-ssh-config-manager.gemspec
|
31
31
|
vagrant plugin install vagrant-ssh-config-manager-*.gem
|
@@ -258,7 +258,7 @@ sed -i '/# BEGIN vagrant-ssh-config-manager/,/# END vagrant-ssh-config-manager/d
|
|
258
258
|
## Compatibility
|
259
259
|
|
260
260
|
- **Vagrant**: 2.0+
|
261
|
-
- **Ruby**:
|
261
|
+
- **Ruby**: 3.0+
|
262
262
|
- **Platforms**: Linux, macOS, Windows (with WSL)
|
263
263
|
- **Providers**: VirtualBox, VMware, Libvirt, Hyper-V, Docker, AWS, and others
|
264
264
|
|
data/Rakefile
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
3
5
|
|
4
6
|
RSpec::Core::RakeTask.new(:spec)
|
5
7
|
|
6
|
-
task :
|
8
|
+
task default: :spec
|
7
9
|
|
8
|
-
desc
|
10
|
+
desc 'Run RuboCop'
|
9
11
|
task :rubocop do
|
10
|
-
sh
|
12
|
+
sh 'bundle exec rubocop'
|
11
13
|
end
|
12
14
|
|
13
|
-
desc
|
15
|
+
desc 'Run RuboCop with auto-correct'
|
14
16
|
task :rubocop_fix do
|
15
|
-
sh
|
17
|
+
sh 'bundle exec rubocop -a'
|
16
18
|
end
|
17
19
|
|
18
|
-
desc
|
20
|
+
desc 'Run tests with coverage'
|
19
21
|
task :coverage do
|
20
22
|
ENV['COVERAGE'] = 'true'
|
21
23
|
Rake::Task[:spec].invoke
|
data/TESTING.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Hybrid Testing for vagrant-ssh-config-manager
|
2
|
+
|
3
|
+
This project uses a **hybrid testing approach** that combines fast unit tests with comprehensive integration tests.
|
4
|
+
|
5
|
+
## 🚀 Quick Start
|
6
|
+
|
7
|
+
```bash
|
8
|
+
# Run unit tests (fast, recommended for development)
|
9
|
+
bundle exec rspec spec/unit/
|
10
|
+
|
11
|
+
# Run integration tests (real APIs)
|
12
|
+
bundle exec rspec spec/integration/
|
13
|
+
|
14
|
+
# Run both test suites
|
15
|
+
./test-all.sh
|
16
|
+
|
17
|
+
# Helper scripts for detailed output:
|
18
|
+
./test-unit.sh # Unit tests with documentation format
|
19
|
+
./test-integration.sh # Integration tests with documentation format
|
20
|
+
./test-all.sh # Both suites with progress format
|
21
|
+
```
|
22
|
+
|
23
|
+
## 📁 Test Structure
|
24
|
+
|
25
|
+
```
|
26
|
+
spec/
|
27
|
+
├── unit_helper.rb # Minimal setup for unit tests
|
28
|
+
├── integration_helper.rb # Real Vagrant setup for integration tests
|
29
|
+
├── unit/ # Fast, isolated unit tests
|
30
|
+
│ ├── config_spec.rb # ✅ Config class (32 examples)
|
31
|
+
│ ├── file_locker_spec.rb # ✅ FileLocker class (27 examples)
|
32
|
+
│ ├── file_manager_spec.rb # ✅ FileManager class (39 examples)
|
33
|
+
│ └── ssh_config_manager_spec.rb # ✅ SshConfigManager class (43 examples)
|
34
|
+
└── integration/ # Real API integration tests
|
35
|
+
└── include_manager_spec.rb # ✅ IncludeManager (14 examples)
|
36
|
+
```
|
37
|
+
|
38
|
+
## ✅ Current Test Status
|
39
|
+
|
40
|
+
- **Unit Tests**: 141 examples, 0 failures (~0.23s)
|
41
|
+
- **Integration Tests**: 14 examples, 0 failures (~0.02s)
|
42
|
+
- **Total**: **155 examples, 0 failures** (100% pass rate)
|
43
|
+
- **Combined Runtime**: ~0.25 seconds (extremely fast!)
|
44
|
+
|
45
|
+
## 🚀 Performance Metrics
|
46
|
+
|
47
|
+
```bash
|
48
|
+
$ ./test-all.sh
|
49
|
+
📦 Unit Tests: 141 examples, 0 failures (0.23s)
|
50
|
+
🔗 Integration Tests: 14 examples, 0 failures (0.02s)
|
51
|
+
✅ Total: 155 examples, 0 failures
|
52
|
+
```
|
53
|
+
|
54
|
+
## 🔧 Test Types
|
55
|
+
|
56
|
+
### Unit Tests (spec/unit/)
|
57
|
+
- **Purpose**: Fast feedback, isolated component testing
|
58
|
+
- **Setup**: Mocked dependencies, no real Vagrant loading
|
59
|
+
- **Speed**: ~0.23 seconds for 141 tests
|
60
|
+
- **Coverage**:
|
61
|
+
- Config validation and setup (32 examples)
|
62
|
+
- FileLocker concurrency and thread safety (27 examples)
|
63
|
+
- FileManager SSH file operations (39 examples)
|
64
|
+
- SshConfigManager entry management (43 examples)
|
65
|
+
|
66
|
+
### Integration Tests (spec/integration/)
|
67
|
+
- **Purpose**: Real API verification, end-to-end testing
|
68
|
+
- **Setup**: Real Vagrant APIs, isolated file system environments
|
69
|
+
- **Speed**: ~0.02 seconds for 14 tests
|
70
|
+
- **Coverage**: IncludeManager SSH config manipulation, plugin markers
|
71
|
+
|
72
|
+
## 🛠 Helper Scripts
|
73
|
+
|
74
|
+
- `./test-unit.sh` - Run only unit tests with detailed output
|
75
|
+
- `./test-integration.sh` - Run only integration tests with detailed output
|
76
|
+
- `./test-all.sh` - Run both test suites with summary
|
77
|
+
|
78
|
+
### 🎯 Test Strategy
|
79
|
+
- **Unit Tests**: Mock all external dependencies for speed and isolation
|
80
|
+
- **Integration Tests**: Use real Vagrant APIs with controlled environments
|
81
|
+
- **Comprehensive Coverage**: Every major component and method tested
|
82
|
+
- **Error Scenarios**: Both success and failure paths covered
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module SshConfigManager
|
5
|
+
module Action
|
6
|
+
# Handles SSH config cleanup when a Vagrant machine is destroyed
|
7
|
+
class Destroy
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@env = env
|
11
|
+
@logger = Log4r::Logger.new('vagrant::plugins::ssh_config_manager::action::destroy')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
machine = env[:machine]
|
16
|
+
|
17
|
+
# Handle SSH config removal before destroying the machine
|
18
|
+
if machine
|
19
|
+
config = machine.config.sshconfigmanager
|
20
|
+
handle_ssh_config_removal(machine, config) if config&.enabled && config.auto_remove_on_destroy
|
21
|
+
end
|
22
|
+
|
23
|
+
# Call the next middleware (actual destroy)
|
24
|
+
@app.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def handle_ssh_config_removal(machine, config)
|
30
|
+
@logger.info("Removing SSH config file for machine: #{machine.name}")
|
31
|
+
|
32
|
+
# Lazy load required classes with error handling
|
33
|
+
begin
|
34
|
+
require 'vagrant_ssh_config_manager/file_manager'
|
35
|
+
require 'vagrant_ssh_config_manager/include_manager'
|
36
|
+
rescue LoadError => e
|
37
|
+
@logger.error("Failed to load required classes: #{e.message}")
|
38
|
+
machine.ui.warn('SSH config manager: Failed to load required components, skipping SSH config removal')
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create file manager and include manager
|
43
|
+
file_manager = FileManager.new(config)
|
44
|
+
include_manager = IncludeManager.new(config)
|
45
|
+
|
46
|
+
# Check if SSH config file exists
|
47
|
+
unless file_manager.ssh_config_file_exists?(machine)
|
48
|
+
@logger.debug("No SSH config file found for machine: #{machine.name}")
|
49
|
+
machine.ui.info("No SSH config file found to remove for machine: #{machine.name}")
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
# Remove SSH config file with logging
|
54
|
+
@logger.info("Attempting to remove SSH config file for #{machine.name}")
|
55
|
+
|
56
|
+
if file_manager.remove_ssh_config_file(machine)
|
57
|
+
machine.ui.info("SSH config file removed for machine '#{machine.name}'")
|
58
|
+
@logger.info("Successfully removed SSH config file for #{machine.name}")
|
59
|
+
|
60
|
+
# Manage Include directive after file removal
|
61
|
+
include_manager.manage_include_directive
|
62
|
+
else
|
63
|
+
machine.ui.warn("Failed to remove SSH config file for machine: #{machine.name}")
|
64
|
+
@logger.warn("Failed to remove SSH config file for #{machine.name}")
|
65
|
+
end
|
66
|
+
rescue Errno::EACCES => e
|
67
|
+
@logger.error("Permission denied accessing SSH config for #{machine.name}: #{e.message}")
|
68
|
+
machine.ui.warn('SSH config manager: Permission denied. Check file permissions.')
|
69
|
+
rescue Errno::EIO => e
|
70
|
+
@logger.error("I/O error for #{machine.name}: #{e.message}")
|
71
|
+
machine.ui.warn('SSH config manager: I/O error accessing SSH config files.')
|
72
|
+
rescue StandardError => e
|
73
|
+
@logger.error("Error removing SSH config for #{machine.name}: #{e.message}")
|
74
|
+
@logger.debug("Backtrace: #{e.backtrace.join("\n")}")
|
75
|
+
|
76
|
+
# Don't fail the vagrant destroy process, just warn
|
77
|
+
machine.ui.warn("SSH config manager encountered an error during cleanup: #{e.message}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module SshConfigManager
|
5
|
+
module Action
|
6
|
+
# Handles SSH config update when a Vagrant machine is halted or suspended
|
7
|
+
class Halt
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@env = env
|
11
|
+
@logger = Log4r::Logger.new('vagrant::plugins::ssh_config_manager::action::halt')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
machine = env[:machine]
|
16
|
+
|
17
|
+
# Handle SSH config for halt/suspend operations
|
18
|
+
if machine
|
19
|
+
config = machine.config.sshconfigmanager
|
20
|
+
handle_ssh_config_for_halt(machine, config, env) if config&.enabled && config.keep_config_on_halt
|
21
|
+
end
|
22
|
+
|
23
|
+
# Call the next middleware (actual halt/suspend)
|
24
|
+
@app.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def handle_ssh_config_for_halt(machine, _config, env)
|
30
|
+
# Determine the type of operation
|
31
|
+
operation = determine_operation_type(env)
|
32
|
+
@logger.info("Handling SSH config for #{operation} operation on machine: #{machine.name}")
|
33
|
+
|
34
|
+
# With separate files, we keep the SSH config file during halt/suspend
|
35
|
+
# This allows users to quickly resume and reconnect
|
36
|
+
case operation
|
37
|
+
when :halt, :suspend, :poweroff, :force_halt
|
38
|
+
machine.ui.info("Machine #{operation}ed - SSH config file retained")
|
39
|
+
@logger.debug("Keeping SSH config file for #{operation}ed machine: #{machine.name}")
|
40
|
+
else
|
41
|
+
@logger.debug("No SSH config action needed for operation: #{operation}")
|
42
|
+
end
|
43
|
+
rescue StandardError => e
|
44
|
+
@logger.error("Error handling SSH config for halt/suspend #{machine.name}: #{e.message}")
|
45
|
+
@logger.debug("Backtrace: #{e.backtrace.join("\n")}")
|
46
|
+
|
47
|
+
# Don't fail the halt/suspend process
|
48
|
+
machine.ui.warn("SSH config manager encountered an error: #{e.message}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def determine_operation_type(env)
|
52
|
+
# Try to determine what type of halt operation this is
|
53
|
+
if env[:force_halt]
|
54
|
+
:force_halt
|
55
|
+
elsif env[:suspend]
|
56
|
+
:suspend
|
57
|
+
elsif env[:graceful_halt] == false
|
58
|
+
:poweroff
|
59
|
+
else
|
60
|
+
:halt
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module SshConfigManager
|
5
|
+
module Action
|
6
|
+
class Provision
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@env = env
|
10
|
+
@logger = Log4r::Logger.new('vagrant::plugins::ssh_config_manager::action::provision')
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
# Call the next middleware first (actual provisioning)
|
15
|
+
@app.call(env)
|
16
|
+
|
17
|
+
# Only proceed if the machine is running and SSH is ready
|
18
|
+
machine = env[:machine]
|
19
|
+
return unless machine && machine.state.id == :running
|
20
|
+
|
21
|
+
# Check if plugin is enabled
|
22
|
+
config = machine.config.sshconfigmanager
|
23
|
+
return unless config&.enabled && config.refresh_on_provision
|
24
|
+
|
25
|
+
# Handle SSH config file refresh after provisioning
|
26
|
+
handle_ssh_config_refresh(machine, config)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def handle_ssh_config_refresh(machine, config)
|
32
|
+
@logger.info("Refreshing SSH config file after provisioning for machine: #{machine.name}")
|
33
|
+
|
34
|
+
# Lazy load required classes with error handling
|
35
|
+
begin
|
36
|
+
require 'vagrant_ssh_config_manager/ssh_info_extractor'
|
37
|
+
require 'vagrant_ssh_config_manager/file_manager'
|
38
|
+
require 'vagrant_ssh_config_manager/include_manager'
|
39
|
+
rescue LoadError => e
|
40
|
+
@logger.error("Failed to load required classes: #{e.message}")
|
41
|
+
machine.ui.warn('SSH config manager: Failed to load required components, skipping SSH config refresh')
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
# Extract SSH information
|
46
|
+
extractor = SshInfoExtractor.new(machine)
|
47
|
+
|
48
|
+
# Check if machine supports SSH
|
49
|
+
unless extractor.ssh_capable?
|
50
|
+
@logger.debug("Machine #{machine.name} does not support SSH, skipping")
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
# Create file manager and include manager
|
55
|
+
file_manager = FileManager.new(config)
|
56
|
+
include_manager = IncludeManager.new(config)
|
57
|
+
|
58
|
+
# Refresh SSH config file (regenerate it)
|
59
|
+
# Provisioning might have changed SSH configuration
|
60
|
+
if file_manager.write_ssh_config_file(machine)
|
61
|
+
file_manager.send(:generate_host_name, machine)
|
62
|
+
machine.ui.info("SSH config file refreshed for machine '#{machine.name}' after provisioning")
|
63
|
+
@logger.info('SSH config file refreshed due to provisioning')
|
64
|
+
|
65
|
+
# Ensure Include directive is managed
|
66
|
+
include_manager.manage_include_directive
|
67
|
+
else
|
68
|
+
machine.ui.warn("Failed to refresh SSH config file for machine: #{machine.name}")
|
69
|
+
@logger.warn("Failed to refresh SSH config file for #{machine.name}")
|
70
|
+
end
|
71
|
+
rescue StandardError => e
|
72
|
+
@logger.error("Error refreshing SSH config for #{machine.name}: #{e.message}")
|
73
|
+
@logger.debug("Backtrace: #{e.backtrace.join("\n")}")
|
74
|
+
|
75
|
+
# Don't fail the vagrant provision process, just warn
|
76
|
+
machine.ui.warn("SSH config manager encountered an error during refresh: #{e.message}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module SshConfigManager
|
5
|
+
module Action
|
6
|
+
class Reload
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@env = env
|
10
|
+
@logger = Log4r::Logger.new('vagrant::plugins::ssh_config_manager::action::reload')
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
# Call the next middleware first
|
15
|
+
@app.call(env)
|
16
|
+
|
17
|
+
# Only proceed if the machine is running and SSH is ready
|
18
|
+
machine = env[:machine]
|
19
|
+
return unless machine && machine.state.id == :running
|
20
|
+
|
21
|
+
# Check if plugin is enabled
|
22
|
+
config = machine.config.sshconfigmanager
|
23
|
+
return unless config&.enabled
|
24
|
+
|
25
|
+
# Handle SSH config update
|
26
|
+
handle_ssh_config_update(machine, config)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def handle_ssh_config_update(machine, config)
|
32
|
+
@logger.info("Updating SSH config entry for machine: #{machine.name}")
|
33
|
+
|
34
|
+
# Lazy load required classes with error handling
|
35
|
+
begin
|
36
|
+
require 'vagrant_ssh_config_manager/ssh_info_extractor'
|
37
|
+
require 'vagrant_ssh_config_manager/file_manager'
|
38
|
+
require 'vagrant_ssh_config_manager/include_manager'
|
39
|
+
rescue LoadError => e
|
40
|
+
@logger.error("Failed to load required classes: #{e.message}")
|
41
|
+
machine.ui.warn('SSH config manager: Failed to load required components, skipping SSH config update')
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
# Extract SSH information
|
46
|
+
extractor = SshInfoExtractor.new(machine)
|
47
|
+
|
48
|
+
# Check if machine supports SSH
|
49
|
+
unless extractor.ssh_capable?
|
50
|
+
@logger.debug("Machine #{machine.name} does not support SSH, skipping")
|
51
|
+
machine.ui.info("Machine #{machine.name} does not support SSH, skipping SSH config update")
|
52
|
+
return
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create file manager and include manager
|
56
|
+
file_manager = FileManager.new(config)
|
57
|
+
include_manager = IncludeManager.new(config)
|
58
|
+
|
59
|
+
# Check if file exists and compare content
|
60
|
+
if file_manager.ssh_config_file_exists?(machine)
|
61
|
+
# Update SSH config file (always regenerate for simplicity)
|
62
|
+
@logger.info("SSH config file exists, updating for #{machine.name}")
|
63
|
+
if file_manager.write_ssh_config_file(machine)
|
64
|
+
host_name = file_manager.send(:generate_host_name, machine)
|
65
|
+
machine.ui.info("SSH config file updated for machine '#{machine.name}' (#{host_name})")
|
66
|
+
@logger.info('SSH config file updated due to reload')
|
67
|
+
|
68
|
+
# Ensure Include directive is managed
|
69
|
+
include_manager.manage_include_directive
|
70
|
+
else
|
71
|
+
machine.ui.warn("Failed to update SSH config file for machine: #{machine.name}")
|
72
|
+
@logger.warn("Failed to update SSH config file for #{machine.name}")
|
73
|
+
end
|
74
|
+
else
|
75
|
+
# Add new SSH config file (machine might have been added during reload)
|
76
|
+
@logger.info("No existing SSH config file found, creating new file for #{machine.name}")
|
77
|
+
if file_manager.write_ssh_config_file(machine)
|
78
|
+
host_name = file_manager.send(:generate_host_name, machine)
|
79
|
+
machine.ui.info("SSH config file created for machine '#{machine.name}' as '#{host_name}'")
|
80
|
+
@logger.info("Successfully created new SSH config file for #{machine.name}")
|
81
|
+
|
82
|
+
# Manage Include directive after file creation
|
83
|
+
include_manager.manage_include_directive
|
84
|
+
else
|
85
|
+
machine.ui.warn("Failed to create SSH config file for machine: #{machine.name}")
|
86
|
+
@logger.warn("Failed to create SSH config file for #{machine.name}")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
rescue Errno::EACCES => e
|
90
|
+
@logger.error("Permission denied accessing SSH config for #{machine.name}: #{e.message}")
|
91
|
+
machine.ui.warn('SSH config manager: Permission denied. Check file permissions.')
|
92
|
+
rescue Errno::EIO => e
|
93
|
+
@logger.error("I/O error for #{machine.name}: #{e.message}")
|
94
|
+
machine.ui.warn('SSH config manager: I/O error accessing SSH config files.')
|
95
|
+
rescue StandardError => e
|
96
|
+
@logger.error("Error updating SSH config for #{machine.name}: #{e.message}")
|
97
|
+
@logger.debug("Backtrace: #{e.backtrace.join("\n")}")
|
98
|
+
|
99
|
+
# Don't fail the vagrant reload process, just warn
|
100
|
+
machine.ui.warn("SSH config manager encountered an error: #{e.message}")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|