vagrant-actionio 0.0.9

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. data/.env-example +4 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +10 -0
  6. data/README.md +110 -0
  7. data/Rakefile +21 -0
  8. data/a.rb +1 -0
  9. data/actionio-dummy.box +0 -0
  10. data/data/cacert.pem +3895 -0
  11. data/example_box/README.md +13 -0
  12. data/example_box/metadata.json +3 -0
  13. data/lib/vagrant-actionio.rb +18 -0
  14. data/lib/vagrant-actionio/action.rb +152 -0
  15. data/lib/vagrant-actionio/action/connect_actionio.rb +31 -0
  16. data/lib/vagrant-actionio/action/is_created.rb +18 -0
  17. data/lib/vagrant-actionio/action/is_running.rb +18 -0
  18. data/lib/vagrant-actionio/action/is_stopped.rb +18 -0
  19. data/lib/vagrant-actionio/action/is_terminated.rb +18 -0
  20. data/lib/vagrant-actionio/action/message_already_created.rb +16 -0
  21. data/lib/vagrant-actionio/action/message_already_terminated.rb +16 -0
  22. data/lib/vagrant-actionio/action/message_cannot_terminate.rb +16 -0
  23. data/lib/vagrant-actionio/action/message_not_created.rb +16 -0
  24. data/lib/vagrant-actionio/action/message_not_running.rb +16 -0
  25. data/lib/vagrant-actionio/action/message_provisioning_not_yet_supported.rb +16 -0
  26. data/lib/vagrant-actionio/action/read_ssh_info.rb +53 -0
  27. data/lib/vagrant-actionio/action/read_state.rb +36 -0
  28. data/lib/vagrant-actionio/action/remove_machine_id.rb +19 -0
  29. data/lib/vagrant-actionio/action/run_instance.rb +94 -0
  30. data/lib/vagrant-actionio/action/start_instance.rb +56 -0
  31. data/lib/vagrant-actionio/action/stop_instance.rb +56 -0
  32. data/lib/vagrant-actionio/action/sync_folders.rb +57 -0
  33. data/lib/vagrant-actionio/action/terminate_instance.rb +57 -0
  34. data/lib/vagrant-actionio/action/timed_provision.rb +21 -0
  35. data/lib/vagrant-actionio/action/warn_networks.rb +19 -0
  36. data/lib/vagrant-actionio/config.rb +75 -0
  37. data/lib/vagrant-actionio/connection.rb +70 -0
  38. data/lib/vagrant-actionio/errors.rb +35 -0
  39. data/lib/vagrant-actionio/plugin.rb +73 -0
  40. data/lib/vagrant-actionio/provider.rb +50 -0
  41. data/lib/vagrant-actionio/util/env.rb +12 -0
  42. data/lib/vagrant-actionio/util/timer.rb +17 -0
  43. data/lib/vagrant-actionio/version.rb +5 -0
  44. data/locales/en.yml +121 -0
  45. data/spec/vagrant-actionio/action/read_ssh_info_spec.rb +58 -0
  46. data/spec/vagrant-actionio/action/read_state_spec.rb +46 -0
  47. data/spec/vagrant-actionio/action/run_instance_spec.rb +24 -0
  48. data/spec/vagrant-actionio/action/start_instance_spec.rb +21 -0
  49. data/spec/vagrant-actionio/action/stop_instance_spec.rb +21 -0
  50. data/spec/vagrant-actionio/action/terminate_instance_spec.rb +21 -0
  51. data/spec/vagrant-actionio/config_spec.rb +47 -0
  52. data/spec/vagrant-actionio/connection_spec.rb +105 -0
  53. data/vagrant-actionio.gemspec +59 -0
  54. metadata +2882 -0
@@ -0,0 +1,70 @@
1
+ require 'vagrant-actionio/util/env'
2
+ require 'vagrant-actionio/errors'
3
+ require 'vagrant-actionio/version'
4
+ require 'oauth2'
5
+
6
+ ENV['SSL_CERT_FILE'] = File.join(File.expand_path('../../../', __FILE__), '/data/cacert.pem')
7
+
8
+ module VagrantPlugins
9
+ module ActionIO
10
+ class Connection
11
+ OAUTH_CLIENT_ID = Util::Env.read_with_default('VAGRANT_ACTIONIO_OAUTH_ID', '414b8765a91db88e3d9d2a391eb19117a652b23ec7c1222fd61ddb59d0298072')
12
+ OAUTH_CLIENT_SECRET = Util::Env.read_with_default('VAGRANT_ACTIONIO_OAUTH_SECRET', 'd64a2c76e05126366d9627f165978a2a810c6b853c853df805e22f7390e59950')
13
+ VERIFY_SSL = ENV['VAGRANT_ACTIONIO_VERIFY_SSL'] != 'false'
14
+ HOST = Util::Env.read_with_default('VAGRANT_ACTIONIO_HOST', 'https://www.action.io')
15
+ API_PATH_PREFIX = '/api/v0'
16
+ USER_AGENT = "Vagrant-ActionIO/#{VERSION} (Vagrant #{Vagrant::VERSION}; #{RUBY_DESCRIPTION})"
17
+
18
+ attr_accessor :client, :token
19
+
20
+ def initialize(access_token_string)
21
+ options = { site: HOST }
22
+ options[:ssl] = { verify_mode: OpenSSL::SSL::VERIFY_NONE } if !VERIFY_SSL
23
+ @client = OAuth2::Client.new(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, options)
24
+ @token = OAuth2::AccessToken.new(client, access_token_string)
25
+ end
26
+
27
+ def request(verb, path, options={})
28
+ options = { parse: :json }.merge options
29
+ options[:headers] ||= {}
30
+ options[:headers]['User-Agent'] = USER_AGENT
31
+
32
+ @token.request verb.to_sym, "#{API_PATH_PREFIX}#{path}", options
33
+ end
34
+
35
+ def verify_access_token
36
+ response = request(:get, '/scopes')
37
+ rescue => e
38
+ if e.response && e.response.status == 401
39
+ raise Errors::APIError, 'invalid_access_token'
40
+ else
41
+ raise e
42
+ end
43
+ else
44
+ if response.status == 200
45
+ json = JSON.parse(response.body)
46
+ if json.kind_of?(Hash) && json['scopes'].split.include?('boxes')
47
+ return
48
+ else
49
+ raise Errors::APIError, 'invalid_access_token_scope'
50
+ end
51
+ end
52
+ end
53
+
54
+ def fetch_box_state(box_id)
55
+ begin
56
+ response = request(:get, "/boxes/#{box_id}")
57
+ rescue => e
58
+ if e.respond_to?(:response) && e.response.status == 404
59
+ # The box can't be found
60
+ return nil
61
+ else
62
+ raise e
63
+ end
64
+ end
65
+
66
+ response.parsed['box']['state'].to_sym
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,35 @@
1
+ require 'vagrant'
2
+
3
+ module VagrantPlugins
4
+ module ActionIO
5
+ module Errors
6
+ class VagrantActionIOError < Vagrant::Errors::VagrantError
7
+ error_namespace('vagrant_actionio.errors')
8
+ end
9
+
10
+ class APIError < VagrantActionIOError
11
+ error_key(:api_error)
12
+ end
13
+
14
+ class BoxNotYetStartedError < VagrantActionIOError
15
+ error_key(:box_not_yet_started_error)
16
+ end
17
+
18
+ class BoxNotYetStoppedError < VagrantActionIOError
19
+ error_key(:box_not_yet_stopped_error)
20
+ end
21
+
22
+ class BoxNotYetTerminatedError < VagrantActionIOError
23
+ error_key(:box_not_yet_terminated_error)
24
+ end
25
+
26
+ class RsyncError < VagrantActionIOError
27
+ error_key(:rsync_error)
28
+ end
29
+
30
+ class TimeoutError < VagrantActionIOError
31
+ error_key(:timeout_error)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant Action.IO plugin must be run within Vagrant.'
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < '1.1.0'
10
+ raise 'The Vagrant Action.IO plugin is only compatible with Vagrant 1.1+'
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module ActionIO
15
+ class Plugin < Vagrant.plugin('2')
16
+ name 'Action.IO'
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ boxes in Action.IO.
20
+ DESC
21
+
22
+ config(:actionio, :provider) do
23
+ require_relative 'config'
24
+ Config
25
+ end
26
+
27
+ provider(:actionio) do
28
+ # Setup logging and i18n
29
+ setup_logging
30
+ setup_i18n
31
+
32
+ # Return the provider
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', ActionIO.source_root)
40
+ I18n.reload!
41
+ end
42
+
43
+ # This sets up our log level to be whatever VAGRANT_LOG is.
44
+ def self.setup_logging
45
+ require 'log4r'
46
+
47
+ level = nil
48
+ begin
49
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
50
+ rescue NameError
51
+ # This means that the logging constant wasn't found,
52
+ # which is fine. We just keep `level` as `nil`. But
53
+ # we tell the user.
54
+ level = nil
55
+ end
56
+
57
+ # Some constants, such as "true" resolve to booleans, so the
58
+ # above error checking doesn't catch it. This will check to make
59
+ # sure that the log level is an integer, as Log4r requires.
60
+ level = nil if !level.is_a?(Integer)
61
+
62
+ # Set the logging level on all "vagrant" namespaced
63
+ # logs as long as we have a valid level.
64
+ if level
65
+ logger = Log4r::Logger.new('vagrant_actionio')
66
+ logger.outputters = Log4r::Outputter.stderr
67
+ logger.level = level
68
+ logger = nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,50 @@
1
+ require 'log4r'
2
+ require 'vagrant'
3
+
4
+ module VagrantPlugins
5
+ module ActionIO
6
+ class Provider < Vagrant.plugin('2', :provider)
7
+ def initialize(machine)
8
+ @machine = machine
9
+ end
10
+
11
+ def action(name)
12
+ # Attempt to get the action method from the Action class if it
13
+ # exists, otherwise return nil to show that we don't support the
14
+ # given action.
15
+ action_method = "action_#{name}"
16
+ return Action.send(action_method) if Action.respond_to?(action_method)
17
+ nil
18
+ end
19
+
20
+ def ssh_info
21
+ # Run a custom action called 'read_ssh_info' which does what it
22
+ # says and puts the resulting SSH info into the `:machine_ssh_info`
23
+ # key in the environment.
24
+ env = @machine.action('read_ssh_info')
25
+ env[:machine_ssh_info]
26
+ end
27
+
28
+ def state
29
+ # Run a custom action we define called 'read_state' which does
30
+ # what it says. It puts the state in the `:machine_state_id`
31
+ # key in the environment.
32
+ env = @machine.action('read_state')
33
+
34
+ state_id = env[:machine_state_id]
35
+
36
+ # Get the short and long description
37
+ short = I18n.t("vagrant_actionio.states.short_#{state_id}")
38
+ long = I18n.t("vagrant_actionio.states.long_#{state_id}")
39
+
40
+ # Return the MachineState object
41
+ Vagrant::MachineState.new(state_id, short, long)
42
+ end
43
+
44
+ def to_s
45
+ id = @machine.id.nil? ? 'new' : @machine.id
46
+ "Action.IO (#{id})"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module VagrantPlugins
2
+ module ActionIO
3
+ module Util
4
+ class Env
5
+ def self.read_with_default(env_var, default)
6
+ value = ENV[env_var]
7
+ value.nil? ? default : value
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module ActionIO
3
+ module Util
4
+ class Timer
5
+ # A basic utility method that times the execution of the given
6
+ # block and returns it.
7
+ def self.time
8
+ start_time = Time.now.to_f
9
+ yield
10
+ end_time = Time.now.to_f
11
+
12
+ end_time - start_time
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module ActionIO
3
+ VERSION = '0.0.9'
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,121 @@
1
+ en:
2
+ vagrant_actionio:
3
+ already_created: |-
4
+ The box already exists on Action.IO.
5
+ already_terminated: |-
6
+ The box is already terminated on Action.IO.
7
+ cannot_terminate: |-
8
+ The box needs to be in either "running" or "stopped" state to be terminatable.
9
+ launching_box: |-
10
+ Launching a box on Action.IO with the following settings...
11
+ not_created: |-
12
+ Your box on Action.IO is not created. Please create your box by running `vagrant up` first.
13
+ not_running: |-
14
+ Your box on Action.IO is not running. Please start your box by running `vagrant up` first.
15
+ provisioning_not_yet_supported: |-
16
+ Vagrant provisioning is coming soon, but not yet supported. Please check https://github.com/action-io/vagrant-actionio for updates.
17
+ ready: |-
18
+ Your box on Action.IO is running and ready for use!
19
+ rsync_folder: |-
20
+ Rsyncing folder: %{hostpath} => %{guestpath}
21
+ starting_box: |-
22
+ Starting the box on Action.IO...
23
+ stopped: |-
24
+ Your box on Action.IO is stopped.
25
+ stopping_box: |-
26
+ Stopping the box on Action.IO...
27
+ terminated: |-
28
+ Your box on Action.IO is terminated.
29
+ terminating_box: |-
30
+ Terminating the box on Action.IO...
31
+ warn_networks: |-
32
+ Warning! The Action.IO provider doesn't support any of the Vagrant
33
+ high-level network configurations (`config.vm.network`). They
34
+ will be silently ignored.
35
+
36
+ config:
37
+ access_token_required: |-
38
+ An access token must be specified via "access_token"
39
+
40
+ private_key_missing: |-
41
+ The specified SSH private key could not be found
42
+
43
+ region_required: |-
44
+ A region must be specified via "region"
45
+
46
+ ssh_private_key_path_required: |-
47
+ A path to an ssh private key must be specified via "ssh_private_key_path"
48
+
49
+ errors:
50
+ api_error: |-
51
+ There was an error talking to Action.IO. The error message is shown below:
52
+
53
+ %{message}
54
+
55
+ box_not_yet_started_error: |-
56
+ Box is not yet started.
57
+
58
+ box_not_yet_stopped_error: |-
59
+ Box is not yet stopped.
60
+
61
+ box_not_yet_terminated_error: |-
62
+ Box is not yet terminated.
63
+
64
+ invalid_access_token: |-
65
+ Access token is invalid.
66
+
67
+ invalid_access_token_scope: |-
68
+ Access token does not have "boxes" scope.
69
+
70
+ rsync_error: |-
71
+ There was an error when attemping to rsync a shared folder.
72
+ Please inspect the error message below for more info.
73
+
74
+ Host path: %{hostpath}
75
+ Guest path: %{guestpath}
76
+ Error: %{stderr}
77
+
78
+ timeout_error: |-
79
+ Box creation timed out.
80
+
81
+ states:
82
+ short_not_created: |-
83
+ not created
84
+ long_not_created: |-
85
+ The Action.IO box is not created. Run `vagrant up` to create it.
86
+
87
+ short_provisioning: |-
88
+ provisioning
89
+ long_provisioning: |-
90
+ The Action.IO box is being created.
91
+
92
+ short_running: |-
93
+ running
94
+ long_running: |-
95
+ The Action.IO box is running. To stop this machine, you can run
96
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
97
+
98
+ short_starting: |-
99
+ starting
100
+ long_starting: |-
101
+ The Action.IO box is starting.
102
+
103
+ short_stopped: |-
104
+ stopped
105
+ long_stopped: |-
106
+ The Action.IO box is stopped. Run `vagrant up` to start it.
107
+
108
+ short_stopping: |-
109
+ stopping
110
+ long_stopping: |-
111
+ The Action.IO box is stopping.
112
+
113
+ short_terminated: |-
114
+ terminated
115
+ long_terminated: |-
116
+ The Action.IO box is terminated.
117
+
118
+ short_terminating: |-
119
+ terminating
120
+ long_terminating: |-
121
+ The Action.IO box is terminating.
@@ -0,0 +1,58 @@
1
+ require 'vagrant-actionio/action/read_ssh_info'
2
+ require 'ostruct'
3
+
4
+ describe VagrantPlugins::ActionIO::Action::ReadSSHInfo do
5
+ let(:app) { double 'app', call: nil }
6
+ let(:instance) { VagrantPlugins::ActionIO::Action::ReadSSHInfo.new(app, env) }
7
+
8
+ context 'when machine id is nil' do
9
+ let(:machine) { double 'machine', id: nil }
10
+ let(:env) { { actionio: nil, machine: machine } }
11
+
12
+ it 'returns nil' do
13
+ instance.call(env)
14
+ expect(env[:machine_ssh_info]).to be_nil
15
+ end
16
+ end
17
+
18
+ context 'when machine id is not nil' do
19
+ let(:machine) { OpenStruct.new(id: 123) }
20
+ let!(:actionio) { double 'connection', request: nil }
21
+ let(:env) { { actionio: actionio, machine: machine } }
22
+
23
+ context 'when request is successful' do
24
+ before do
25
+ json = '{"box":{"id":123,"host":"foo-box-123.usw1.actionbox.io","port":12345}}'
26
+ response = double 'response', status: 200, body: json, parsed: JSON.parse(json)
27
+ actionio.should_receive(:request).with(:get, '/boxes/123').and_return response
28
+ machine.stub_chain(:provider_config, :ssh_private_key_path).and_return '/home/action/.ssh/id_rsa'
29
+ end
30
+
31
+ it 'makes a get request to /boxes/:id and returns a hash containing the ssh info' do
32
+ instance.call(env)
33
+ expect(env[:machine_ssh_info]).to eq({
34
+ host: 'foo-box-123.usw1.actionbox.io',
35
+ port: '12345',
36
+ private_key_path: '/home/action/.ssh/id_rsa',
37
+ username: 'action'
38
+ })
39
+ end
40
+ end
41
+
42
+ context 'when request returns 404' do
43
+ before do
44
+ response = double 'response', status: 404
45
+ error = StandardError.new('request error')
46
+ error.stub(:response) { response }
47
+ actionio.should_receive(:request).with(:get, '/boxes/123').and_raise error
48
+ end
49
+
50
+ it 'sets machine id to be nil and returns nil' do
51
+ instance.call(env)
52
+ expect(env[:machine].id).to be_nil
53
+ expect(env[:machine_ssh_info]).to be_nil
54
+ end
55
+ end
56
+ end
57
+ end
58
+