vscode-vagrant
vscode-vagrant copied to clipboard
Feature request: Vagrant Up then Remote Connection
It would be useful if we can use this plugin (or something similar) to perform vagrant up, then vagrant ssh to achieve connection to the remote machine (with vscode-remote-release).
I have no idea if this is feasible or even sensible, but it would be interesting!
It would be useful!
In the interim I use a strategy to automatically maintain the remote hosts list, which is actually all you need. It solves the problem of the machines coming up on different ports each time.
I thought it worth describing here in case people find it interesting or useful.
Visual Studio Code can parse include directives in .ssh/config, but not wildcards (at the moment).
So I use triggers to regenerate a set of SSH config include files from vagrant ssh-config and store them in a known directory. I then have a method that generates a single index file including each of them, and in turn I include that from .ssh/config.
Basically:
- when bringing up/provisioning/reloading/resuming a machine, I dump the output from
vagrant ssh-configinto a file in a known directory (inside$HOME/.vagrant.d) - when destroying/halting/suspending machines, I remove the file
- in each case I rebuild the master include file
Then each trigger action will maintain your remote SSH hosts list for you, without needing to restart vscode.
The triggers in Vagrantfile:
config.trigger.after [:up, :provision, :reload, :resume] do |trigger|
trigger.ruby do |env,machine|
MyClass.up_trigger(env, machine)
end
end
config.trigger.after [:destroy, :halt, :suspend] do |trigger|
trigger.ruby do |env,machine|
MyClass.down_trigger(env, machine)
end
end
Then in MyClass is the following code.
This function defines an SSH configuration directory within .vagrant, where I will write individual files containing the output of vagrant ssh-config:
def ssh_config_dir
cfg_dir = Pathname.new(Vagrant.user_data_path).join('mydir', 'ssh')
cfg_dir.mkpath unless cfg_dir.exist?
cfg_dir
end
This function builds a master include file of all of those files, which gets stored in the same directory (so, err, don't call a vagrant box "include" ;-):
def build_ssh_include_file(ssh_dir)
return if !File.directory? ssh_dir
include_file = [ ]
Dir.entries(ssh_dir).each do |item|
next if File.directory? item
next if item == '.' or item == '..'
next if item !~ /\.config$/i
next if item == 'include.config'
path = ssh_dir.join(item)
include_file << "Include #{path}"
end
ssh_dir.join('include.config').write("# all vagrant hosts\n" + include_file.join("\n"))
end
The up_trigger function uses bash to invoke vagrant ssh-config to write the SSH config to a file. So this is sort of Unix-only for now. I guess I could directly invoke the underlying Vagrant code that produces that output for a more portable approach.
It then rebuilds the index file.
def up_trigger(env, machine)
# make our SSH config directory if we need it
cfg_dir = ssh_config_dir
return if !File.directory? cfg_dir
# now dump the vagrant SSH config into a named file
ssh_config = `bash -c 'vagrant ssh-config'`
cfg_dir.join(machine.name.to_s + '.config').write("\n" + ssh_config)
build_ssh_include_file(cfg_dir)
end
The down trigger removes the appropriate SSH config file and rebuilds the index. So the host will disappear from your vscode remotes.
def down_trigger(env, machine)
cfg_dir = ssh_config_dir
return if !File.directory? cfg_dir
cfg_file = cfg_dir.join(machine.name.to_s + '.config')
cfg_file.unlink if File.file? cfg_file
build_ssh_include_file(cfg_dir)
end
So you then include the master list in .ssh/config:
Include ~/.vagrant.d/mydir/ssh/include.config