vagrant-terraform 0.1.3
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 +7 -0
- data/.gitignore +10 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +11 -0
- data/LICENSE +21 -0
- data/README.md +120 -0
- data/example_box/README.md +12 -0
- data/example_box/Vagrantfile +14 -0
- data/example_box/dummy.box +0 -0
- data/example_box/metadata.json +4 -0
- data/lib/vagrant-terraform/action/create_vm.rb +205 -0
- data/lib/vagrant-terraform/action/destroy_vm.rb +39 -0
- data/lib/vagrant-terraform/action/halt_vm.rb +39 -0
- data/lib/vagrant-terraform/action/is_created.rb +19 -0
- data/lib/vagrant-terraform/action/is_running.rb +19 -0
- data/lib/vagrant-terraform/action/read_ssh_info.rb +44 -0
- data/lib/vagrant-terraform/action/read_state.rb +67 -0
- data/lib/vagrant-terraform/action/setup_terraform.rb +42 -0
- data/lib/vagrant-terraform/action/start_vm.rb +51 -0
- data/lib/vagrant-terraform/action/wait_for_vm_up.rb +99 -0
- data/lib/vagrant-terraform/action.rb +186 -0
- data/lib/vagrant-terraform/config.rb +90 -0
- data/lib/vagrant-terraform/errors.rb +32 -0
- data/lib/vagrant-terraform/plugin.rb +75 -0
- data/lib/vagrant-terraform/provider.rb +76 -0
- data/lib/vagrant-terraform/util/machine_names.rb +23 -0
- data/lib/vagrant-terraform/util/terraform_execute.rb +32 -0
- data/lib/vagrant-terraform/util/timer.rb +17 -0
- data/lib/vagrant-terraform/util/update_vm_state.rb +29 -0
- data/lib/vagrant-terraform/util.rb +8 -0
- data/lib/vagrant-terraform/version.rb +6 -0
- data/lib/vagrant-terraform.rb +21 -0
- data/locales/en.yml +50 -0
- data/vagrant-terraform.gemspec +21 -0
- metadata +91 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "open3"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module TerraformProvider
|
6
|
+
module Action
|
7
|
+
# This action reads the state of the machine and puts it in the
|
8
|
+
# `:machine_state_id` key in the environment.
|
9
|
+
class SetupTerraform
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
@logger = Log4r::Logger.new("vagrant_terraform::action::setup_terraform")
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
raise "env[:machine_tf_dir] not set" if env[:machine_tf_dir].nil?
|
17
|
+
|
18
|
+
terraform_dir = env[:machine_tf_dir]
|
19
|
+
if File.exist?(terraform_dir) && File.exist?("#{terraform_dir}/terraform.tfstate")
|
20
|
+
env[:ui].info("Already initialized.")
|
21
|
+
else
|
22
|
+
# dir_name = env[:root_path].basename.to_s.dup.gsub(/[^-a-z0-9_]/i, "")
|
23
|
+
begin
|
24
|
+
Dir.mkdir(File.dirname(terraform_dir)) unless File.exist?(File.dirname(terraform_dir))
|
25
|
+
rescue => e
|
26
|
+
retry if e.message =~ /File exists/
|
27
|
+
env[:ui].error("terraform init failed: #{e.message}")
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
Dir.mkdir(terraform_dir) unless File.exist?(terraform_dir)
|
32
|
+
rescue => e
|
33
|
+
retry if e.message =~ /File exists/
|
34
|
+
env[:ui].error("terraform init failed: #{e.message}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@app.call(env)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'vagrant-terraform/errors'
|
3
|
+
require 'vagrant-terraform/util/terraform_execute'
|
4
|
+
require 'vagrant-terraform/util/update_vm_state'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module TerraformProvider
|
8
|
+
module Action
|
9
|
+
|
10
|
+
# Just start the VM.
|
11
|
+
class StartVM
|
12
|
+
include Util::TerraformExecute
|
13
|
+
include Util::UpdateVmState
|
14
|
+
|
15
|
+
def initialize(app, env)
|
16
|
+
@logger = Log4r::Logger.new("vagrant_terraform::action::start_vm")
|
17
|
+
@app = app
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
config = env[:machine].provider_config
|
22
|
+
|
23
|
+
env[:ui].info(I18n.t("vagrant_terraform.starting_vm"))
|
24
|
+
|
25
|
+
begin
|
26
|
+
terraform_dir = env[:machine_tf_dir]
|
27
|
+
terraform_main_file = "#{terraform_dir}/main.tf"
|
28
|
+
update_vm_state(terraform_main_file, "running")
|
29
|
+
terraform_execute(env, 'terraform apply -auto-approve')
|
30
|
+
rescue Exception => e
|
31
|
+
fault_message = /Error was \"\[?(.+?)\]?\".*/.match(e.message)[1] rescue e.message
|
32
|
+
# TODO: retry in some case?
|
33
|
+
# retry if e.message =~ /something/
|
34
|
+
|
35
|
+
if e.message !~ /VM is running/
|
36
|
+
if config.debug
|
37
|
+
raise e
|
38
|
+
else
|
39
|
+
raise Errors::StartVMError,
|
40
|
+
:error_message => fault_message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
@app.call(env)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'vagrant-terraform/util/timer'
|
3
|
+
require 'vagrant-terraform/util/terraform_execute'
|
4
|
+
require 'socket'
|
5
|
+
require 'timeout'
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module TerraformProvider
|
9
|
+
module Action
|
10
|
+
|
11
|
+
# Wait till VM is started, till it obtains an IP address and is
|
12
|
+
# accessible via ssh.
|
13
|
+
class WaitForVmUp
|
14
|
+
include Util::TerraformExecute
|
15
|
+
|
16
|
+
def initialize(app, env)
|
17
|
+
@logger = Log4r::Logger.new("vagrant_terraform::action::wait_for_vm_up")
|
18
|
+
@app = app
|
19
|
+
end
|
20
|
+
|
21
|
+
def port_open?(ip, port, seconds=10)
|
22
|
+
# => checks if a port is open or not on a remote host
|
23
|
+
Timeout::timeout(seconds) do
|
24
|
+
begin
|
25
|
+
TCPSocket.new(ip, port).close
|
26
|
+
@logger.info("SSH Check OK for IP: #{ip}")
|
27
|
+
true
|
28
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError => e
|
29
|
+
@logger.info("SSH Connection Failed for IP #{ip}: #{e}")
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
rescue Timeout::Error
|
34
|
+
@logger.info("SSH Connection Failed: Timeout for IP: #{ip}" )
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(env)
|
39
|
+
# Initialize metrics if they haven't been
|
40
|
+
env[:metrics] ||= {}
|
41
|
+
|
42
|
+
# Wait for VM to obtain an ip address.
|
43
|
+
env[:metrics]["instance_ip_time"] = Util::Timer.time do
|
44
|
+
env[:ui].info(I18n.t("vagrant_terraform.waiting_for_ip"))
|
45
|
+
for attempt in 1..300
|
46
|
+
# If we're interrupted don't worry about waiting
|
47
|
+
next if env[:interrupted]
|
48
|
+
|
49
|
+
output = terraform_execute(env, "terraform refresh")
|
50
|
+
ip_addr = output.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/)&.to_s
|
51
|
+
unless ip_addr.nil?
|
52
|
+
env[:ui].info("Got IP (attempt #{attempt}): #{ip_addr}")
|
53
|
+
# Check if SSH-Server is up
|
54
|
+
if port_open?(ip_addr, 22)
|
55
|
+
env[:ip_address] = ip_addr
|
56
|
+
@logger.debug("Got output #{env[:ip_address]}")
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
sleep 2
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
terminate(env) if env[:interrupted]
|
65
|
+
|
66
|
+
if env[:ip_address].nil?
|
67
|
+
env[:ui].error("failed to get IP: #{env[:metrics]["instance_ip_time"]}")
|
68
|
+
raise Errors::NoIPError
|
69
|
+
else
|
70
|
+
@logger.info("Got IP address #{env[:ip_address]}")
|
71
|
+
@logger.info("Time for getting IP: #{env[:metrics]["instance_ip_time"]}")
|
72
|
+
|
73
|
+
# Booted and ready for use.
|
74
|
+
env[:ui].info(I18n.t("vagrant_terraform.ready"))
|
75
|
+
|
76
|
+
@app.call(env)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def recover(env)
|
81
|
+
return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
|
82
|
+
|
83
|
+
if env[:machine].provider.state.id != :not_created
|
84
|
+
# Undo the import
|
85
|
+
terminate(env)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def terminate(env)
|
90
|
+
destroy_env = env.dup
|
91
|
+
destroy_env.delete(:interrupted)
|
92
|
+
destroy_env[:config_validate] = false
|
93
|
+
destroy_env[:force_confirm_destroy] = true
|
94
|
+
env[:action_runner].run(Action.action_destroy, destroy_env)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'vagrant/action/builder'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module TerraformProvider
|
6
|
+
module Action
|
7
|
+
# Include the built-in modules so we can use them as top-level things.
|
8
|
+
include Vagrant::Action::Builtin
|
9
|
+
|
10
|
+
# This action is called to bring the box up from nothing.
|
11
|
+
def self.action_up
|
12
|
+
Vagrant::Action::Builder.new.tap do |b|
|
13
|
+
b.use HandleBox
|
14
|
+
b.use ConfigValidate
|
15
|
+
|
16
|
+
b.use Call, ReadState do |env, b2|
|
17
|
+
b2.use SetupTerraform
|
18
|
+
# synced_folders defaults to NFS on linux. Make it default to rsync.
|
19
|
+
env[:machine].config.nfs.functional = false
|
20
|
+
if env[:machine_state_id] == :running
|
21
|
+
b2.use Provision
|
22
|
+
b2.use SyncedFolderCleanup
|
23
|
+
require 'vagrant/action/builtin/synced_folders'
|
24
|
+
b2.use SyncedFolders
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
28
|
+
if env[:machine_state_id] == :not_created
|
29
|
+
b2.use CreateVM
|
30
|
+
b2.use Provision
|
31
|
+
b2.use SetHostname
|
32
|
+
end
|
33
|
+
|
34
|
+
b2.use StartVM
|
35
|
+
b2.use WaitForVmUp
|
36
|
+
b2.use SyncedFolderCleanup
|
37
|
+
require 'vagrant/action/builtin/synced_folders'
|
38
|
+
b2.use SyncedFolders
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.action_destroy
|
45
|
+
Vagrant::Action::Builder.new.tap do |b|
|
46
|
+
b.use ConfigValidate
|
47
|
+
b.use Call, IsCreated do |env, b2|
|
48
|
+
if !env[:result]
|
49
|
+
unless env[:machine].id.nil?
|
50
|
+
dir = ".vagrant/terraform/#{env[:machine].id}"
|
51
|
+
env[:ui].info("Removing: " + dir)
|
52
|
+
FileUtils.rm_rf(dir)
|
53
|
+
end
|
54
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_created"))
|
55
|
+
next
|
56
|
+
end
|
57
|
+
|
58
|
+
b2.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
|
59
|
+
b2.use HaltVM unless env[:machine].state.id == :stopped
|
60
|
+
# b2.use WaitTillDown unless env[:machine].state.id == :stopped
|
61
|
+
b2.use DestroyVM
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.action_provision
|
67
|
+
Vagrant::Action::Builder.new.tap do |b|
|
68
|
+
b.use ConfigValidate
|
69
|
+
b.use Call, IsCreated do |env, b2|
|
70
|
+
# synced_folders defaults to NFS on linux. Make it default to rsync.
|
71
|
+
env[:machine].config.nfs.functional = false
|
72
|
+
if !env[:result]
|
73
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_created"))
|
74
|
+
next
|
75
|
+
end
|
76
|
+
b2.use Provision
|
77
|
+
b2.use SyncedFolderCleanup
|
78
|
+
require 'vagrant/action/builtin/synced_folders'
|
79
|
+
b2.use SyncedFolders
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# This action is called to read the state of the machine. The resulting
|
85
|
+
# state is expected to be put into the `:machine_state_id` key.
|
86
|
+
def self.action_read_state
|
87
|
+
Vagrant::Action::Builder.new.tap do |b|
|
88
|
+
b.use HandleBox
|
89
|
+
b.use ConfigValidate
|
90
|
+
b.use ReadState
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# This action is called to read the SSH info of the machine. The
|
95
|
+
# resulting state is expected to be put into the `:machine_ssh_info`
|
96
|
+
# key.
|
97
|
+
def self.action_read_ssh_info
|
98
|
+
Vagrant::Action::Builder.new.tap do |b|
|
99
|
+
b.use ConfigValidate
|
100
|
+
b.use Call, ReadState do |env, b2|
|
101
|
+
b2.use ReadSSHInfo
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.action_halt
|
107
|
+
Vagrant::Action::Builder.new.tap do |b|
|
108
|
+
b.use Call, IsRunning do |env, b2|
|
109
|
+
if env[:machine_state_id] == :powering_up
|
110
|
+
env[:ui].info(I18n.t("vagrant_terraform.powering_up"))
|
111
|
+
next
|
112
|
+
end
|
113
|
+
if !env[:result]
|
114
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_up"))
|
115
|
+
next
|
116
|
+
end
|
117
|
+
b2.use HaltVM
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.action_reload
|
123
|
+
Vagrant::Action::Builder.new.tap do |b|
|
124
|
+
b.use action_halt
|
125
|
+
b.use action_up
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.action_ssh
|
130
|
+
Vagrant::Action::Builder.new.tap do |b|
|
131
|
+
b.use ConfigValidate
|
132
|
+
|
133
|
+
b.use Call, ReadState do |env, b2|
|
134
|
+
if env[:machine_state_id] == :not_created
|
135
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_created"))
|
136
|
+
next
|
137
|
+
end
|
138
|
+
if env[:machine_state_id] != :running
|
139
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_up"))
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
raise Errors::NoIPError if env[:ip_address].nil?
|
144
|
+
b2.use SSHExec
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.action_ssh_run
|
151
|
+
Vagrant::Action::Builder.new.tap do |b|
|
152
|
+
b.use ConfigValidate
|
153
|
+
|
154
|
+
b.use Call, ReadState do |env, b2|
|
155
|
+
if env[:machine_state_id] == :not_created
|
156
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_created"))
|
157
|
+
next
|
158
|
+
end
|
159
|
+
if env[:machine_state_id] != :running
|
160
|
+
env[:ui].info(I18n.t("vagrant_terraform.not_up"))
|
161
|
+
next
|
162
|
+
end
|
163
|
+
|
164
|
+
raise Errors::NoIPError if env[:ip_address].nil?
|
165
|
+
b2.use SSHRun
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
171
|
+
autoload :SetupTerraform, action_root.join("setup_terraform")
|
172
|
+
autoload :CreateVM, action_root.join("create_vm")
|
173
|
+
autoload :DestroyVM, action_root.join("destroy_vm")
|
174
|
+
autoload :HaltVM, action_root.join("halt_vm")
|
175
|
+
autoload :IsCreated, action_root.join("is_created")
|
176
|
+
autoload :IsRunning, action_root.join("is_running")
|
177
|
+
autoload :ReadSSHInfo, action_root.join("read_ssh_info")
|
178
|
+
autoload :ReadState, action_root.join("read_state")
|
179
|
+
autoload :WaitForVmUp, action_root.join("wait_for_vm_up")
|
180
|
+
|
181
|
+
autoload :StartVM, action_root.join("start_vm")
|
182
|
+
# autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
|
183
|
+
autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
require 'filesize'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module TerraformProvider
|
6
|
+
class Config < Vagrant.plugin('2', :config)
|
7
|
+
attr_reader :disks
|
8
|
+
|
9
|
+
attr_accessor :api_url
|
10
|
+
attr_accessor :api_token_id
|
11
|
+
attr_accessor :api_token_secret
|
12
|
+
attr_accessor :vga
|
13
|
+
attr_accessor :insecure
|
14
|
+
attr_accessor :debug
|
15
|
+
attr_accessor :vmname
|
16
|
+
attr_accessor :template
|
17
|
+
attr_accessor :disk_size
|
18
|
+
attr_accessor :storage_domain
|
19
|
+
attr_accessor :cpu_cores
|
20
|
+
attr_accessor :memory_size
|
21
|
+
attr_accessor :target_node
|
22
|
+
attr_accessor :onboot
|
23
|
+
attr_accessor :description
|
24
|
+
attr_accessor :nameserver
|
25
|
+
attr_accessor :searchdomain
|
26
|
+
attr_accessor :os_type
|
27
|
+
attr_accessor :full_clone
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@api_url = UNSET_VALUE
|
31
|
+
@api_token_id = UNSET_VALUE
|
32
|
+
@api_token_secret = UNSET_VALUE
|
33
|
+
@vga = UNSET_VALUE
|
34
|
+
@insecure = UNSET_VALUE
|
35
|
+
@debug = UNSET_VALUE
|
36
|
+
@vmname = UNSET_VALUE
|
37
|
+
@template = UNSET_VALUE
|
38
|
+
@disk_size = UNSET_VALUE
|
39
|
+
@storage_domain = UNSET_VALUE
|
40
|
+
@cpu_cores = UNSET_VALUE
|
41
|
+
@memory_size = UNSET_VALUE
|
42
|
+
@target_node = UNSET_VALUE
|
43
|
+
@onboot = UNSET_VALUE
|
44
|
+
@description = UNSET_VALUE
|
45
|
+
@nameserver = UNSET_VALUE
|
46
|
+
@searchdomain = UNSET_VALUE
|
47
|
+
@os_type = UNSET_VALUE
|
48
|
+
@full_clone = UNSET_VALUE
|
49
|
+
end
|
50
|
+
|
51
|
+
def finalize!
|
52
|
+
@api_url = nil if @api_url == UNSET_VALUE
|
53
|
+
@api_token_id = nil if @api_token_id == UNSET_VALUE
|
54
|
+
@api_token_secret = nil if @api_token_secret == UNSET_VALUE
|
55
|
+
@vga = 'virtio' if @vga == UNSET_VALUE
|
56
|
+
@insecure = false if @insecure == UNSET_VALUE
|
57
|
+
@debug = false if @debug == UNSET_VALUE
|
58
|
+
@vmname = nil if @vmname == UNSET_VALUE
|
59
|
+
@template = nil if @template == UNSET_VALUE
|
60
|
+
@disk_size = nil if @disk_size == UNSET_VALUE
|
61
|
+
@storage_domain = nil if @storage_domain == UNSET_VALUE
|
62
|
+
@cpu_cores = 1 if @cpu_cores == UNSET_VALUE
|
63
|
+
@memory_size = '512 MiB' if @memory_size == UNSET_VALUE
|
64
|
+
@target_node = nil if @target_node == UNSET_VALUE
|
65
|
+
@onboot = false if @onboot == UNSET_VALUE
|
66
|
+
@description = '' if @description == UNSET_VALUE
|
67
|
+
@nameserver = '' if @nameserver == UNSET_VALUE
|
68
|
+
@searchdomain = '' if @searchdomain == UNSET_VALUE
|
69
|
+
@os_type = 'l26' if @os_type == UNSET_VALUE
|
70
|
+
@full_clone = true if @full_clone == UNSET_VALUE
|
71
|
+
|
72
|
+
unless disk_size.nil?
|
73
|
+
begin
|
74
|
+
@disk_size = Filesize.from(@disk_size).to_f('B').to_i
|
75
|
+
rescue ArgumentError
|
76
|
+
raise "Not able to parse 'disk_size' #{@disk_size}."
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
begin
|
81
|
+
@memory_size = Filesize.from(@memory_size).to_f('B').to_i
|
82
|
+
rescue ArgumentError
|
83
|
+
raise "Not able to parse `memory_size`."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module TerraformProvider
|
5
|
+
module Errors
|
6
|
+
class VagrantTerraformError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_terraform.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class NoVMError < VagrantTerraformError
|
11
|
+
error_key(:no_vm_error)
|
12
|
+
end
|
13
|
+
|
14
|
+
class CreateVMError < VagrantTerraformError
|
15
|
+
error_key(:create_vm_error)
|
16
|
+
end
|
17
|
+
|
18
|
+
class StartVMError < VagrantTerraformError
|
19
|
+
error_key(:start_vm_error)
|
20
|
+
end
|
21
|
+
|
22
|
+
class NoIPError < VagrantTerraformError
|
23
|
+
error_key(:no_ip_error)
|
24
|
+
end
|
25
|
+
|
26
|
+
class TerraformError < VagrantTerraformError
|
27
|
+
error_key(:terraform_execution_error)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# vim: ai ts=2 sts=2 et sw=2 ft=ruby
|
2
|
+
begin
|
3
|
+
require 'vagrant'
|
4
|
+
rescue LoadError
|
5
|
+
raise "The Vagrant Terraform plugin must be run within Vagrant."
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
# This is a sanity check to make sure no one is attempting to install
|
10
|
+
# this into an early Vagrant version.
|
11
|
+
if Vagrant::VERSION < '2.4.0'
|
12
|
+
raise "The Vagrant Terraform plugin is only compatible with Vagrant 2.4+"
|
13
|
+
end
|
14
|
+
|
15
|
+
module VagrantPlugins
|
16
|
+
module TerraformProvider
|
17
|
+
class Plugin < Vagrant.plugin('2')
|
18
|
+
name "terraform"
|
19
|
+
description <<-DESC
|
20
|
+
Vagrant plugin to manage virtual machines with terraform.
|
21
|
+
DESC
|
22
|
+
|
23
|
+
config("terraform", :provider) do
|
24
|
+
require_relative "config"
|
25
|
+
Config
|
26
|
+
end
|
27
|
+
|
28
|
+
provider("terraform", parallel: true) do
|
29
|
+
# Setup logging and i18n
|
30
|
+
setup_logging
|
31
|
+
setup_i18n
|
32
|
+
|
33
|
+
require_relative "provider"
|
34
|
+
Provider
|
35
|
+
end
|
36
|
+
|
37
|
+
# This initializes the internationalization strings.
|
38
|
+
def self.setup_i18n
|
39
|
+
I18n.load_path << File.expand_path("locales/en.yml",
|
40
|
+
TerraformProvider.source_root)
|
41
|
+
I18n.reload!
|
42
|
+
end
|
43
|
+
|
44
|
+
# This sets up our log level to be whatever VAGRANT_LOG is.
|
45
|
+
def self.setup_logging
|
46
|
+
require "log4r"
|
47
|
+
|
48
|
+
level = nil
|
49
|
+
begin
|
50
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
51
|
+
rescue NameError
|
52
|
+
# This means that the logging constant wasn't found,
|
53
|
+
# which is fine. We just keep `level` as `nil`. But
|
54
|
+
# we tell the user.
|
55
|
+
level = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
# Some constants, such as "true" resolve to booleans, so the
|
59
|
+
# above error checking doesn't catch it. This will check to make
|
60
|
+
# sure that the log level is an integer, as Log4r requires.
|
61
|
+
level = nil if !level.is_a?(Integer)
|
62
|
+
|
63
|
+
# Set the logging level on all "vagrant" namespaced
|
64
|
+
# logs as long as we have a valid level.
|
65
|
+
if level
|
66
|
+
logger = Log4r::Logger.new("vagrant_terraform")
|
67
|
+
logger.outputters = Log4r::Outputter.stderr
|
68
|
+
logger.level = level
|
69
|
+
logger = nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module TerraformProvider
|
5
|
+
|
6
|
+
# This is the base class for a provider for the V2 API. A provider
|
7
|
+
# is responsible for creating compute resources to match the
|
8
|
+
# needs of a Vagrant-configured system.
|
9
|
+
class Provider < Vagrant.plugin('2', :provider)
|
10
|
+
def initialize(machine)
|
11
|
+
@machine = machine
|
12
|
+
end
|
13
|
+
|
14
|
+
# This should return an action callable for the given name.
|
15
|
+
def action(name)
|
16
|
+
# Attempt to get the action method from the Action class if it
|
17
|
+
# exists, otherwise return nil to show that we don't support the
|
18
|
+
# given action.
|
19
|
+
action_method = "action_#{name}"
|
20
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
# This method is called if the underying machine ID changes. Providers
|
25
|
+
# can use this method to load in new data for the actual backing
|
26
|
+
# machine or to realize that the machine is now gone (the ID can
|
27
|
+
# become `nil`).
|
28
|
+
def machine_id_changed
|
29
|
+
end
|
30
|
+
|
31
|
+
# This should return a hash of information that explains how to
|
32
|
+
# SSH into the machine. If the machine is not at a point where
|
33
|
+
# SSH is even possible, then `nil` should be returned.
|
34
|
+
def ssh_info
|
35
|
+
# Run a custom action called "read_ssh_info" which does what it says
|
36
|
+
# and puts the resulting SSH info into the `:machine_ssh_info` key in
|
37
|
+
# the environment.
|
38
|
+
#
|
39
|
+
# Ssh info has following format..
|
40
|
+
#
|
41
|
+
#{
|
42
|
+
# :host => "1.2.3.4",
|
43
|
+
# :port => "22",
|
44
|
+
# :username => "mitchellh",
|
45
|
+
# :private_key_path => "/path/to/my/key"
|
46
|
+
#}
|
47
|
+
env = @machine.action("read_ssh_info")
|
48
|
+
env[:machine_ssh_info]
|
49
|
+
end
|
50
|
+
|
51
|
+
# This should return the state of the machine within this provider.
|
52
|
+
# The state must be an instance of {MachineState}.
|
53
|
+
def state
|
54
|
+
# Run a custom action we define called "read_state" which does
|
55
|
+
# what it says. It puts the state in the `:machine_state_id`
|
56
|
+
# key in the environment.
|
57
|
+
env = @machine.action("read_state")
|
58
|
+
|
59
|
+
state_id = env[:machine_state_id]
|
60
|
+
|
61
|
+
# Get the short and long description
|
62
|
+
short = I18n.t("vagrant_terraform.states.short_#{state_id}")
|
63
|
+
long = I18n.t("vagrant_terraform.states.long_#{state_id}")
|
64
|
+
|
65
|
+
# Return the MachineState object
|
66
|
+
Vagrant::MachineState.new(state_id, short, long)
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
id = @machine.id.nil? ? "new" : @machine.id
|
71
|
+
"Terraform (#{id})"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module TerraformProvider
|
3
|
+
module Util
|
4
|
+
module MachineNames
|
5
|
+
DEFAULT_NAME = 'vagrant'.freeze
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def machine_hostname(machine)
|
10
|
+
machine.config.vm.hostname || DEFAULT_NAME
|
11
|
+
end
|
12
|
+
|
13
|
+
def machine_vmname(machine)
|
14
|
+
if machine.id.nil?
|
15
|
+
machine.provider_config.vmname || machine_hostname(machine)
|
16
|
+
else
|
17
|
+
machine.id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|