vagrant-haipa 0.0.1 → 0.2.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +11 -0
  3. data/.gitignore +49 -16
  4. data/.rspec_status +5 -0
  5. data/.vscode/launch.json +13 -3
  6. data/Gemfile +6 -2
  7. data/Gemfile.lock +181 -0
  8. data/LICENSE +21 -373
  9. data/Rakefile +7 -16
  10. data/lib/vagrant-haipa/action/converge_machine.rb +44 -0
  11. data/lib/vagrant-haipa/{actions → action}/delete_machine.rb +3 -10
  12. data/lib/vagrant-haipa/action/is_created.rb +19 -0
  13. data/lib/vagrant-haipa/action/is_running.rb +20 -0
  14. data/lib/vagrant-haipa/{actions → action}/message_already_created.rb +1 -1
  15. data/lib/vagrant-haipa/{actions → action}/message_not_created.rb +1 -1
  16. data/lib/vagrant-haipa/{actions → action}/message_will_not_destroy.rb +1 -1
  17. data/lib/vagrant-haipa/action/read_state.rb +19 -0
  18. data/lib/vagrant-haipa/{actions → action}/set_name.rb +3 -6
  19. data/lib/vagrant-haipa/action/start_machine.rb +24 -0
  20. data/lib/vagrant-haipa/action/stop_machine.rb +25 -0
  21. data/lib/vagrant-haipa/{actions → action}/wait_for_ip_address.rb +4 -4
  22. data/lib/vagrant-haipa/{actions.rb → action.rb} +78 -106
  23. data/lib/vagrant-haipa/config.rb +17 -15
  24. data/lib/vagrant-haipa/driver.rb +139 -0
  25. data/lib/vagrant-haipa/errors.rb +4 -36
  26. data/lib/vagrant-haipa/plugin.rb +8 -7
  27. data/lib/vagrant-haipa/provider.rb +44 -63
  28. data/lib/vagrant-haipa/version.rb +2 -2
  29. data/lib/vagrant-haipa.rb +11 -7
  30. data/locales/en.yml +2 -70
  31. data/spec/spec_helper.rb +20 -0
  32. data/spec/unit/provider_spec.rb +38 -0
  33. data/test/Vagrantfile +23 -14
  34. data/test/console.key +27 -0
  35. data/vagrant +27 -27
  36. data/vagrant-haipa.gemspec +3 -4
  37. metadata +32 -53
  38. data/README.md +0 -111
  39. data/lib/vagrant-haipa/actions/check_state.rb +0 -19
  40. data/lib/vagrant-haipa/actions/connect_haipa.rb +0 -24
  41. data/lib/vagrant-haipa/actions/create_machine.rb +0 -56
  42. data/lib/vagrant-haipa/actions/is_created.rb +0 -18
  43. data/lib/vagrant-haipa/actions/is_stopped.rb +0 -18
  44. data/lib/vagrant-haipa/actions/modify_provision_path.rb +0 -38
  45. data/lib/vagrant-haipa/actions/shut_down.rb +0 -33
  46. data/lib/vagrant-haipa/actions/start_machine.rb +0 -34
  47. data/lib/vagrant-haipa/actions/stop_machine.rb +0 -33
  48. data/lib/vagrant-haipa/helpers/client.rb +0 -111
  49. data/lib/vagrant-haipa/helpers/result.rb +0 -40
  50. data/test/cookbooks/test/recipes/default.rb +0 -1
  51. data/test/scripts/provision.sh +0 -3
  52. data/test/test.sh +0 -13
  53. data/test/test_id_rsa +0 -27
  54. data/test/test_id_rsa.pub +0 -1
@@ -1,6 +1,6 @@
1
1
  module VagrantPlugins
2
2
  module Haipa
3
- module Actions
3
+ module Action
4
4
  class WaitForIpAddress
5
5
  include Vagrant::Util::Retryable
6
6
 
@@ -11,12 +11,12 @@ module VagrantPlugins
11
11
  end
12
12
 
13
13
  def call(env)
14
- # refresh machine state with provider and output ip address
14
+ # get machine state from driver and output ip address
15
15
  retryable(:tries => 20, :sleep => 10) do
16
16
  next if env[:interrupted]
17
17
 
18
- haipa_machine = Provider.haipa_machine(@machine, :refresh => true)
19
- addresses = haipa_machine['Networks'].map{|x| x['IpV4Addresses']}.flatten
18
+ haipa_machine = @machine.provider.driver.machine('Networks')
19
+ addresses = haipa_machine.networks.map{|x| x.ip_v4addresses}.flatten
20
20
  addresses.reject! { |s| s.nil? || s.strip.empty? }
21
21
  address = addresses.first
22
22
  raise 'not ready' unless address
@@ -1,85 +1,89 @@
1
1
  module VagrantPlugins
2
2
  module Haipa
3
- module Actions
3
+ module Action
4
4
  include Vagrant::Action::Builtin
5
5
 
6
- # This action is called to halt the remote machine.
7
- def self.action_halt
6
+ # This action is called to bring the box up from nothing.
7
+ def self.action_up
8
8
  Vagrant::Action::Builder.new.tap do |b|
9
9
  b.use ConfigValidate
10
10
  b.use Call, IsCreated do |env, b2|
11
- unless env[:result]
12
- b2.use MessageNotCreated
13
- next
14
- end
15
11
 
16
- b2.use ConnectHaipa
17
- b2.use StopMachine
12
+ if !env[:result]
13
+ b2.use SetName
14
+ b2.use ConvergeMachine
15
+ end
18
16
  end
17
+ b.use action_start
19
18
  end
20
19
  end
21
20
 
22
- # This action is called to terminate the remote machine.
23
- def self.action_destroy
21
+
22
+ # This action is called to read the state of the machine. The
23
+ # resulting state is expected to be put into the `:machine_state_id`
24
+ # key.
25
+ def self.action_read_state
24
26
  Vagrant::Action::Builder.new.tap do |b|
25
- b.use Call, DestroyConfirm do |env, b2|
27
+ b.use ConfigValidate
28
+ b.use ReadState
29
+ end
30
+ end
31
+
32
+ def self.action_start
33
+ Vagrant::Action::Builder.new.tap do |b|
34
+ b.use ConfigValidate
35
+ b.use Call, IsRunning do |env, b2|
36
+ # If the machine is running, run the necessary provisioners
26
37
  if env[:result]
27
- b2.use ConfigValidate
28
- b2.use Call, IsCreated do |env2, b3|
29
- unless env2[:result]
30
- b3.use MessageNotCreated
31
- next
32
- end
33
-
34
- b3.use ConnectHaipa
35
- b3.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
36
- b3.use DeleteMachine
37
- end
38
- else
39
- b2.use MessageWillNotDestroy
38
+ b2.use action_provision
39
+ next
40
40
  end
41
+
42
+ b2.use action_boot
41
43
  end
42
44
  end
43
45
  end
44
46
 
45
- # This action is called when `vagrant provision` is called.
46
- def self.action_provision
47
+ def self.action_stop
47
48
  Vagrant::Action::Builder.new.tap do |b|
48
49
  b.use ConfigValidate
50
+
49
51
  b.use Call, IsCreated do |env, b2|
50
52
  unless env[:result]
51
53
  b2.use MessageNotCreated
52
54
  next
53
55
  end
54
-
55
- b2.use Provision
56
- b2.use SyncedFolderCleanup
57
- b2.use SyncedFolders
56
+
57
+ b2.use StopMachine
58
58
  end
59
59
  end
60
60
  end
61
61
 
62
- # This action is called to read the SSH info of the machine. The
63
- # resulting state is expected to be put into the `:machine_ssh_info`
64
- # key.
65
- def self.action_read_ssh_info
62
+ def self.action_boot
66
63
  Vagrant::Action::Builder.new.tap do |b|
67
- b.use ConfigValidate
68
- b.use ConnectHaipa
69
- b.use ReadSSHInfo
64
+ b.use Provision
65
+ b.use SyncedFolderCleanup
66
+ b.use SyncedFolders
67
+ b.use StartMachine
70
68
  end
71
69
  end
72
70
 
73
- # This action is called to read the state of the machine. The
74
- # resulting state is expected to be put into the `:machine_state_id`
75
- # key.
76
- def self.action_read_state
71
+ # This action is called when `vagrant provision` is called.
72
+ def self.action_provision
77
73
  Vagrant::Action::Builder.new.tap do |b|
78
74
  b.use ConfigValidate
79
- b.use ConnectHaipa
80
- b.use ReadState
75
+ b.use Call, IsCreated do |env, b2|
76
+ unless env[:result]
77
+ b2.use MessageNotCreated
78
+ next
79
+ end
80
+
81
+ b2.use Provision
82
+ b2.use SyncedFolderCleanup
83
+ b2.use SyncedFolders
84
+ end
81
85
  end
82
- end
86
+ end
83
87
 
84
88
  # This action is called to SSH into the machine.
85
89
  def self.action_ssh
@@ -118,92 +122,60 @@ module VagrantPlugins
118
122
  end
119
123
  end
120
124
 
121
- def self.action_start
122
- Vagrant::Action::Builder.new.tap do |b|
123
- b.use Call, IsState, :running do |env1, b1|
124
- if env1[:result]
125
- b1.use action_provision
126
- next
127
- end
128
-
129
- b1.use Call, IsState, :paused do |env2, b2|
130
- if env2[:result]
131
- b2.use action_resume
132
- next
133
- end
134
-
135
- b2.use Provision
136
- b2.use StartMachine
137
- b2.use WaitForCommunicator, [:running]
138
- b2.use SyncedFolderCleanup
139
- b2.use SyncedFolders
140
- b2.use SetHostname
141
- end
142
- end
143
- end
144
- end
145
-
146
- # This action is called to bring the box up from nothing.
147
- def self.action_up
125
+ # This action is called to terminate the remote machine.
126
+ def self.action_destroy
148
127
  Vagrant::Action::Builder.new.tap do |b|
149
- # b.use HandleBox
150
- b.use ConfigValidate
151
- # b.use BoxCheckOutdated
152
- b.use ConnectHaipa
153
- b.use Call, IsCreated do |env1, b1|
154
- if env1[:result]
155
- b1.use Call, IsStopped do |env2, b2|
156
- if env2[:result]
157
- b2.use action_start
158
- else
159
- b2.use MessageAlreadyCreated
128
+ b.use Call, DestroyConfirm do |env, b2|
129
+ if env[:result]
130
+ b2.use ConfigValidate
131
+ b2.use Call, IsCreated do |env2, b3|
132
+ unless env2[:result]
133
+ b3.use MessageNotCreated
134
+ next
160
135
  end
136
+
137
+ b3.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
138
+ b3.use DeleteMachine
161
139
  end
162
140
  else
163
- b1.use SetName
164
- b1.use CreateMachine
165
- b1.use action_start
141
+ b2.use MessageWillNotDestroy
166
142
  end
167
143
  end
168
144
  end
169
- end
145
+ end
170
146
 
171
147
  def self.action_reload
172
148
  Vagrant::Action::Builder.new.tap do |b|
173
149
  b.use ConfigValidate
174
- b.use ConnectHaipa
175
150
  b.use Call, IsCreated do |env, b2|
176
151
  unless env[:result]
177
152
  b2.use MessageNotCreated
178
153
  next
179
154
  end
180
155
 
181
- b2.use action_halt
182
- b2.use Call, WaitForState, :stopped, 120 do |env2, b3|
183
- if env2[:result]
184
- b3.use action_up
185
- else
186
- # TODO we couldn't reach :stopped, what now?
187
- end
188
- end
156
+ b2.use action_stop
157
+ b2.use ConvergeMachine
158
+ b2.use action_up
189
159
  end
190
160
  end
191
161
  end
192
162
 
193
163
  # The autoload farm
194
- action_root = Pathname.new(File.expand_path('../actions', __FILE__))
195
- autoload :ConnectHaipa, action_root.join('connect_haipa')
164
+ action_root = Pathname.new(File.expand_path('../action', __FILE__))
165
+ autoload :ReadState, action_root.join('read_state')
196
166
  autoload :IsCreated, action_root.join('is_created')
197
- autoload :IsStopped, action_root.join('is_stopped')
167
+ autoload :IsRunning, action_root.join('is_running')
168
+ autoload :SetName, action_root.join('set_name')
169
+ autoload :ConvergeMachine, action_root.join('converge_machine')
170
+ autoload :DeleteMachine, action_root.join('delete_machine')
171
+ autoload :StartMachine, action_root.join('start_machine')
172
+ autoload :StopMachine, action_root.join('stop_machine')
173
+ autoload :WaitForIpAddress, action_root.join('wait_for_ip_address')
174
+
198
175
  autoload :MessageAlreadyCreated, action_root.join('message_already_created')
199
176
  autoload :MessageNotCreated, action_root.join('message_not_created')
200
177
  autoload :MessageWillNotDestroy, action_root.join('message_will_not_destroy')
201
- autoload :CreateMachine, action_root.join('create_machine')
202
- autoload :DeleteMachine, action_root.join('delete_machine')
203
- autoload :StartMachine, action_root.join('start_machine')
204
- autoload :StopMachine, action_root.join('stop_machine')
205
- autoload :WaitForIpAddress, action_root.join('wait_for_ip_address')
206
- autoload :SetName, action_root.join('set_name')
178
+
207
179
  end
208
180
  end
209
- end
181
+ end
@@ -1,36 +1,38 @@
1
1
  module VagrantPlugins
2
2
  module Haipa
3
3
  class Config < Vagrant.plugin('2', :config)
4
- attr_accessor :token
5
- attr_accessor :image
6
- attr_accessor :region
7
- attr_accessor :flavor
8
-
9
4
  attr_accessor :name
10
5
 
11
6
  attr_accessor :vm_config
12
- attr_accessor :provision
7
+ attr_accessor :provision
13
8
 
9
+ attr_accessor :client_id
10
+ attr_accessor :client_key_file
11
+ attr_accessor :identity_endpoint
12
+ attr_accessor :api_endpoint
14
13
 
15
- def initialize
16
- @token = UNSET_VALUE
17
- @image = UNSET_VALUE
18
- @region = UNSET_VALUE
19
- @flavor = UNSET_VALUE
20
14
 
15
+ def initialize
16
+
21
17
  @name = UNSET_VALUE
22
18
  @vm_config = UNSET_VALUE
23
19
  @provision = UNSET_VALUE
20
+
21
+ @client_id = UNSET_VALUE
22
+ @client_key_file = UNSET_VALUE
23
+ @identity_endpoint = UNSET_VALUE
24
+ @api_endpoint = UNSET_VALUE
24
25
  end
25
26
 
26
27
  def finalize!
27
- @token = ENV['DO_TOKEN'] if @token == UNSET_VALUE
28
- @image = 'ubuntu-14-04-x64' if @image == UNSET_VALUE
29
- @region = 'nyc2' if @region == UNSET_VALUE
30
- @flavor = 'default' if @size == UNSET_VALUE
31
28
  @name = nil if @name == UNSET_VALUE
32
29
  @vm_config = [] if @vm_config == UNSET_VALUE
33
30
  @provision = [] if @provision == UNSET_VALUE
31
+
32
+ @client_id = nil if @client_id == UNSET_VALUE
33
+ @client_key_file = nil if @client_key_file == UNSET_VALUE
34
+ @identity_endpoint = nil if @identity_endpoint == UNSET_VALUE
35
+ @api_endpoint = nil if @api_endpoint == UNSET_VALUE
34
36
  end
35
37
 
36
38
  def validate(machine)
@@ -0,0 +1,139 @@
1
+ require 'haipa_compute'
2
+
3
+ module VagrantPlugins
4
+ module Haipa
5
+ class Driver
6
+ include Vagrant::Util::Retryable
7
+
8
+ @@compute_api = nil
9
+
10
+ def initialize(machine)
11
+ @machine = machine
12
+ end
13
+
14
+ # @return [::Haipa::Client::Compute::ApiConfiguration] Haipa Compute API
15
+ def compute_api
16
+ # If already connected to Haipa, just use it and don't connect
17
+ # again.
18
+ return @@compute_api if @@compute_api
19
+
20
+ config = @machine.provider_config
21
+
22
+
23
+ @@compute_api = ::Haipa::Client::Compute.new({
24
+ client_id: config.client_id,
25
+ client_key_file: config.client_key_file,
26
+ identity_endpoint: config.identity_endpoint,
27
+ api_endpoint: config.api_endpoint
28
+ })
29
+
30
+ @@compute_api
31
+
32
+ end
33
+
34
+
35
+ def read_state
36
+ return :not_created if @machine.id.nil?
37
+
38
+ haipa_machine = nil
39
+ begin
40
+ haipa_machine = compute_api.client.machines.get(@machine.id)
41
+ rescue ::Haipa::Client::HaipaOperationError => ex
42
+ if haipa_machine.nil?
43
+ # The machine can't be found
44
+ @logger.info('Machine not found or terminated, assuming it got destroyed.')
45
+ return :not_created
46
+ end
47
+ end
48
+
49
+ # Return the state
50
+ haipa_machine.status
51
+ end
52
+
53
+ def machine_by_name(name)
54
+ haipa_machine_list = compute_api.client.machines.list(:filter=>"name eq '#{name}'")
55
+ haipa_machine_list.value.first
56
+ end
57
+
58
+ def machine(expand = nil)
59
+ compute_api.client.machines.get(@machine.id, :expand => expand)
60
+ end
61
+
62
+ def converge(env, name)
63
+
64
+ machine_config_hash = {
65
+ 'name' => name,
66
+ 'vm' => @machine.provider_config.vm_config,
67
+ "provisioning" => @machine.provider_config.provision
68
+ }
69
+
70
+ machine_config = compute_api.deserialize(:MachineConfig, machine_config_hash)
71
+ operation = compute_api.client.machines.update_or_create(:config => machine_config)
72
+
73
+ wait_for_operation(env,operation)
74
+ end
75
+
76
+ def start(env)
77
+ operation = compute_api.client.machines.start(@machine.id)
78
+ wait_for_operation(env,operation)
79
+ end
80
+
81
+ def stop(env)
82
+ operation = compute_api.client.machines.stop(@machine.id)
83
+ wait_for_operation(env,operation)
84
+ end
85
+
86
+ def delete(env)
87
+ operation = compute_api.client.machines.delete(@machine.id)
88
+ wait_for_operation(env,operation)
89
+ end
90
+
91
+ protected
92
+
93
+ def wait_for_operation(env,operation)
94
+ timestamp = '2018-09-01T23:47:17.50094+02:00'
95
+
96
+ operation_error = nil
97
+
98
+ # wait for operation to be started
99
+ result = retryable(:tries => 20, :sleep => 5) do
100
+ # stop waiting if interrupted
101
+ next if env[:interrupted]
102
+
103
+ result = compute_api.client.operations.get(operation.id)
104
+ yield result if block_given?
105
+
106
+ raise 'Operation not started' if result.status == 'Queued'
107
+ result
108
+ end
109
+
110
+ if result.status == 'Running' then
111
+
112
+ result = retryable(:tries => 20, :sleep => 5) do
113
+ # stop waiting if interrupted
114
+ next if env[:interrupted]
115
+
116
+ # check action status
117
+ result = compute_api.client.operations.get(operation.id, :expand => "LogEntries($filter=Timestamp gt #{timestamp})")
118
+
119
+ result.log_entries.each do |entry|
120
+ env[:ui].info(entry.message)
121
+ timestamp = entry.timestamp
122
+ end
123
+
124
+ yield result if block_given?
125
+
126
+ raise 'Operation not completed' if result.status == 'Running'
127
+ result
128
+ end
129
+ end
130
+
131
+ raise "Operation failed: #{result.status_message}" if result.status == 'Failed'
132
+
133
+ #refresh operation result
134
+ compute_api.client.operations.get(operation.id)
135
+ end
136
+ end
137
+ end
138
+ end
139
+
@@ -1,41 +1,9 @@
1
1
  module VagrantPlugins
2
2
  module Haipa
3
- module Errors
4
- class HaipaError < Vagrant::Errors::VagrantError
5
- error_namespace("vagrant_haipa.errors")
6
- end
7
-
8
- class APIStatusError < HaipaError
9
- error_key(:api_status)
10
- end
11
-
12
- class JSONError < HaipaError
13
- error_key(:json)
14
- end
15
-
16
- class ResultMatchError < HaipaError
17
- error_key(:result_match)
18
- end
19
-
20
- class CertificateError < HaipaError
21
- error_key(:certificate)
22
- end
23
-
24
- class LocalIPError < HaipaError
25
- error_key(:local_ip)
26
- end
27
-
28
- class PublicKeyError < HaipaError
29
- error_key(:public_key)
30
- end
31
-
32
- class RsyncError < HaipaError
33
- error_key(:rsync)
34
- end
35
-
36
- class OperationNotCompleted < HaipaError
37
- error_key(:rsync)
38
- end
3
+ class HaipaError < Vagrant::Errors::VagrantError
4
+ error_namespace("vagrant_haipa.errors")
39
5
  end
6
+
40
7
  end
41
8
  end
9
+
@@ -1,22 +1,23 @@
1
1
  module VagrantPlugins
2
2
  module Haipa
3
- class Plugin < Vagrant.plugin('2')
4
- name 'Haipa'
3
+ class Plugin < Vagrant.plugin("2")
4
+ name "Haipa provider"
5
5
  description <<-DESC
6
- This plugin installs a provider that allows Vagrant to manage
7
- machines using Haipa's API.
6
+ This plugin installs a provider that allows Vagrant to manage
7
+ machines in Haipa.
8
8
  DESC
9
9
 
10
10
  config(:haipa, :provider) do
11
11
  require_relative 'config'
12
12
  Config
13
- end
13
+ end
14
14
 
15
15
  provider(:haipa, parallel: true, defaultable: false, box_optional: true) do
16
16
  require_relative 'provider'
17
17
  Provider
18
18
  end
19
-
20
- end
19
+
20
+ end
21
21
  end
22
22
  end
23
+