vagrant-haipa 0.0.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
+