vagrant-local 0.0.1

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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.github/dependabot.yml +6 -0
  5. data/.github/workflows/codeql-analysis.yml +72 -0
  6. data/.github/workflows/lint-release-and-publish-nightly.yml +73 -0
  7. data/.github/workflows/lint-release-and-publish.yml +71 -0
  8. data/.github/workflows/ruby-lint.yml +35 -0
  9. data/.gitignore +35 -0
  10. data/.rspec +2 -0
  11. data/.rubocop.yml +143 -0
  12. data/CHANGELOG.md +32 -0
  13. data/CODE_OF_CONDUCT.md +128 -0
  14. data/CONTRIBUTING.md +97 -0
  15. data/Gemfile +26 -0
  16. data/LICENSE +651 -0
  17. data/PULL_REQUEST_TEMPLATE.md +39 -0
  18. data/README.md +92 -0
  19. data/RELEASE.md +22 -0
  20. data/Rakefile +32 -0
  21. data/SECURITY.md +19 -0
  22. data/ansible.cfg +5 -0
  23. data/docs/CNAME +1 -0
  24. data/docs/_config.yml +1 -0
  25. data/docs/css/main.css +55 -0
  26. data/docs/css/styles.css +8678 -0
  27. data/docs/index.html +125 -0
  28. data/lib/vagrant-local/action/create.rb +27 -0
  29. data/lib/vagrant-local/action/destroy.rb +25 -0
  30. data/lib/vagrant-local/action/halt.rb +24 -0
  31. data/lib/vagrant-local/action/import.rb +27 -0
  32. data/lib/vagrant-local/action/is_created.rb +22 -0
  33. data/lib/vagrant-local/action/network.rb +24 -0
  34. data/lib/vagrant-local/action/network_cleanup.rb +26 -0
  35. data/lib/vagrant-local/action/not_created.rb +20 -0
  36. data/lib/vagrant-local/action/package.rb +135 -0
  37. data/lib/vagrant-local/action/restart.rb +27 -0
  38. data/lib/vagrant-local/action/setup.rb +24 -0
  39. data/lib/vagrant-local/action/shutdown.rb +47 -0
  40. data/lib/vagrant-local/action/start.rb +25 -0
  41. data/lib/vagrant-local/action/wait_till_boot.rb +47 -0
  42. data/lib/vagrant-local/action/wait_till_up.rb +65 -0
  43. data/lib/vagrant-local/action.rb +187 -0
  44. data/lib/vagrant-local/command/guest_power_controls.rb +58 -0
  45. data/lib/vagrant-local/command/local.rb +69 -0
  46. data/lib/vagrant-local/command/restart_guest.rb +29 -0
  47. data/lib/vagrant-local/command/shutdown_guest.rb +29 -0
  48. data/lib/vagrant-local/command/vnc_console.rb +48 -0
  49. data/lib/vagrant-local/command/webvnc_console.rb +49 -0
  50. data/lib/vagrant-local/config.rb +55 -0
  51. data/lib/vagrant-local/driver.rb +208 -0
  52. data/lib/vagrant-local/errors.rb +84 -0
  53. data/lib/vagrant-local/executor.rb +38 -0
  54. data/lib/vagrant-local/plugin.rb +76 -0
  55. data/lib/vagrant-local/provider.rb +83 -0
  56. data/lib/vagrant-local/util/subprocess.rb +31 -0
  57. data/lib/vagrant-local/util/timer.rb +19 -0
  58. data/lib/vagrant-local/version.rb +8 -0
  59. data/lib/vagrant-local.rb +29 -0
  60. data/locales/en.yml +187 -0
  61. data/vagrant-zones.gemspec +37 -0
  62. metadata +191 -0
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'log4r'
4
+ require 'fileutils'
5
+ require 'digest/md5'
6
+ require 'io/console'
7
+ require 'ruby_expect'
8
+ require 'netaddr'
9
+ require 'ipaddr'
10
+ require 'vagrant/util/numeric'
11
+ require 'pty'
12
+ require 'expect'
13
+ require 'vagrant'
14
+ require 'resolv'
15
+ require 'open3'
16
+ require 'vagrant-local/util/timer'
17
+ require 'vagrant-local/util/subprocess'
18
+ require 'vagrant/util/retryable'
19
+
20
+ module VagrantPlugins
21
+ module ProviderLocal
22
+ # This class does the heavy lifting of the local provider
23
+ class Driver
24
+ include Vagrant::Util::Retryable
25
+ attr_accessor :executor
26
+
27
+ def initialize(machine)
28
+ @logger = Log4r::Logger.new('vagrant_local::driver')
29
+ @machine = machine
30
+ @executor = Executor::Exec.new
31
+ @pfexec = if Process.uid.zero?
32
+ ''
33
+ elsif system('sudo -v')
34
+ 'sudo'
35
+ else
36
+ 'pfexec'
37
+ end
38
+ end
39
+
40
+ def state(machine)
41
+ vm_data = YAML.load_file("#{machine.name}.vmstate")
42
+ return :not_created unless vm_data.is_a?(Array) && !vm_data.empty? && vm_data.first.is_a?(Hash)
43
+
44
+ vm_state = vm_data.first['state']
45
+ case vm_state
46
+ when 'running'
47
+ :running
48
+ when 'installed', 'stopped'
49
+ :stopped
50
+ else
51
+ :not_created
52
+ end
53
+ end
54
+
55
+ # Execute System commands
56
+ def execute(...)
57
+ @executor.execute(...)
58
+ end
59
+
60
+ ## Begin installation
61
+ def install(_uii)
62
+ config = @machine.config.vm.provisioners[0].config.extra_vars.to_json
63
+ command = "#{@pfexec} ansible-playbook ./providers/ansible/install.yml -e '#{config}'"
64
+ _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
65
+ puts stdout.readline until stdout.eof?
66
+ wait_thr.value
67
+ end
68
+
69
+ ## Run commands over SSH instead of ZLogin
70
+ def ssh_run_command(uii, command)
71
+ config = @machine.provider_config
72
+ ip = get_ip_address
73
+ user = user(@machine)
74
+ key = userprivatekeypath(@machine).to_s
75
+ port = sshport(@machine).to_s
76
+ port = 22 if sshport(@machine).to_s.nil?
77
+ execute_return = ''
78
+ Util::Timer.time do
79
+ retryable(on: Errors::TimeoutError, tries: 60) do
80
+ # If we're interrupted don't worry about waiting
81
+ ssh_string = "#{@pfexec} ssh -o 'StrictHostKeyChecking=no' -p"
82
+ execute_return = execute(false, %(#{ssh_string} #{port} -i #{key} #{user}@#{ip} "#{command}"))
83
+ uii.info(I18n.t('vagrant_local.ssh_run_command')) if config.debug
84
+ uii.info(I18n.t('vagrant_local.ssh_run_command') + command) if config.debug
85
+ loop do
86
+ break if @machine.communicate.ready?
87
+ end
88
+ end
89
+ end
90
+ execute_return
91
+ end
92
+
93
+ ## Boot the Machine
94
+ def boot(uii)
95
+ config = @machine.config.vm.provisioners[0].config.extra_vars.to_json
96
+ command = "#{@pfexec} ansible-playbook ./providers/ansible/boot.yml -e '#{config}'"
97
+ uii.info(I18n.t('vagrant_local.start'))
98
+ _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
99
+ puts stdout.readline until stdout.eof?
100
+ wait_thr.value
101
+ end
102
+
103
+ # This ensures the host is ready for provisioning
104
+ def check_support(uii)
105
+ uii.info(I18n.t('vagrant_local.preflight_checks'))
106
+ uii.info(I18n.t('vagrant_local.ansible_playbook_check'))
107
+ playbook_result = execute(false, "#{@pfexec} which ansible-playbook")
108
+ raise Errors::AnsiblePlaybookNotDetected if playbook_result.empty?
109
+
110
+ uii.info(I18n.t('vagrant_local.ansible_check'))
111
+ result = execute(false, "#{@pfexec} which ansible")
112
+ raise Errors::AnsibleNotDetected if result.empty?
113
+ end
114
+
115
+ def get_ip_address
116
+ vm_data = YAML.load_file("#{@machine.name}.vmstate")
117
+ return nil unless vm_data.is_a?(Array) && !vm_data.empty? && vm_data.first.is_a?(Hash)
118
+
119
+ vm_data.first['public_ip']
120
+ end
121
+
122
+ # This filters the vagrantuser
123
+ def user(machine)
124
+ config = machine.provider_config
125
+ user = config.vagrant_user unless config.vagrant_user.nil?
126
+ user = 'vagrant' if config.vagrant_user.nil?
127
+ user
128
+ end
129
+
130
+ # This filters the userprivatekeypath
131
+ def userprivatekeypath(machine)
132
+ config = machine.provider_config
133
+ userkey = config.vagrant_user_private_key_path.to_s
134
+ if config.vagrant_user_private_key_path.to_s.nil?
135
+ id_rsa = 'https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant'
136
+ file = './id_rsa'
137
+ command = "#{@pfexec} curl #{id_rsa} -O #{file}"
138
+ Util::Subprocess.new command do |_stdout, stderr, _thread|
139
+ uii.rewriting do |uipkp|
140
+ uipkp.clear_line
141
+ uipkp.info(I18n.t('vagrant_local.importing_vagrant_key'), new_line: false)
142
+ uipkp.report_progress(stderr, 100, false)
143
+ end
144
+ end
145
+ uii.clear_line
146
+ userkey = './id_rsa'
147
+ end
148
+ userkey
149
+ end
150
+
151
+ # This filters the sshport
152
+ def sshport(machine)
153
+ config = machine.provider_config
154
+ sshport = '22'
155
+ sshport = config.sshport.to_s unless config.sshport.to_s.nil? || config.sshport.to_i.zero?
156
+ # uii.info(I18n.t('vagrant_local.sshport')) if config.debug
157
+ sshport
158
+ end
159
+
160
+ # This filters the vagrantuserpass
161
+ def vagrantuserpass(machine)
162
+ config = machine.provider_config
163
+ # uii.info(I18n.t('vagrant_local.vagrantuserpass')) if config.debug
164
+ config.vagrant_user_pass unless config.vagrant_user_pass.to_s.nil?
165
+ end
166
+
167
+ # Halts the instance, first via shutdown command, then a halt.
168
+ def halt(uii)
169
+ provider_config = @machine.provider_config
170
+ config = @machine.config.vm.provisioners[0].config.extra_vars.to_json
171
+ uii.info(I18n.t('vagrant_local.graceful_shutdown'))
172
+ begin
173
+ Timeout.timeout(provider_config.clean_shutdown_time) do
174
+ command = "#{@pfexec} ansible-playbook ./providers/ansible/halt.yml -e '#{config}'"
175
+ _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
176
+ puts stdout.readline until stdout.eof?
177
+ wait_thr.value
178
+ end
179
+ rescue Timeout::Error
180
+ uii.info(I18n.t('vagrant_local.graceful_shutdown_failed') + provider_config.clean_shutdown_time.to_s)
181
+ begin
182
+ Timeout.timeout(provider_config.clean_shutdown_time) do
183
+ command = "#{@pfexec} ansible-playbook ./providers/ansible/halt.yml -e '#{config}'"
184
+ _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
185
+ puts stdout.readline until stdout.eof?
186
+ wait_thr.value
187
+ end
188
+ rescue Timeout::Error
189
+ raise Errors::TimeoutHalt
190
+ end
191
+ end
192
+ end
193
+
194
+ # Destroys the instance
195
+ def destroy(id)
196
+ config = @machine.config.vm.provisioners[0].config.extra_vars.to_json
197
+ if state(@machine) == :stopped
198
+ id.info(I18n.t('vagrant_local.destroy'))
199
+ command = "#{@pfexec} ansible-playbook ./providers/ansible/destroy.yml -e '#{config}'"
200
+ _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
201
+ puts stdout.readline until stdout.eof?
202
+ wait_thr.value
203
+ end
204
+ id.info(I18n.t('vagrant_local.destroyed'))
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vagrant'
4
+
5
+ module VagrantPlugins
6
+ module ProviderLocal
7
+ module Errors
8
+ # Namespace for Vagrant Local Errors
9
+ class VagrantLocalError < Vagrant::Errors::VagrantError
10
+ error_namespace('vagrant_local.errors')
11
+ end
12
+
13
+ # System Check Results
14
+ class SystemVersionIsTooLow < VagrantLocalError
15
+ error_key(:system_version_too_low)
16
+ end
17
+
18
+ # Compatability Check Tool
19
+ class MissingCompatCheckTool < VagrantLocalError
20
+ error_key(:missing_compatability_check_tool)
21
+ end
22
+
23
+ # Missing Bhyve
24
+ class MissingBhyve < VagrantLocalError
25
+ error_key(:missing_bhyve)
26
+ end
27
+
28
+ # HasNoRootPrivilege
29
+ class HasNoRootPrivilege < VagrantLocalError
30
+ error_key(:has_no_root_privilege)
31
+ end
32
+
33
+ # ExecuteError
34
+ class ExecuteError < VagrantLocalError
35
+ error_key(:execute_error)
36
+ end
37
+
38
+ # TimeoutError
39
+ class TimeoutError < VagrantLocalError
40
+ error_key(:timeout_error)
41
+ end
42
+
43
+ # VirtualBoxRunningConflictDetected
44
+ class VirtualBoxRunningConflictDetected < VagrantLocalError
45
+ error_key(:virtual_box_running_conflict_detected)
46
+ end
47
+
48
+ # AnsibleNotDetected
49
+ class AnsibleNotDetected < VagrantLocalError
50
+ error_key(:ansible_not_detected)
51
+ end
52
+
53
+ # AnsiblePlaybookNotDetected
54
+ class AnsiblePlaybookNotDetected < VagrantLocalError
55
+ error_key(:ansible_playbook_not_detected)
56
+ end
57
+
58
+ # NotYetImplemented
59
+ class NotYetImplemented < VagrantLocalError
60
+ error_key(:not_yet_implemented)
61
+ end
62
+
63
+ # TimeoutHalt
64
+ class TimeoutHalt < VagrantLocalError
65
+ error_key(:halt_timeout)
66
+ end
67
+
68
+ # InvalidbhyveBrand
69
+ class InvalidbhyveBrand < VagrantLocalError
70
+ error_key(:invalidbhyve_brand)
71
+ end
72
+
73
+ # InvalidLXBrand
74
+ class InvalidLXBrand < VagrantLocalError
75
+ error_key(:invalidLX_brand)
76
+ end
77
+
78
+ # ConsoleFailed
79
+ class ConsoleFailed < VagrantLocalError
80
+ error_key(:console_failed_exit)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vagrant/util/busy'
4
+ require 'vagrant/util/subprocess'
5
+
6
+ module VagrantPlugins
7
+ module ProviderLocal
8
+ module Executor
9
+ # This class is used to execute commands as subprocess.
10
+ class Exec
11
+ # When we need the command's exit code we should set parameter
12
+ # exit_code to true, otherwise this method will return executed
13
+ # command's stdout
14
+ def execute(exit_code, *cmd, **_opts, &block)
15
+ # Append in the options for subprocess
16
+ cmd << { notify: %i[stdout stderr] }
17
+
18
+ cmd.unshift('sh', '-c')
19
+ interrupted = false
20
+ # Lambda to change interrupted to true
21
+ int_callback = -> { interrupted = true }
22
+ result = ::Vagrant::Util::Busy.busy(int_callback) do
23
+ ::Vagrant::Util::Subprocess.execute(*cmd, &block)
24
+ end
25
+ return result.exit_code if exit_code
26
+
27
+ result.stderr.gsub!("\r\n", "\n")
28
+ result.stdout.gsub!("\r\n", "\n")
29
+ puts "Command Failed: #{cmd}" if result.exit_code != 0 || interrupted
30
+ puts "Exit Results: #{result.stderr}" if result.exit_code != 0 || interrupted
31
+ raise Errors::ExecuteError if result.exit_code != 0 || interrupted
32
+
33
+ result.stdout[0..-2]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'vagrant'
5
+ rescue LoadError
6
+ raise 'The Vagrant Local plugin must be run within Vagrant.'
7
+ end
8
+
9
+ module VagrantPlugins
10
+ module ProviderLocal
11
+ # This is a the plugin droping for the vagrant-local vagrant plugin
12
+ class Plugin < Vagrant.plugin('2')
13
+ name 'local'
14
+ description <<-DESC
15
+ This plugin allows vagrant to manage a host as a VM
16
+ DESC
17
+
18
+ config(:local, :provider) do
19
+ require_relative 'config'
20
+ Config
21
+ end
22
+ provider(:local, parallel: false) do
23
+ require_relative 'provider'
24
+ Provider
25
+ end
26
+
27
+ # This initializes the internationalization strings.
28
+ def self.setup_i18n
29
+ I18n.load_path << File.expand_path('locales/en.yml', ProviderLocal.source_root)
30
+ I18n.reload!
31
+ end
32
+
33
+ # This sets up our log level to be whatever VAGRANT_LOG is.
34
+ def self.setup_logging
35
+ require 'log4r'
36
+
37
+ level = nil
38
+ begin
39
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
40
+ rescue NameError
41
+ # This means that the logging constant wasn't found,
42
+ # which is fine. We just keep `level` as `nil`. But
43
+ # we tell the user.
44
+ level = nil
45
+ end
46
+
47
+ # Some constants, such as "true" resolve to booleans, so the
48
+ # above error checking doesn't catch it. This will check to make
49
+ # sure that the log level is an integer, as Log4r requires.
50
+ level = nil unless level.is_a?(Integer)
51
+
52
+ # Set the logging level on all "vagrant" namespaced
53
+ # logs as long as we have a valid level.
54
+
55
+ return unless level
56
+
57
+ logger = Log4r::Logger.new('vagrant_local')
58
+ logger.outputters = Log4r::Outputter.stderr
59
+ logger.level = level
60
+ logger
61
+ end
62
+
63
+ # Setup logging and i18n before any autoloading loads other classes
64
+ # with logging configured as this prevents inheritance of the log level
65
+ # from the parent logger.
66
+ setup_logging
67
+ setup_i18n
68
+
69
+ ## This setups the local commands master
70
+ command('local') do
71
+ require_relative 'command/local'
72
+ Command::Local
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vagrant'
4
+ require 'log4r'
5
+
6
+ module VagrantPlugins
7
+ # This is a module to assist in managing a Host
8
+ module ProviderLocal
9
+ autoload :Driver, 'vagrant-local/driver'
10
+ # This is a module to assist in managing a Host
11
+ class Provider < Vagrant.plugin('2', :provider)
12
+ def initialize(machine)
13
+ @logger = Log4r::Logger.new('vagrant::provider::local')
14
+ @machine = machine
15
+ super(machine)
16
+ end
17
+
18
+ def driver
19
+ return @driver if @driver
20
+
21
+ @driver = Driver.new(@machine)
22
+ end
23
+
24
+ def ssh_info
25
+ # We just return nil if were not able to identify the VM's IP and
26
+ # let Vagrant core deal with it like docker provider does
27
+ return nil if state.id != :running
28
+ return nil unless driver.get_ip_address
29
+
30
+ passwordauth = 'passwordauth'
31
+ ssh_info = {
32
+ host: driver.get_ip_address,
33
+ port: driver.sshport(@machine).to_s,
34
+ password: driver.vagrantuserpass(@machine).to_s,
35
+ username: driver.user(@machine),
36
+ private_key_path: driver.userprivatekeypath(@machine).to_s,
37
+ PasswordAuthentication: passwordauth
38
+ }
39
+ ssh_info unless ssh_info.nil?
40
+ end
41
+
42
+ # This should return an action callable for the given name.
43
+ # @param [Symbol] name Name of the action.
44
+ # @return [Object] A callable action sequence object, whether it
45
+ # is a proc, object, etc.
46
+ def action(name)
47
+ # Attempt to get the action method from the Action class if it
48
+ # exists, otherwise return nil to show that we don't support the
49
+ # given action
50
+ action_method = "action_#{name}"
51
+ return Action.send(action_method) if Action.respond_to?(action_method)
52
+
53
+ nil
54
+ end
55
+
56
+ # This method is called if the underying machine ID changes. Providers
57
+ # can use this method to load in new data for the actual backing
58
+ # machine or to realize that the machine is now gone (the ID can
59
+ # become `nil`). No parameters are given, since the underlying machine
60
+ # is simply the machine instance given to this object. And no
61
+ # return value is necessary.
62
+ def machine_id_changed
63
+ nil
64
+ end
65
+
66
+ def state
67
+ state_id = nil
68
+ state_id = :not_created unless @machine.id
69
+ state_id = driver.state(@machine) if @machine.id && !state_id
70
+ # This is a special pseudo-state so that we don't set the
71
+ # NOT_CREATED_ID while we're setting up the machine. This avoids
72
+ # clearing the data dir.
73
+ state_id = :preparing if @machine.id == 'preparing'
74
+ # Get the short and long description
75
+ short = state_id.to_s.tr('_', ' ')
76
+ # If we're not created, then specify the special ID flag
77
+ state_id = Vagrant::MachineState::NOT_CREATED_ID if state_id == :not_created
78
+ # Return the MachineState object
79
+ Vagrant::MachineState.new(state_id, short, short)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'log4r'
5
+ module VagrantPlugins
6
+ module ProviderLocal
7
+ module Util
8
+ # This shiny device polishes bared foos
9
+ class Subprocess
10
+ def initialize(cmd, &_block)
11
+ Open3.popen3(cmd) do |_stdin, stdout, stderr, thread|
12
+ # read each stream from a new thread
13
+ { :out => stdout, :err => stderr }.each do |key, stream|
14
+ Thread.new do
15
+ until (line = stream.gets).nil?
16
+ # yield the block depending on the stream
17
+ if key == :out
18
+ yield line, nil, thread if block_given?
19
+ elsif block_given?
20
+ yield nil, line, thread
21
+ end
22
+ end
23
+ end
24
+ end
25
+ thread.join # don't exit until the external process is done
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VagrantPlugins
4
+ module ProviderLocal
5
+ module Util
6
+ # This is a utlity to time commands and scripts
7
+ class Timer
8
+ # A basic utility method that times the execution of the given
9
+ # block and returns it.
10
+ def self.time
11
+ start_time = Time.now.to_f
12
+ yield
13
+ end_time = Time.now.to_f
14
+ end_time - start_time
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VagrantPlugins
4
+ module ProviderLocal
5
+ VERSION = '0.0.1'
6
+ NAME = 'vagrant-local'
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module VagrantPlugins
6
+ # This is used to configure, manage, create and destroy local where vagrant by itself cannot
7
+ module ProviderLocal
8
+ lib_path = Pathname.new(File.expand_path('vagrant-local', __dir__))
9
+ autoload :Action, lib_path.join('action')
10
+ autoload :Executor, lib_path.join('executor')
11
+ autoload :Driver, lib_path.join('driver')
12
+ autoload :Errors, lib_path.join('errors')
13
+ # This function returns the path to the source of this plugin
14
+ # @return [Pathname]
15
+ def self.source_root
16
+ @source_root ||= Pathname.new(File.expand_path('..', __dir__))
17
+ end
18
+ end
19
+ end
20
+
21
+ begin
22
+ require 'vagrant'
23
+ rescue LoadError
24
+ raise 'The Vagrant vagrant-local plugin must be run within Vagrant.'
25
+ end
26
+
27
+ raise 'The Vagrant vagrant-local plugin is only compatible with Vagrant 2+.' if Vagrant::VERSION < '2'
28
+
29
+ require 'vagrant-local/plugin'