vagrant-linode 0.1.3 → 0.2.0

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rspec +4 -0
  4. data/.rubocop.yml +1 -0
  5. data/.rubocop_todo.yml +164 -0
  6. data/Gemfile +9 -6
  7. data/README.md +21 -9
  8. data/Rakefile +21 -1
  9. data/Vagrantfile.multi +18 -0
  10. data/box/linode-debian-7.5.box +0 -0
  11. data/box/linode.box +0 -0
  12. data/box/metadata-debian-7.5.json +12 -0
  13. data/box/metadata.json +2 -2
  14. data/features/provision.feature +34 -0
  15. data/features/steps/sdk_steps.rb +13 -0
  16. data/features/steps/server_steps.rb +25 -0
  17. data/features/support/env.rb +34 -0
  18. data/features/support/fog_mock.rb +16 -0
  19. data/features/vagrant-linode.feature +68 -0
  20. data/lib/vagrant-linode.rb +44 -5
  21. data/lib/vagrant-linode/actions.rb +201 -87
  22. data/lib/vagrant-linode/actions/connect_linode.rb +36 -0
  23. data/lib/vagrant-linode/actions/create.rb +9 -9
  24. data/lib/vagrant-linode/actions/create_image.rb +23 -0
  25. data/lib/vagrant-linode/actions/destroy.rb +1 -3
  26. data/lib/vagrant-linode/actions/halt.rb +29 -0
  27. data/lib/vagrant-linode/actions/is_created.rb +16 -0
  28. data/lib/vagrant-linode/actions/is_stopped.rb +17 -0
  29. data/lib/vagrant-linode/actions/list_datacenters.rb +20 -0
  30. data/lib/vagrant-linode/actions/list_distributions.rb +20 -0
  31. data/lib/vagrant-linode/actions/list_images.rb +20 -0
  32. data/lib/vagrant-linode/actions/list_plans.rb +20 -0
  33. data/lib/vagrant-linode/actions/list_servers.rb +20 -0
  34. data/lib/vagrant-linode/actions/message_already_active.rb +16 -0
  35. data/lib/vagrant-linode/actions/message_already_off.rb +16 -0
  36. data/lib/vagrant-linode/actions/message_not_created.rb +16 -0
  37. data/lib/vagrant-linode/actions/message_off.rb +16 -0
  38. data/lib/vagrant-linode/actions/power_off.rb +4 -3
  39. data/lib/vagrant-linode/actions/power_on.rb +3 -2
  40. data/lib/vagrant-linode/actions/read_ssh_info.rb +48 -0
  41. data/lib/vagrant-linode/actions/read_state.rb +38 -0
  42. data/lib/vagrant-linode/actions/rebuild.rb +3 -2
  43. data/lib/vagrant-linode/actions/reload.rb +3 -2
  44. data/lib/vagrant-linode/commands/create_image.rb +21 -0
  45. data/lib/vagrant-linode/commands/datacenters.rb +21 -0
  46. data/lib/vagrant-linode/commands/distributions.rb +21 -0
  47. data/lib/vagrant-linode/commands/images.rb +59 -0
  48. data/lib/vagrant-linode/commands/list_images.rb +21 -0
  49. data/lib/vagrant-linode/commands/networks.rb +21 -0
  50. data/lib/vagrant-linode/commands/plans.rb +21 -0
  51. data/lib/vagrant-linode/commands/root.rb +81 -0
  52. data/lib/vagrant-linode/commands/servers.rb +21 -0
  53. data/lib/vagrant-linode/config.rb +11 -3
  54. data/lib/vagrant-linode/helpers/client.rb +21 -79
  55. data/lib/vagrant-linode/helpers/waiter.rb +21 -0
  56. data/lib/vagrant-linode/plugin.rb +20 -0
  57. data/lib/vagrant-linode/provider.rb +27 -32
  58. data/lib/vagrant-linode/version.rb +1 -1
  59. data/locales/en.yml +17 -1
  60. data/spec/spec_helper.rb +20 -0
  61. data/spec/vagrant-linode/actions/list_distributions_spec.rb +47 -0
  62. data/spec/vagrant-linode/actions/list_plans_spec.rb +47 -0
  63. data/spec/vagrant-linode/config_spec.rb +189 -0
  64. data/test/Vagrantfile +4 -9
  65. data/vagrant-linode.gemspec +1 -1
  66. metadata +70 -20
  67. data/lib/vagrant-linode/actions/check_state.rb +0 -19
  68. data/lib/vagrant-linode/actions/setup_key.rb +0 -52
@@ -8,26 +8,26 @@ include Vagrant::Util::Retryable
8
8
  module VagrantPlugins
9
9
  module Linode
10
10
  module Helpers
11
- module Client
12
- def client
13
- def wait_for_event(env, id)
14
- retryable(tries: 120, sleep: 10) do
15
- # stop waiting if interrupted
16
- next if env[:interrupted]
17
- # check action status
18
- result = @client.linode.job.list(jobid: id, linodeid: env[:machine].id)
19
- result = result[0] if result.is_a?(Array)
20
-
21
- yield result if block_given?
22
- fail 'not ready' if result['host_finish_dt'] > ''
23
- end
24
- end
25
- linodeapi = ::LinodeAPI::Raw.new(apikey: @machine.provider_config.token,
26
- endpoint: @machine.provider_config.api_url || nil)
27
- # linodeapi.wait_for_event = wait_for_event
28
- # linodeapi.extend wait_for_event
29
- end
30
- end
11
+ # module Client
12
+ # def client
13
+ # def wait_for_event(env, id)
14
+ # retryable(tries: 120, sleep: 10) do
15
+ # # stop waiting if interrupted
16
+ # next if env[:interrupted]
17
+ # # check action status
18
+ # result = @client.linode.job.list(jobid: id, linodeid: env[:machine].id)
19
+ # result = result[0] if result.is_a?(Array)
20
+ #
21
+ # yield result if block_given?
22
+ # fail 'not ready' if result['host_finish_dt'] > ''
23
+ # end
24
+ # end
25
+ # linodeapi = ::LinodeAPI::Raw.new(apikey: @machine.provider_config.api_key,
26
+ # endpoint: @machine.provider_config.api_url || nil)
27
+ # # linodeapi.wait_for_event = wait_for_event
28
+ # # linodeapi.extend wait_for_event
29
+ # end
30
+ # end
31
31
 
32
32
  class ApiClient
33
33
  include Vagrant::Util::Retryable
@@ -35,69 +35,11 @@ module VagrantPlugins
35
35
  def initialize(machine)
36
36
  @logger = Log4r::Logger.new('vagrant::linode::apiclient')
37
37
  @config = machine.provider_config
38
- @client = ::LinodeAPI::Raw.new(apikey: @config.token, endpoint: @config.api_url || nil)
38
+ @client = ::LinodeAPI::Raw.new(apikey: @config.api_key, endpoint: @config.api_url || nil)
39
39
  end
40
40
 
41
41
  attr_reader :client
42
42
 
43
- def delete(path, params = {}, _method = :delete)
44
- @client.request :url_encoded
45
- request(path, params, :delete)
46
- end
47
-
48
- def post(path, params = {}, _method = :post)
49
- @client.headers['Content-Type'] = 'application/json'
50
- request(path, params, :post)
51
- end
52
-
53
- def request(path, params = {}, method = :get)
54
- begin
55
- @logger.info "Request: #{path}"
56
- result = @client.send(method) do |req|
57
- req.url path, params
58
- req.headers['Authorization'] = "Bearer #{@config.token}"
59
- end
60
- rescue Faraday::Error::ConnectionFailed => e
61
- # TODO this is suspect but because farady wraps the exception
62
- # in something generic there doesn't appear to be another
63
- # way to distinguish different connection errors :(
64
- if e.message =~ /certificate verify failed/
65
- raise Errors::CertificateError
66
- end
67
-
68
- raise e
69
- end
70
-
71
- unless method == :delete
72
- begin
73
- body = JSON.parse(result.body)
74
- @logger.info "Response: #{body}"
75
- next_page = body['links']['pages']['next'] rescue nil
76
- unless next_page.nil?
77
- uri = URI.parse(next_page)
78
- new_path = path.split('?')[0]
79
- next_result = request("#{new_path}?#{uri.query}")
80
- req_target = new_path.split('/')[-1]
81
- body["#{req_target}"].concat(next_result["#{req_target}"])
82
- end
83
- rescue JSON::ParserError => e
84
- raise(Errors::JSONError, message: e.message,
85
- path: path,
86
- params: params,
87
- response: result.body)
88
- end
89
- end
90
-
91
- unless /^2\d\d$/ =~ result.status.to_s
92
- fail(Errors::APIStatusError, path: path,
93
- params: params,
94
- status: result.status,
95
- response: body.inspect)
96
- end
97
-
98
- Result.new(body)
99
- end
100
-
101
43
  def wait_for_event(env, id)
102
44
  retryable(tries: 120, sleep: 10) do
103
45
  # stop waiting if interrupted
@@ -0,0 +1,21 @@
1
+ module VagrantPlugins
2
+ module Linode
3
+ module Helpers
4
+ module Waiter
5
+ include Vagrant::Util::Retryable
6
+ def wait_for_event(env, id)
7
+ retryable(tries: 120, sleep: 10) do
8
+ # stop waiting if interrupted
9
+ next if env[:interrupted]
10
+ # check action status
11
+ result = env[:linode_api].linode.job.list(jobid: id, linodeid: env[:machine].id)
12
+ result = result[0] if result.is_a?(Array)
13
+
14
+ yield result if block_given?
15
+ fail 'not ready' if result['host_finish_dt'] > ''
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,15 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Linode provider 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
+ fail 'Linode provider is only compatible with Vagrant 1.1+'
11
+ end
12
+
1
13
  module VagrantPlugins
2
14
  module Linode
3
15
  class Plugin < Vagrant.plugin('2')
@@ -13,10 +25,18 @@ module VagrantPlugins
13
25
  end
14
26
 
15
27
  provider(:linode, parallel: true) do
28
+ Linode.init_i18n
29
+ Linode.init_logging
30
+
16
31
  require_relative 'provider'
17
32
  Provider
18
33
  end
19
34
 
35
+ command(:linode) do
36
+ require_relative 'commands/root'
37
+ Commands::Root
38
+ end
39
+
20
40
  command(:rebuild) do
21
41
  require_relative 'commands/rebuild'
22
42
  Commands::Rebuild
@@ -1,13 +1,22 @@
1
+ require 'vagrant-linode/helpers/client'
1
2
  require 'vagrant-linode/actions'
2
3
 
3
4
  module VagrantPlugins
4
5
  module Linode
5
6
  class Provider < Vagrant.plugin('2', :provider)
7
+ def initialize(machine)
8
+ @machine = machine
9
+ end
10
+
6
11
  # This class method caches status for all linodes within
7
12
  # the Linode account. A specific linode's status
8
13
  # may be refreshed by passing :refresh => true as an option.
9
14
  def self.linode(machine, opts = {})
10
- client = Helpers::ApiClient.new(machine).client
15
+ client = Helpers::ApiClient.new(machine).client
16
+
17
+ # @todo how do I reuse VagrantPlugins::Linode::Actions::ConnectLinode ?
18
+ # ..and nuke the helper
19
+ # client = env[:linode_api]
11
20
 
12
21
  # load status of linodes if it has not been done before
13
22
  unless @linodes
@@ -20,7 +29,7 @@ module VagrantPlugins
20
29
  linode = client.linode.list(linodeid: machine.id).first
21
30
  linode.network = client.linode.ip.list linodeid: linode['linodeid']
22
31
  @linodes << linode
23
- else
32
+ elsif machine.id
24
33
  # lookup linode status for the given machine
25
34
  linode = @linodes.find { |d| d['linodeid'].to_s == machine.id }
26
35
  end
@@ -37,15 +46,12 @@ module VagrantPlugins
37
46
  linode ||= { status: :not_created }
38
47
  end
39
48
 
40
- def initialize(machine)
41
- @machine = machine
42
- end
43
-
44
49
  # Attempt to get the action method from the Action class if it
45
50
  # exists, otherwise return nil to show that we don't support the
46
51
  # given action.
47
52
  def action(name)
48
- return Actions.send(name) if Actions.respond_to?(name)
53
+ action_method = "action_#{name}"
54
+ return Actions.send(action_method) if Actions.respond_to?(action_method)
49
55
  nil
50
56
  end
51
57
 
@@ -56,6 +62,9 @@ module VagrantPlugins
56
62
  # is simply the machine instance given to this object. And no
57
63
  # return value is necessary.
58
64
  def machine_id_changed
65
+ if @machine.id
66
+ Provider.linode(@machine, refresh: true)
67
+ end
59
68
  end
60
69
 
61
70
  # This should return a hash of information that explains how to
@@ -77,40 +86,26 @@ module VagrantPlugins
77
86
  # `ssh` prompt with a password, whereas we can pass a private key
78
87
  # via commandline.
79
88
  def ssh_info
80
- linode = Provider.linode(@machine, refresh: true)
81
-
82
- return nil if self.state.id != :active
83
-
84
- public_network = linode.network.find { |network| network['ispublic'] == 1 }
85
-
86
- {
87
- host: public_network['ipaddress'],
88
- port: '22',
89
- username: 'root',
90
- private_key_path: @machine.config.ssh.private_key_path
91
- }
89
+ env = @machine.action('read_ssh_info')
90
+ env[:machine_ssh_info]
92
91
  end
93
92
 
94
93
  # This should return the state of the machine within this provider.
95
94
  # The state must be an instance of {MachineState}. Please read the
96
95
  # documentation of that class for more information.
97
96
  def state
98
- status = Provider.linode(@machine)['status']
99
- states = {
100
- "" => :not_created,
101
- '-2' => :boot_failed,
102
- '-1' => :being_created,
103
- '0' => :brand_new, # brand new
104
- '1' => :active, # running
105
- '2' => :off, # powered off
106
- '3' => :shutting_down
107
- }
108
- id = long = short = states[status.to_s]
109
- Vagrant::MachineState.new(id, short, long)
97
+ env = @machine.action('read_state')
98
+ state_id = env[:machine_state]
99
+
100
+ short = I18n.t("vagrant_linode.states.short_#{state_id}")
101
+ long = I18n.t("vagrant_linode.states.long_#{state_id}")
102
+
103
+ Vagrant::MachineState.new(state_id, short, long)
110
104
  end
111
105
 
112
106
  def to_s
113
- "Linode"
107
+ id = @machine.id.nil? ? 'new' : @machine.id
108
+ "Linode (#{id})"
114
109
  end
115
110
  end
116
111
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Linode
3
- VERSION = '0.1.3'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -23,8 +23,24 @@ en:
23
23
  trying_rsync_install: "Rsync not found, attempting to install with yum..."
24
24
  rsyncing: "Rsyncing folder: %{hostpath} => %{guestpath}..."
25
25
  rsync_missing: "The rsync executable was not found in the current path."
26
+ states:
27
+ short_not_created: "Not Created"
28
+ short_boot_failed: "Boot Failed"
29
+ short_being_created: "Being Created"
30
+ short_brand_new: "Brand New"
31
+ short_active: "Active"
32
+ short_off: "Powered Off"
33
+ short_shutting_down: "Shutting Down"
34
+ long_not_created: "Linode has not been created"
35
+ long_boot_failed: "Linode boot failed"
36
+ long_being_created: "Linode is created"
37
+ long_brand_new: "Linode is brand new"
38
+ long_active: "Linode is active"
39
+ long_off: "Linode is powered off"
40
+ long_shutting_down: "Linode is shutting down"
26
41
  config:
27
- token: "Token is required"
42
+ api_key: "API Key is required"
43
+ token: "Config option token is deprecated. Use api_key."
28
44
  private_key: "SSH private key path is required"
29
45
  public_key: "SSH public key not found: %{key}"
30
46
  disk_too_large: "Disk Images use more drive space than plan allocates"
@@ -0,0 +1,20 @@
1
+ if ENV['COVERAGE'] != 'false'
2
+ require 'simplecov'
3
+ require 'coveralls'
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
9
+
10
+ # Normally classes are lazily loaded, so any class without a test
11
+ # is missing from the report. This ensures they show up so we can
12
+ # see uncovered methods.
13
+ require 'vagrant'
14
+ Dir['lib/**/*.rb'].each do|file|
15
+ require_string = file.match(/lib\/(.*)\.rb/)[1]
16
+ require require_string
17
+ end
18
+ end
19
+
20
+ require 'linode'
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'vagrant-linode/actions/list_distributions'
3
+
4
+ describe VagrantPlugins::Linode::Actions::ListImages do
5
+ let(:app) { lambda { |_env| } }
6
+ let(:ui) { Vagrant::UI::Silent.new }
7
+ let(:distributions) do
8
+ Fog.mock!
9
+ Fog::Compute.new(provider: :linode,
10
+ linode_region: :dfw,
11
+ linode_api_key: 'anything',
12
+ linode_username: 'anything').distributions
13
+ end
14
+ let(:compute_connection) { double('fog connection') }
15
+ let(:env) do
16
+ {
17
+ linode_compute: compute_connection,
18
+ ui: ui
19
+ }
20
+ end
21
+
22
+ subject(:action) { described_class.new(app, env) }
23
+
24
+ before do
25
+ allow(compute_connection).to receive(:distributions).and_return distributions
26
+ end
27
+
28
+ it 'get distributions from Fog' do
29
+ expect(compute_connection).to receive(:distributions).and_return distributions
30
+ action.call(env)
31
+ end
32
+
33
+ it 'writes a sorted, formatted image table to Vagrant::UI' do
34
+ header_line = '%-36s %s' % ['Image ID', 'Image Name']
35
+ expect(ui).to receive(:info).with(header_line)
36
+ distributions.sort_by(&:name).each do |image|
37
+ formatted_line = '%-36s %s' % [image.id.to_s, image.name]
38
+ expect(ui).to receive(:info).with formatted_line
39
+ end
40
+ action.call(env)
41
+ end
42
+
43
+ it 'continues the middleware chain' do
44
+ expect(app).to receive(:call).with(env)
45
+ action.call(env)
46
+ end
47
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'vagrant-linode/actions/list_plans'
3
+
4
+ describe VagrantPlugins::Linode::Actions::ListPlans do
5
+ let(:app) { lambda { |_env| } }
6
+ let(:ui) { Vagrant::UI::Silent.new }
7
+ let(:plans) do
8
+ Fog.mock!
9
+ Fog::Compute.new(provider: :linode,
10
+ linode_datacenter: :dallas,
11
+ linode_api_key: 'anything',
12
+ linode_username: 'anything').plans
13
+ end
14
+ let(:compute_connection) { double('fog connection') }
15
+ let(:env) do
16
+ {
17
+ linode_compute: compute_connection,
18
+ ui: ui
19
+ }
20
+ end
21
+
22
+ subject(:action) { described_class.new(app, env) }
23
+
24
+ before do
25
+ allow(compute_connection).to receive(:plans).and_return plans
26
+ end
27
+
28
+ it 'get plans from Fog' do
29
+ expect(compute_connection).to receive(:plans).and_return plans
30
+ action.call(env)
31
+ end
32
+
33
+ it 'writes a sorted, formatted plan table to Vagrant::UI' do
34
+ header_line = '%-36s %s' % ['Plan ID', 'Plan Name']
35
+ expect(ui).to receive(:info).with(header_line)
36
+ plans.sort_by(&:id).each do |plan|
37
+ formatted_line = '%-36s %s' % [plan.id, plan.name]
38
+ expect(ui).to receive(:info).with formatted_line
39
+ end
40
+ action.call(env)
41
+ end
42
+
43
+ it 'continues the middleware chain' do
44
+ expect(app).to receive(:call).with(env)
45
+ action.call(env)
46
+ end
47
+ end
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+ require 'vagrant-linode/config'
3
+
4
+ describe VagrantPlugins::Linode::Config do
5
+ describe 'defaults' do
6
+ let(:vagrant_public_key) { Vagrant.source_root.join('keys/vagrant.pub') }
7
+
8
+ subject do
9
+ super().tap(&:finalize!)
10
+ end
11
+
12
+ its(:api_key) { should be_nil }
13
+ its(:api_url) { should be_nil }
14
+ its(:distribution) { should eq(/Ubuntu/) }
15
+ its(:datacenter) { should eq(/dallas/) }
16
+ its(:plan) { should eq(/1024/) }
17
+ its(:paymentterm) { should eq(/1/) }
18
+ its(:private_networking) { should eq(/Ubuntu/) }
19
+ its(:ca_path) { should eql(vagrant_public_key) }
20
+ its(:ssh_key_name) { should eq(/Vagrant/) }
21
+ its(:setup) { should eq(true) }
22
+ its(:xvda_size) { should eq(true) }
23
+ its(:swap_size) { should eq(256) }
24
+ end
25
+
26
+ describe 'overriding defaults' do
27
+ [:api_key,
28
+ :api_url,
29
+ :distribution,
30
+ :plan,
31
+ :paymentterm,
32
+ :private_networking,
33
+ :ca_path,
34
+ :ssh_key_name,
35
+ :setup,
36
+ :xvda_size,
37
+ :swap_size].each do |attribute|
38
+ it "should not default #{attribute} if overridden" do
39
+ subject.send("#{attribute}=".to_sym, 'foo')
40
+ subject.finalize!
41
+ subject.send(attribute).should == 'foo'
42
+ end
43
+ end
44
+
45
+ it 'should not default plan if overridden' do
46
+ plan = 'Linode 2048'
47
+ subject.send(:plan, plan)
48
+ subject.finalize!
49
+ subject.send(:plan).should include(plan)
50
+ end
51
+
52
+ end
53
+
54
+ describe 'validation' do
55
+ let(:machine) { double('machine') }
56
+ let(:validation_errors) { subject.validate(machine)['Linode Provider'] }
57
+ let(:error_message) { double('error message') }
58
+
59
+ before(:each) do
60
+ machine.stub_chain(:env, :root_path).and_return '/'
61
+ subject.api_key = 'bar'
62
+ end
63
+
64
+ subject do
65
+ super().tap(&:finalize!)
66
+ end
67
+
68
+ context 'with invalid key' do
69
+ it 'should raise an error' do
70
+ subject.nonsense1 = true
71
+ subject.nonsense2 = false
72
+ I18n.should_receive(:t).with('vagrant.config.common.bad_field',
73
+ fields: 'nonsense1, nonsense2')
74
+ .and_return error_message
75
+ validation_errors.first.should == error_message
76
+ end
77
+ end
78
+ context 'with good values' do
79
+ it 'should validate' do
80
+ validation_errors.should be_empty
81
+ end
82
+ end
83
+
84
+ context 'the API key' do
85
+ it 'should error if not given' do
86
+ subject.api_key = nil
87
+ I18n.should_receive(:t).with('vagrant_linode.config.api_key').and_return error_message
88
+ validation_errors.first.should == error_message
89
+ end
90
+ end
91
+
92
+ context 'the public key path' do
93
+ it "should have errors if the key doesn't exist" do
94
+ subject.public_key_path = 'missing'
95
+ I18n.should_receive(:t).with('vagrant_linode.config.public_key_not_found').and_return error_message
96
+ validation_errors.first.should == error_message
97
+ end
98
+ it 'should not have errors if the key exists with an absolute path' do
99
+ subject.public_key_path = File.expand_path 'locales/en.yml', Dir.pwd
100
+ validation_errors.should be_empty
101
+ end
102
+ it 'should not have errors if the key exists with a relative path' do
103
+ machine.stub_chain(:env, :root_path).and_return '.'
104
+ subject.public_key_path = 'locales/en.yml'
105
+ validation_errors.should be_empty
106
+ end
107
+ end
108
+
109
+ context 'the username' do
110
+ it 'should error if not given' do
111
+ subject.username = nil
112
+ I18n.should_receive(:t).with('vagrant_linode.config.username_required').and_return error_message
113
+ validation_errors.first.should == error_message
114
+ end
115
+ end
116
+
117
+ [:linode_compute_url, :linode_auth_url].each do |url|
118
+ context "the #{url}" do
119
+ it 'should not validate if the URL is invalid' do
120
+ subject.send "#{url}=", 'baz'
121
+ I18n.should_receive(:t).with('vagrant_linode.config.invalid_uri', key: url, uri: 'baz').and_return error_message
122
+ validation_errors.first.should == error_message
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ describe 'linode_auth_url' do
129
+ it 'should return UNSET_VALUE if linode_auth_url and linode_region are UNSET' do
130
+ subject.linode_auth_url.should == VagrantPlugins::Linode::Config::UNSET_VALUE
131
+ end
132
+ it 'should return UNSET_VALUE if linode_auth_url is UNSET and linode_region is :ord' do
133
+ subject.linode_region = :ord
134
+ subject.linode_auth_url.should == VagrantPlugins::Linode::Config::UNSET_VALUE
135
+ end
136
+ it 'should return UK Authentication endpoint if linode_auth_url is UNSET and linode_region is :lon' do
137
+ subject.linode_region = :lon
138
+ subject.linode_auth_url.should == Fog::Linode::UK_AUTH_ENDPOINT
139
+ end
140
+ it 'should return custom endpoint if supplied and linode_region is :lon' do
141
+ my_endpoint = 'http://custom-endpoint.com'
142
+ subject.linode_region = :lon
143
+ subject.linode_auth_url = my_endpoint
144
+ subject.linode_auth_url.should == my_endpoint
145
+ end
146
+ it 'should return custom endpoint if supplied and linode_region is UNSET' do
147
+ my_endpoint = 'http://custom-endpoint.com'
148
+ subject.linode_auth_url = my_endpoint
149
+ subject.linode_auth_url.should == my_endpoint
150
+ end
151
+ end
152
+
153
+ describe 'lon_region?' do
154
+ it 'should return false if linode_region is UNSET_VALUE' do
155
+ subject.linode_region = VagrantPlugins::Linode::Config::UNSET_VALUE
156
+ subject.send(:lon_region?).should be_false
157
+ end
158
+ it 'should return false if linode_region is nil' do
159
+ subject.linode_region = nil
160
+ subject.send(:lon_region?).should be_false
161
+ end
162
+ it 'should return false if linode_region is :ord' do
163
+ subject.linode_region = :ord
164
+ subject.send(:lon_region?).should be_false
165
+ end
166
+ it "should return true if linode_region is 'lon'" do
167
+ subject.linode_region = 'lon'
168
+ subject.send(:lon_region?).should be_true
169
+ end
170
+ it 'should return true if linode_Region is :lon' do
171
+ subject.linode_region = :lon
172
+ subject.send(:lon_region?).should be_true
173
+ end
174
+ end
175
+
176
+ describe 'network' do
177
+ it 'should remove SERVICE_NET_ID if :service_net is detached' do
178
+ subject.send(:network, :service_net, attached: false)
179
+ subject.send(:networks).should_not include(VagrantPlugins::Linode::Config::SERVICE_NET_ID)
180
+ end
181
+
182
+ it 'should not allow duplicate networks' do
183
+ net_id = 'deadbeef-0000-0000-0000-000000000000'
184
+ subject.send(:network, net_id)
185
+ subject.send(:network, net_id)
186
+ subject.send(:networks).count(net_id).should == 1
187
+ end
188
+ end
189
+ end