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



12
13
14
15
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 12

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

Instance Method Details

#all_config_filesObject Also known as: get_all_config_files

Return list of all config files



190
191
192
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 190

def all_config_files
  Dir.glob(File.join(@config.ssh_config_dir, '*.conf'))
end

#cleanup_orphaned_filesObject

Detect and clean up orphaned SSH config files



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
160
161
162
163
164
165
166
167
168
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 129

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
    next unless filename.match(/^([a-f0-9]{8})-(.+)$/)

    project_hash = ::Regexp.last_match(1)
    vm_name = ::Regexp.last_match(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
    next unless 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

  # 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

#file_path(machine) ⇒ Object Also known as: get_file_path

Return full path for a machine’s SSH config file



31
32
33
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 31

def file_path(machine)
  generate_file_path(machine)
end

#generate_file_path(machine) ⇒ Object

Generate full file path for a machine’s SSH config under ssh_config_dir



26
27
28
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 26

def generate_file_path(machine)
  File.join(@config.ssh_config_dir, generate_filename(machine))
end

#generate_filename(machine) ⇒ Object

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



19
20
21
22
23
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 19

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



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 36

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]&.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

#remove_orphaned_filesObject

Remove orphaned SSH config files



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 171

def remove_orphaned_files
  orphaned_files = cleanup_orphaned_files
  removed_count = 0

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

  # Clean up empty directory if configured
  cleanup_empty_directory if @config.cleanup_empty_dir && removed_count.positive?

  removed_count
end

#remove_ssh_config_file(machine) ⇒ Object

Remove SSH config file for VM



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 91

def remove_ssh_config_file(machine)
  file_path = 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 StandardError => 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)


113
114
115
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 113

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

#validate_ssh_config_content?(content) ⇒ Boolean Also known as: validate_ssh_config_content

Validate SSH config file content Returns true if the content contains required SSH config elements

Returns:

  • (Boolean)


119
120
121
122
123
124
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 119

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



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/vagrant_ssh_config_manager/file_manager.rb', line 68

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

  file_path = 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: 0o700)

    # Use atomic write with temporary file
    write_file_atomically(file_path, content)

    @logger.info("SSH config file created: #{file_path}")
    true
  rescue StandardError => e
    @logger.error("Failed to write SSH config file #{file_path}: #{e.message}")
    false
  end
end