Class: VagrantPlugins::SshConfigManager::FileManager

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant-ssh-config-manager/file_manager.rb

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ FileManager

Initialize FileManager with configuration



10
11
12
13
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 10

def initialize(config)
  @config = config
  @logger = Log4r::Logger.new("vagrant::plugins::sshconfigmanager::filemanager")
end

Instance Method Details

#cleanup_orphaned_filesObject

Detect and clean up orphaned SSH config files



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 120

def cleanup_orphaned_files
  return unless Dir.exist?(@config.ssh_config_dir)

  orphaned_files = []
  config_files = Dir.glob(File.join(@config.ssh_config_dir, "*.conf"))

  config_files.each do |file_path|
    filename = File.basename(file_path, ".conf")
    
    # Parse filename to extract project hash and VM name
    if filename.match(/^([a-f0-9]{8})-(.+)$/)
      project_hash = $1
      vm_name = $2
      
      # Check if this looks like an orphaned file
      # (This is a basic heuristic - in practice, you might want more sophisticated detection)
      file_age = Time.now - File.mtime(file_path)
      
      # Consider files older than 30 days as potentially orphaned
      if file_age > (30 * 24 * 60 * 60) # 30 days in seconds
        orphaned_files << {
          path: file_path,
          project_hash: project_hash,
          vm_name: vm_name,
          age_days: (file_age / (24 * 60 * 60)).round
        }
      end
    end
  end

  # Log detected orphaned files
  unless orphaned_files.empty?
    @logger.info("Detected #{orphaned_files.length} potentially orphaned SSH config files")
    orphaned_files.each do |file_info|
      @logger.debug("Orphaned file: #{file_info[:path]} (#{file_info[:age_days]} days old)")
    end
  end

  orphaned_files
end

#generate_filename(machine) ⇒ Object

Generate unique filename for VM SSH config Format: project_hash-vm_name.conf



17
18
19
20
21
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 17

def generate_filename(machine)
  project_hash = generate_project_hash(machine.env.root_path.to_s)
  vm_name = machine.name.to_s
  "#{project_hash}-#{vm_name}.conf"
end

#generate_ssh_config_content(machine) ⇒ Object

Generate SSH config content for a VM



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 30

def generate_ssh_config_content(machine)
  ssh_info = machine.ssh_info
  return nil unless ssh_info

  content = []
  content << "# Managed by vagrant-ssh-config-manager plugin"
  content << "# Project: #{File.basename(machine.env.root_path)}"
  content << "# VM: #{machine.name}"
  content << "# Generated: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
  content << ""
  
  host_name = generate_host_name(machine)
  content << "Host #{host_name}"
  content << "  HostName #{ssh_info[:host]}"
  content << "  Port #{ssh_info[:port]}"
  content << "  User #{ssh_info[:username]}"
  
  if ssh_info[:private_key_path] && ssh_info[:private_key_path].first
    content << "  IdentityFile #{ssh_info[:private_key_path].first}"
    content << "  IdentitiesOnly yes"
  end
  
  content << "  UserKnownHostsFile /dev/null"
  content << "  StrictHostKeyChecking no"
  content << "  PasswordAuthentication no"
  content << "  LogLevel FATAL"
  content << ""

  content.join("\n")
end

#get_all_config_filesObject

Get all config files in the directory



183
184
185
186
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 183

def get_all_config_files
  return [] unless Dir.exist?(@config.ssh_config_dir)
  Dir.glob(File.join(@config.ssh_config_dir, "*.conf"))
end

#get_file_path(machine) ⇒ Object

Get full path for VM SSH config file



24
25
26
27
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 24

def get_file_path(machine)
  filename = generate_filename(machine)
  File.join(@config.ssh_config_dir, filename)
end

#remove_orphaned_filesObject

Remove orphaned SSH config files



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 162

def remove_orphaned_files
  orphaned_files = cleanup_orphaned_files
  removed_count = 0

  orphaned_files.each do |file_info|
    begin
      File.delete(file_info[:path])
      @logger.info("Removed orphaned SSH config file: #{file_info[:path]}")
      removed_count += 1
    rescue => e
      @logger.error("Failed to remove orphaned file #{file_info[:path]}: #{e.message}")
    end
  end

  # Clean up empty directory if configured
  cleanup_empty_directory if @config.cleanup_empty_dir && removed_count > 0

  removed_count
end

#remove_ssh_config_file(machine) ⇒ Object

Remove SSH config file for VM



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 85

def remove_ssh_config_file(machine)
  file_path = get_file_path(machine)
  
  begin
    if File.exist?(file_path)
      File.delete(file_path)
      @logger.info("SSH config file removed: #{file_path}")
      
      # Clean up empty directory if configured
      cleanup_empty_directory if @config.cleanup_empty_dir
      true
    else
      @logger.debug("SSH config file does not exist: #{file_path}")
      false
    end
  rescue => e
    @logger.error("Failed to remove SSH config file #{file_path}: #{e.message}")
    false
  end
end

#ssh_config_file_exists?(machine) ⇒ Boolean

Check if SSH config file exists for VM

Returns:

  • (Boolean)


107
108
109
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 107

def ssh_config_file_exists?(machine)
  File.exist?(get_file_path(machine))
end

#validate_ssh_config_content(content) ⇒ Object

Validate SSH config file content



112
113
114
115
116
117
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 112

def validate_ssh_config_content(content)
  return false if content.nil? || content.empty?
  
  # Basic validation - check for required SSH config elements
  content.include?("Host ") && content.include?("HostName ") && content.include?("Port ")
end

#write_ssh_config_file(machine) ⇒ Object

Write SSH config file for VM with atomic operation



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/vagrant-ssh-config-manager/file_manager.rb', line 62

def write_ssh_config_file(machine)
  return false unless @config.enabled

  file_path = get_file_path(machine)
  content = generate_ssh_config_content(machine)
  return false unless content

  begin
    # Ensure directory exists
    FileUtils.mkdir_p(File.dirname(file_path), mode: 0700)
    
    # Use atomic write with temporary file
    write_file_atomically(file_path, content)
    
    @logger.info("SSH config file created: #{file_path}")
    true
  rescue => e
    @logger.error("Failed to write SSH config file #{file_path}: #{e.message}")
    false
  end
end