vagrant-softlayer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +15 -0
  2. data/Gemfile +7 -0
  3. data/LICENSE +20 -0
  4. data/README.md +233 -0
  5. data/Rakefile +6 -0
  6. data/dummy.box +0 -0
  7. data/example_box/README.md +13 -0
  8. data/example_box/metadata.json +3 -0
  9. data/lib/vagrant-softlayer/action/create_instance.rb +54 -0
  10. data/lib/vagrant-softlayer/action/destroy_instance.rb +23 -0
  11. data/lib/vagrant-softlayer/action/is.rb +21 -0
  12. data/lib/vagrant-softlayer/action/message.rb +22 -0
  13. data/lib/vagrant-softlayer/action/read_ssh_info.rb +28 -0
  14. data/lib/vagrant-softlayer/action/read_state.rb +42 -0
  15. data/lib/vagrant-softlayer/action/rebuild_instance.rb +35 -0
  16. data/lib/vagrant-softlayer/action/setup_softlayer.rb +37 -0
  17. data/lib/vagrant-softlayer/action/start_instance.rb +21 -0
  18. data/lib/vagrant-softlayer/action/stop_instance.rb +30 -0
  19. data/lib/vagrant-softlayer/action/sync_folders.rb +99 -0
  20. data/lib/vagrant-softlayer/action/update_dns.rb +96 -0
  21. data/lib/vagrant-softlayer/action/wait_for_provision.rb +40 -0
  22. data/lib/vagrant-softlayer/action/wait_for_rebuild.rb +36 -0
  23. data/lib/vagrant-softlayer/action.rb +200 -0
  24. data/lib/vagrant-softlayer/command/rebuild.rb +34 -0
  25. data/lib/vagrant-softlayer/config.rb +178 -0
  26. data/lib/vagrant-softlayer/errors.rb +25 -0
  27. data/lib/vagrant-softlayer/plugin.rb +77 -0
  28. data/lib/vagrant-softlayer/provider.rb +47 -0
  29. data/lib/vagrant-softlayer/util/network.rb +42 -0
  30. data/lib/vagrant-softlayer/util/warden.rb +38 -0
  31. data/lib/vagrant-softlayer/version.rb +5 -0
  32. data/lib/vagrant-softlayer.rb +22 -0
  33. data/locales/en.yml +146 -0
  34. data/spec/spec_helper.rb +1 -0
  35. data/spec/vagrant-softlayer/config_spec.rb +156 -0
  36. data/vagrant-softlayer.gemspec +53 -0
  37. metadata +152 -0
@@ -0,0 +1,25 @@
1
+ module VagrantPlugins
2
+ module SoftLayer
3
+ module Errors
4
+ class VagrantSoftLayerError < Vagrant::Errors::VagrantError
5
+ error_namespace("vagrant_softlayer.errors")
6
+ end
7
+
8
+ class SLApiError < VagrantSoftLayerError
9
+ error_key(:api_error)
10
+ end
11
+
12
+ class SLCertificateError < VagrantSoftLayerError
13
+ error_key(:certificate_error)
14
+ end
15
+
16
+ class SLDNSZoneNotFound < VagrantSoftLayerError
17
+ error_key(:dns_zone_not_found)
18
+ end
19
+
20
+ class SLSshKeyNotFound < VagrantSoftLayerError
21
+ error_key(:ssh_key_not_found)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,77 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant SoftLayer 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.3.0"
10
+ raise "The Vagrant SoftLayer plugin is only compatible with Vagrant 1.3+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module SoftLayer
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "SoftLayer"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ SoftLayer CCI.
20
+ DESC
21
+
22
+ command(:rebuild) do
23
+ require_relative 'command/rebuild'
24
+ Command::Rebuild
25
+ end
26
+
27
+ config(:softlayer, :provider) do
28
+ require_relative "config"
29
+ Config
30
+ end
31
+
32
+ provider(:softlayer) do
33
+ init_logging
34
+ init_i18n
35
+
36
+ require_relative "provider"
37
+ Provider
38
+ end
39
+
40
+ # This initializes the I18n load path so that the plugin specific
41
+ # transations work.
42
+ def self.init_i18n
43
+ I18n.load_path << File.expand_path("locales/en.yml", SoftLayer.source_root)
44
+ I18n.reload!
45
+ end
46
+
47
+ # This sets up our log level to be whatever VAGRANT_LOG is.
48
+ def self.init_logging
49
+ require "log4r"
50
+
51
+ level = nil
52
+ begin
53
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
54
+ rescue NameError
55
+ # This means that the logging constant wasn't found,
56
+ # which is fine. We just keep `level` as `nil`. But
57
+ # we tell the user.
58
+ level = nil
59
+ end
60
+
61
+ # Some constants, such as "true" resolve to booleans, so the
62
+ # above error checking doesn't catch it. This will check to make
63
+ # sure that the log level is an integer, as Log4r requires.
64
+ level = nil if !level.is_a?(Integer)
65
+
66
+ # Set the logging level on all "vagrant" namespaced
67
+ # logs as long as we have a valid level.
68
+ if level
69
+ logger = Log4r::Logger.new("vagrant_softlayer")
70
+ logger.outputters = Log4r::Outputter.stderr
71
+ logger.level = level
72
+ logger = nil
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,47 @@
1
+ module VagrantPlugins
2
+ module SoftLayer
3
+ class Provider < Vagrant.plugin("2", :provider)
4
+ def initialize(machine)
5
+ @machine = machine
6
+ end
7
+
8
+ def action(name)
9
+ # Attempt to get the action method from the Action class if it
10
+ # exists, otherwise return nil to show that we don't support the
11
+ # given action.
12
+ action_method = "action_#{name}"
13
+ return Action.send(action_method) if Action.respond_to?(action_method)
14
+ nil
15
+ end
16
+
17
+ def ssh_info
18
+ # Run a custom action called "read_ssh_info" which does what it
19
+ # says and puts the resulting SSH info into the `:machine_ssh_info`
20
+ # key in the environment.
21
+ env = @machine.action("read_ssh_info")
22
+ env[:machine_ssh_info]
23
+ end
24
+
25
+ def state
26
+ # Run a custom action we define called "read_state" which does
27
+ # what it says. It puts the state in the `:machine_state_id`
28
+ # key in the environment.
29
+ env = @machine.action("read_state")
30
+
31
+ state_id = env[:machine_state_id]
32
+
33
+ # Get the short and long description
34
+ short = I18n.t("vagrant_softlayer.states.short_#{state_id}")
35
+ long = I18n.t("vagrant_softlayer.states.long_#{state_id}")
36
+
37
+ # Return the MachineState object
38
+ Vagrant::MachineState.new(state_id, short, long)
39
+ end
40
+
41
+ def to_s
42
+ id = @machine.id || "new VM"
43
+ "SoftLayer (#{id})"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ module VagrantPlugins
2
+ module SoftLayer
3
+ module Util
4
+ module Network
5
+ # Gets instance's IP address.
6
+ #
7
+ # Returns the private IP address if the instance has been
8
+ # defined as private only, the public IP address otherwise.
9
+ def ip_address(env)
10
+ service = env[:machine].provider_config.private_only ? :getPrimaryBackendIpAddress : :getPrimaryIpAddress
11
+ return sl_warden { env[:sl_machine].send(service) }
12
+ end
13
+
14
+ # Returns SSH keys starting from the configuration parameter.
15
+ #
16
+ # In the configuration, each key could be passed either as an
17
+ # id or as a label. The routine will detect this and lookup
18
+ # the id if needed.
19
+ #
20
+ # The first parameter is the current environment.
21
+ #
22
+ # The second parameter is useful for returning: if it is set
23
+ # the routine will return just the array of ids (this is needed,
24
+ # as an example, for reloading OS), otherwise an hash is
25
+ # returned (this latter case is needed instead for creating
26
+ # an instance).
27
+ def ssh_keys(env, ids_only = false)
28
+ account = ::SoftLayer::Service.new("SoftLayer_Account", env[:sl_credentials])
29
+ acc_keys = sl_warden { account.object_mask("id", "label").getSshKeys }
30
+ key_ids = []
31
+ Array(env[:machine].provider_config.ssh_key).each do |key|
32
+ pattern = key.is_a?(String) ? "label" : "id"
33
+ key_hash = acc_keys.find { |acc_key| acc_key[pattern] == key }
34
+ raise Errors::SLSshKeyNotFound, :key => key unless key_hash
35
+ key_ids << key_hash["id"]
36
+ end
37
+ return (ids_only ? key_ids : key_ids.map { |key_id| { :id => key_id } })
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ module VagrantPlugins
2
+ module SoftLayer
3
+ module Util
4
+ module Warden
5
+ # Handles gracefully SoftLayer API calls.
6
+ #
7
+ # The block code is executed, catching both common
8
+ # connection errors and API exceptions.
9
+ #
10
+ # Optionally, in the not-so-uncommon case when
11
+ # the object (e.g. the SoftLayer instance) is not
12
+ # found, executes a proc and/or retry the API call
13
+ # after some seconds.
14
+ #
15
+ # A future version of the method will add a retry timeout.
16
+ def sl_warden(rescue_proc = nil, retry_interval = 0, &block)
17
+ begin
18
+ yield
19
+ rescue ::OpenSSL::SSL::SSLError
20
+ raise Errors::SLCertificateError
21
+ rescue SocketError, ::SoftLayer::SoftLayerAPIException => e
22
+ if e.class == ::SoftLayer::SoftLayerAPIException && e.message.start_with?("Unable to find object with id")
23
+ out = rescue_proc.call if rescue_proc
24
+ if retry_interval > 0
25
+ sleep retry_interval
26
+ retry
27
+ else
28
+ return out
29
+ end
30
+ else
31
+ raise Errors::SLApiError, :class => e.class, :message => e.message
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module SoftLayer
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ require "pathname"
2
+ require "softlayer_api"
3
+ require "vagrant-softlayer/plugin"
4
+
5
+ module VagrantPlugins
6
+ module SoftLayer
7
+ API_PRIVATE_ENDPOINT = ::SoftLayer::API_PRIVATE_ENDPOINT
8
+ API_PUBLIC_ENDPOINT = ::SoftLayer::API_PUBLIC_ENDPOINT
9
+
10
+ lib_path = Pathname.new(File.expand_path("../vagrant-softlayer", __FILE__))
11
+ autoload :Action, lib_path.join("action")
12
+ autoload :Config, lib_path.join("config")
13
+ autoload :Errors, lib_path.join("errors")
14
+
15
+ # This returns the path to the source of this plugin.
16
+ #
17
+ # @return [Pathname]
18
+ def self.source_root
19
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
20
+ end
21
+ end
22
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,146 @@
1
+ en:
2
+ vagrant_softlayer:
3
+ config:
4
+ api_key_required: |-
5
+ The SoftLayer API key is required. Please specify it
6
+ using the SL_API_KEY environment variable or in the provider
7
+ section of the Vagrantfile:
8
+
9
+ config.vm.provider :softlayer do |sl|
10
+ sl.api_key = "my_API_key"
11
+ end
12
+ domain_required: |-
13
+ The domain of the SoftLayer instance is required.
14
+ Please specify it in the provider section of the Vagrantfile:
15
+
16
+ config.vm.provider :softlayer do |sl|
17
+ sl.domain = "example.com"
18
+ end
19
+ hostname_required: |-
20
+ The hostname of the SoftLayer instance is required.
21
+ Please specify it either with `config.vm.hostname` or
22
+ in the provider section of the Vagrantfile:
23
+
24
+ config.vm.hostname = "vagrant"
25
+
26
+ config.vm.provider :softlayer do |sl|
27
+ sl.hostname = "vagrant"
28
+ end
29
+ ssh_key_required: |-
30
+ At least an SSH key for the instance is required.
31
+ Please specify it, either using name or id, in the
32
+ provider section of the Vagrantfile:
33
+
34
+ config.vm.provider :softlayer do |sl|
35
+ sl.ssh_key = 1
36
+ end
37
+ username_required: |-
38
+ The SoftLayer username is required. Please specify it
39
+ using the SL_USERNAME environment variable or in the provider
40
+ section of the Vagrantfile:
41
+
42
+ config.vm.provider :softlayer do |sl|
43
+ sl.username = "my_username"
44
+ end
45
+ errors:
46
+ api_error: |-
47
+ Vagrant returned an exception while calling the SoftLayer API.
48
+
49
+ Exception class: %{class}
50
+ Exception message: %{message}
51
+ certificate_error: |-
52
+ The secure connection to the SoftLayer API has failed. This is
53
+ generally caused by the OpenSSL configuration associated with
54
+ the Ruby install being unaware of the system specific CA certs.
55
+
56
+ Please ensure that the SSL_CERT_FILE environment variable is set
57
+ with a path to a certificate authority.
58
+
59
+ Linux example:
60
+
61
+ export SSL_CERT_FILE=/opt/vagrant/embedded/cacert.pem
62
+
63
+ Mac OS X example:
64
+
65
+ export SSL_CERT_FILE=/Applications/Vagrant/embedded/cacert.pem
66
+
67
+ Windows example:
68
+
69
+ set SSL_CERT_FILE=C:\HashiCorp\Vagrant\embedded\cacert.pem
70
+ dns_zone_not_found: |-
71
+ The DNS zone you're trying to manage (%{zone}) has not been
72
+ found in the zone list.
73
+ ssh_key_not_found: |-
74
+ The SSH key you're trying to set (%{key}) does not exists in the
75
+ SoftLayer account's keychain.
76
+ states:
77
+ short_not_created: |-
78
+ not created
79
+ long_not_created: |-
80
+ The SoftLayer instance is not created. Run `vagrant up` to create it.
81
+ short_halted: |-
82
+ stopped
83
+ long_halted: |-
84
+ The SoftLayer instance is stopped. Run `vagrant up` to start it.
85
+ short_paused: |-
86
+ paused
87
+ long_paused: |-
88
+ The SoftLayer instance is paused. You need to resume it using another
89
+ SoftLayer client tool (e.g. `sl` command line utility).
90
+ short_running: |-
91
+ running
92
+ long_running: |-
93
+ The SoftLayer instance is running. To stop this machine, you can run
94
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
95
+ short_unknown: |-
96
+ unknown
97
+ long_unknown: |-
98
+ The SoftLayer instance is in an unknown state. You need to check it
99
+ out using SoftLayer administrative interface.
100
+ sync_folders:
101
+ rsync_folder: |-
102
+ Rsyncing folder: %{hostpath} => %{guestpath}
103
+ rsync_not_found: |-
104
+ Warning! Folder sync disabled because the rsync binary is missing in the %{side}.
105
+ Make sure rsync is installed and the binary can be found in the PATH.
106
+ vm:
107
+ already_running: |-
108
+ The SoftLayer instance is already running.
109
+ already_stopped: |-
110
+ The SoftLayer instance is already stopped.
111
+ creating: |-
112
+ Creating a new SoftLayer instance...
113
+ creating_dns_record: |-
114
+ Creating DNS record for the instance...
115
+ deleting_dns_record: |-
116
+ Deleting DNS record for the instance...
117
+ destroying: |-
118
+ Destroying the SoftLayer instance...
119
+ not_destroying: |-
120
+ The SoftLayer instance will not be destroyed, since the confirmation
121
+ was declined.
122
+ not_created: |-
123
+ The SoftLayer instance does not exists.
124
+ not_rebuilding: |-
125
+ The SoftLayer instance will not be rebuilded, since the confirmation
126
+ was declined.
127
+ not_running: |-
128
+ The SoftLayer instance is not running. Please run `vagrant up` first.
129
+ provisioned: |-
130
+ SoftLayer instance successfully provisioned!
131
+ rebuilding: |-
132
+ Rebuilding the SoftLayer instance...
133
+ rebuild_confirmation: |-
134
+ Are you sure you want to rebuild the current VM? [y/N]
135
+ rebuilt: |-
136
+ SoftLayer instance successfully rebuilt!
137
+ starting: |-
138
+ Starting the SoftLayer instance...
139
+ stopping: |-
140
+ Stopping the SoftLayer instance gracefully...
141
+ stopping_force: |-
142
+ Stopping the SoftLayer instance forcibly...
143
+ wait_for_provision: |-
144
+ Waiting for instance provisioning. This may take a few minutes...
145
+ wait_for_rebuild: |-
146
+ Waiting for instance rebuilding. This may take a few minutes...
@@ -0,0 +1 @@
1
+ require_relative "../lib/vagrant-softlayer"
@@ -0,0 +1,156 @@
1
+ require "spec_helper"
2
+
3
+ describe VagrantPlugins::SoftLayer::Config do
4
+ let(:config) { described_class.new }
5
+ let(:machine) { double("machine") }
6
+
7
+ describe "defaults" do
8
+ subject do
9
+ config.tap do |o|
10
+ o.finalize!
11
+ end
12
+ end
13
+
14
+ its("api_key") { should be_nil }
15
+ its("endpoint_url") { should eq VagrantPlugins::SoftLayer::API_PUBLIC_ENDPOINT }
16
+ its("username") { should be_nil }
17
+
18
+ its("datacenter") { should be_nil }
19
+ its("dedicated") { should be_false }
20
+ its("domain") { should be_nil }
21
+ its("hostname") { should be_nil }
22
+ its("hourly_billing") { should be_true }
23
+ its("local_disk") { should be_true }
24
+ its("max_memory") { should eq 1024 }
25
+ its("network_speed") { should eq 10 }
26
+ its("operating_system") { should eq "UBUNTU_LATEST" }
27
+ its("post_install") { should be_nil }
28
+ its("private_only") { should be_false }
29
+ its("ssh_key") { should be_nil }
30
+ its("start_cpus") { should eq 1 }
31
+ its("user_data") { should be_nil }
32
+ its("vlan_private") { should be_nil }
33
+ its("vlan_public") { should be_nil }
34
+
35
+ its("manage_dns") { should be_false }
36
+ end
37
+
38
+ describe "overriding defaults" do
39
+ context "booleans" do
40
+ [true, false].each do |bool|
41
+ [:dedicated, :hourly_billing, :local_disk, :manage_dns, :private_only].each do |attribute|
42
+ it "should accept both true and false for #{attribute}" do
43
+ config.send("#{attribute}=".to_sym, bool)
44
+ config.finalize!
45
+ expect(config.send(attribute)).to eq bool
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ context "integers" do
52
+ [:max_memory, :network_speed, :ssh_key, :start_cpus, :vlan_private, :vlan_public].each do |attribute|
53
+ it "should not default #{attribute} if overridden" do
54
+ config.send("#{attribute}=".to_sym, 999)
55
+ config.finalize!
56
+ expect(config.send(attribute)).to eq 999
57
+ end
58
+ end
59
+ end
60
+
61
+ context "strings" do
62
+ [:api_key, :datacenter, :endpoint_url, :username, :domain, :hostname, :operating_system, :post_install, :ssh_key, :user_data].each do |attribute|
63
+ it "should not default #{attribute} if overridden" do
64
+ config.send("#{attribute}=".to_sym, "foo")
65
+ config.finalize!
66
+ expect(config.send(attribute)).to eq "foo"
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "using SL_ environment variables" do
73
+ before :each do
74
+ ENV.stub(:[]).with("SL_API_KEY").and_return("env_api_key")
75
+ ENV.stub(:[]).with("SL_USERNAME").and_return("env_username")
76
+ end
77
+
78
+ subject do
79
+ config.tap do |o|
80
+ o.finalize!
81
+ end
82
+ end
83
+
84
+ its("api_key") { should eq "env_api_key" }
85
+ its("username") { should eq "env_username" }
86
+ end
87
+
88
+ describe "validation" do
89
+ before :each do
90
+ # Setup some good configuration values
91
+ config.api_key = "An API key"
92
+ config.username = "An username"
93
+
94
+ config.datacenter = "ams01"
95
+ config.dedicated = false
96
+ config.domain = "example.com"
97
+ config.hostname = "vagrant"
98
+ config.hourly_billing = true
99
+ config.local_disk = true
100
+ config.max_memory = 1024
101
+ config.network_speed = 10
102
+ config.operating_system = "UBUNTU_LATEST"
103
+ config.post_install = "http://example.com/foo"
104
+ config.ssh_key = ["First key", "Second key"]
105
+ config.start_cpus = 1
106
+ config.user_data = "some metadata"
107
+ config.vlan_private = 111
108
+ config.vlan_public = 222
109
+
110
+ config.manage_dns = false
111
+
112
+ machine.stub_chain(:config, :vm, :hostname).and_return(nil)
113
+ end
114
+
115
+ it "should validate" do
116
+ config.finalize!
117
+ expect(config.validate(machine)["SoftLayer"]).to have(:no).item
118
+ end
119
+
120
+ it "should fail if API key is not given" do
121
+ config.api_key = nil
122
+ config.finalize!
123
+ expect(config.validate(machine)["SoftLayer"]).to have(1).item
124
+ end
125
+
126
+ it "should fail if username is not given" do
127
+ config.username = nil
128
+ config.finalize!
129
+ expect(config.validate(machine)["SoftLayer"]).to have(1).item
130
+ end
131
+
132
+ it "should fail if domain is not given" do
133
+ config.domain = nil
134
+ config.finalize!
135
+ expect(config.validate(machine)["SoftLayer"]).to have(1).item
136
+ end
137
+
138
+ it "should fail if hostname is not given" do
139
+ config.hostname = nil
140
+ config.finalize!
141
+ expect(config.validate(machine)["SoftLayer"]).to have(1).item
142
+ end
143
+
144
+ it "should validate if hostname is not given but config.vm.hostname is set" do
145
+ config.hostname = nil
146
+ machine.stub_chain(:config, :vm, :hostname).and_return("vagrant")
147
+ expect(config.validate(machine)["SoftLayer"]).to have(:no).item
148
+ end
149
+
150
+ it "should fail if ssh key is not given" do
151
+ config.ssh_key = nil
152
+ config.finalize!
153
+ expect(config.validate(machine)["SoftLayer"]).to have(1).item
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,53 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+ require "vagrant-softlayer/version"
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "vagrant-softlayer"
6
+ spec.version = VagrantPlugins::SoftLayer::VERSION
7
+ spec.authors = "Audiolize GmbH"
8
+ spec.email = ""
9
+ spec.description = "Enables Vagrant to manages SoftLayer CCI."
10
+ spec.summary = "Enables Vagrant to manages SoftLayer CCI."
11
+
12
+ # The following block of code determines the files that should be included
13
+ # in the gem. It does this by reading all the files in the directory where
14
+ # this gemspec is, and parsing out the ignored files from the gitignore.
15
+ # Note that the entire gitignore(5) syntax is not supported, specifically
16
+ # the "!" syntax, but it should mostly work correctly.
17
+ root_path = File.dirname(__FILE__)
18
+ all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
19
+ all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
20
+ gitignore_path = File.join(root_path, ".gitignore")
21
+ gitignore = File.readlines(gitignore_path)
22
+ gitignore.map! { |line| line.chomp.strip }
23
+ gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
24
+
25
+ unignored_files = all_files.reject do |file|
26
+ # Ignore any directories, the gemspec only cares about files
27
+ next true if File.directory?(file)
28
+
29
+ # Ignore any paths that match anything in the gitignore. We do
30
+ # two tests here:
31
+ #
32
+ # - First, test to see if the entire path matches the gitignore.
33
+ # - Second, match if the basename does, this makes it so that things
34
+ # like '.DS_Store' will match sub-directories too (same behavior
35
+ # as git).
36
+ #
37
+ gitignore.any? do |ignore|
38
+ File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
39
+ File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
40
+ end
41
+ end
42
+
43
+ spec.files = unignored_files
44
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
45
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
46
+ spec.require_path = "lib"
47
+
48
+ spec.add_dependency "softlayer_api"
49
+
50
+ spec.add_development_dependency "bundler", "~> 1.3"
51
+ spec.add_development_dependency "rake"
52
+ spec.add_development_dependency "rspec"
53
+ end