vagrant-command-dns 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/CODE_OF_CONDUCT.md +13 -0
  4. data/Gemfile +9 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +25 -0
  7. data/Rakefile +14 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +7 -0
  10. data/lib/vagrant-command-dns/action/get_ip.rb +78 -0
  11. data/lib/vagrant-command-dns/action/host/create.rb +49 -0
  12. data/lib/vagrant-command-dns/action/host/destroy.rb +49 -0
  13. data/lib/vagrant-command-dns/action/host.rb +31 -0
  14. data/lib/vagrant-command-dns/action/route53/connect.rb +42 -0
  15. data/lib/vagrant-command-dns/action/route53/create.rb +71 -0
  16. data/lib/vagrant-command-dns/action/route53/destroy.rb +69 -0
  17. data/lib/vagrant-command-dns/action/route53.rb +34 -0
  18. data/lib/vagrant-command-dns/action/show_ip.rb +23 -0
  19. data/lib/vagrant-command-dns/action.rb +26 -0
  20. data/lib/vagrant-command-dns/command/host/create.rb +34 -0
  21. data/lib/vagrant-command-dns/command/host/destroy.rb +46 -0
  22. data/lib/vagrant-command-dns/command/host/root.rb +74 -0
  23. data/lib/vagrant-command-dns/command/ip.rb +34 -0
  24. data/lib/vagrant-command-dns/command/root.rb +77 -0
  25. data/lib/vagrant-command-dns/command/route53/create.rb +34 -0
  26. data/lib/vagrant-command-dns/command/route53/destroy.rb +46 -0
  27. data/lib/vagrant-command-dns/command/route53/root.rb +74 -0
  28. data/lib/vagrant-command-dns/config.rb +90 -0
  29. data/lib/vagrant-command-dns/errors.rb +31 -0
  30. data/lib/vagrant-command-dns/plugin.rb +69 -0
  31. data/lib/vagrant-command-dns/version.rb +5 -0
  32. data/lib/vagrant-command-dns.rb +20 -0
  33. data/locales/en.yml +43 -0
  34. data/vagrant-command-dns.gemspec +25 -0
  35. metadata +119 -0
@@ -0,0 +1,46 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ module Host
7
+ class Destroy < Vagrant.plugin('2', :command)
8
+
9
+ def execute
10
+ options = {}
11
+ options[:skip] = false
12
+
13
+ opts = OptionParser.new do |o|
14
+ o.banner = 'Usage: vagrant dns host destroy'
15
+ o.separator ''
16
+ o.separator 'Options:'
17
+ o.separator ''
18
+
19
+ o.on('-s', '--skip', 'Skip ip check before record destruction. Use with extreme caution.') do |skip|
20
+ options[:skip] = skip
21
+ end
22
+
23
+ o.separator ''
24
+ o.separator 'Additional documentation can be found on the plugin homepage'
25
+ o.separator ''
26
+ end
27
+
28
+ argv = parse_options(opts)
29
+ return if !argv
30
+
31
+ with_target_vms(argv) do |machine|
32
+ machine.config.dns.__skip = options[:skip] if options[:skip]
33
+ @env.action_runner.run(Action::Host.host_destroy, {
34
+ machine: machine,
35
+ ui: Vagrant::UI::Prefixed.new(@env.ui, 'dns host'),
36
+ })
37
+ end
38
+
39
+ 0
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,74 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ module Host
7
+ class Root < Vagrant.plugin('2', :command)
8
+
9
+ def self.synopsis
10
+ 'manage host /etc/hosts dns records'
11
+ end
12
+
13
+ def initialize(argv, env)
14
+ super
15
+
16
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
17
+
18
+ @subcommands = Vagrant::Registry.new
19
+
20
+ @subcommands.register(:create) do
21
+ require_relative 'create'
22
+ Command::Host::Create
23
+ end
24
+
25
+ @subcommands.register(:destroy) do
26
+ require_relative 'destroy'
27
+ Command::Host::Destroy
28
+ end
29
+ end
30
+
31
+ def execute
32
+ if @main_args.include?('-h') || @main_args.include?('--help')
33
+ return help
34
+ end
35
+
36
+ # If we reached this far then we must have a subcommand. If not,
37
+ # then we also just print the help and exit.
38
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
39
+ return help if !command_class || !@sub_command
40
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
41
+
42
+ # Initialize and execute the command class
43
+ command_class.new(@sub_args, @env).execute
44
+ end
45
+
46
+ def help
47
+ opts = OptionParser.new do |opts|
48
+ opts.version = VagrantPlugins::CommandDns::VERSION
49
+ opts.banner = 'Usage: vagrant dns host <subcommand>'
50
+ opts.separator ''
51
+ opts.separator 'Available subcommands:'
52
+
53
+ # Add the available subcommands as separators in order to print them
54
+ # out as well.
55
+ keys = []
56
+ @subcommands.each { |key, value| keys << key.to_s }
57
+
58
+ keys.sort.each do |key|
59
+ opts.separator " #{key}"
60
+ end
61
+
62
+ opts.separator ''
63
+ opts.separator 'For help on any individual subcommand run `vagrant dns host <subcommand> -h`'
64
+ opts.separator ''
65
+ end
66
+
67
+ @env.ui.info(opts.help, prefix: false)
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,34 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ class IP < Vagrant.plugin('2', :command)
7
+
8
+ def execute
9
+ options = {}
10
+
11
+ opts = OptionParser.new do |o|
12
+ o.banner = 'Usage: vagrant dns ip'
13
+ o.separator ''
14
+ o.separator 'Additional documentation can be found on the plugin homepage'
15
+ o.separator ''
16
+ end
17
+
18
+ argv = parse_options(opts)
19
+ return if !argv
20
+
21
+ with_target_vms(argv) do |machine|
22
+ @env.action_runner.run(Action.show_ip, {
23
+ machine: machine,
24
+ ui: Vagrant::UI::Prefixed.new(@env.ui, 'dns'),
25
+ })
26
+ end
27
+
28
+ 0
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,77 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ class Root < Vagrant.plugin('2', :command)
7
+
8
+ def self.synopsis
9
+ 'manage dns records'
10
+ end
11
+
12
+ def initialize(argv, env)
13
+ super
14
+
15
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
16
+
17
+ @subcommands = Vagrant::Registry.new
18
+
19
+ @subcommands.register(:ip) do
20
+ require_relative 'ip'
21
+ IP
22
+ end
23
+
24
+ @subcommands.register(:host) do
25
+ require_relative 'host/root'
26
+ Host::Root
27
+ end
28
+
29
+ @subcommands.register(:route53) do
30
+ require_relative 'route53/root'
31
+ Route53::Root
32
+ end
33
+ end
34
+
35
+ def execute
36
+ if @main_args.include?('-h') || @main_args.include?('--help')
37
+ return help
38
+ end
39
+
40
+ # If we reached this far then we must have a subcommand. If not,
41
+ # then we also just print the help and exit.
42
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
43
+ return help if !command_class || !@sub_command
44
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
45
+
46
+ # Initialize and execute the command class
47
+ command_class.new(@sub_args, @env).execute
48
+ end
49
+
50
+ def help
51
+ opts = OptionParser.new do |opts|
52
+ opts.version = VagrantPlugins::CommandDns::VERSION
53
+ opts.banner = 'Usage: vagrant dns <subcommand>'
54
+ opts.separator ''
55
+ opts.separator 'Available subcommands:'
56
+
57
+ # Add the available subcommands as separators in order to print them
58
+ # out as well.
59
+ keys = []
60
+ @subcommands.each { |key, value| keys << key.to_s }
61
+
62
+ keys.sort.each do |key|
63
+ opts.separator " #{key}"
64
+ end
65
+
66
+ opts.separator ''
67
+ opts.separator 'For help on any individual subcommand run `vagrant dns <subcommand> -h`'
68
+ opts.separator ''
69
+ end
70
+
71
+ @env.ui.info(opts.help, prefix: false)
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,34 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ module Route53
7
+ class Create < Vagrant.plugin('2', :command)
8
+
9
+ def execute
10
+ opts = OptionParser.new do |o|
11
+ o.banner = 'Usage: vagrant dns route53 create'
12
+ o.separator ''
13
+ o.separator 'Additional documentation can be found on the plugin homepage'
14
+ o.separator ''
15
+ end
16
+
17
+ argv = parse_options(opts)
18
+ return if !argv
19
+
20
+ with_target_vms(argv) do |machine|
21
+ @env.action_runner.run(Action::Route53.route53_create, {
22
+ machine: machine,
23
+ ui: Vagrant::UI::Prefixed.new(@env.ui, 'dns route53'),
24
+ })
25
+ end
26
+
27
+ 0
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,46 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ module Route53
7
+ class Destroy < Vagrant.plugin('2', :command)
8
+
9
+ def execute
10
+ options = {}
11
+ options[:skip] = false
12
+
13
+ opts = OptionParser.new do |o|
14
+ o.banner = 'Usage: vagrant dns route53 destroy [options]'
15
+ o.separator ''
16
+ o.separator 'Options:'
17
+ o.separator ''
18
+
19
+ o.on('-s', '--skip', 'Skip ip check before record destruction. Use with extreme caution.') do |skip|
20
+ options[:skip] = skip
21
+ end
22
+
23
+ o.separator ''
24
+ o.separator 'Additional documentation can be found on the plugin homepage'
25
+ o.separator ''
26
+ end
27
+
28
+ argv = parse_options(opts)
29
+ return if !argv
30
+
31
+ with_target_vms(argv) do |machine|
32
+ machine.config.dns.__skip = options[:skip] if options[:skip]
33
+ @env.action_runner.run(Action::Route53.route53_destroy, {
34
+ machine: machine,
35
+ ui: Vagrant::UI::Prefixed.new(@env.ui, 'dns route53'),
36
+ })
37
+ end
38
+
39
+ 0
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,74 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module CommandDns
5
+ module Command
6
+ module Route53
7
+ class Root < Vagrant.plugin('2', :command)
8
+
9
+ def self.synopsis
10
+ 'manage route53 dns records'
11
+ end
12
+
13
+ def initialize(argv, env)
14
+ super
15
+
16
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
17
+
18
+ @subcommands = Vagrant::Registry.new
19
+
20
+ @subcommands.register(:create) do
21
+ require_relative 'create'
22
+ Command::Route53::Create
23
+ end
24
+
25
+ @subcommands.register(:destroy) do
26
+ require_relative 'destroy'
27
+ Command::Route53::Destroy
28
+ end
29
+ end
30
+
31
+ def execute
32
+ if @main_args.include?('-h') || @main_args.include?('--help')
33
+ return help
34
+ end
35
+
36
+ # If we reached this far then we must have a subcommand. If not,
37
+ # then we also just print the help and exit.
38
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
39
+ return help if !command_class || !@sub_command
40
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
41
+
42
+ # Initialize and execute the command class
43
+ command_class.new(@sub_args, @env).execute
44
+ end
45
+
46
+ def help
47
+ opts = OptionParser.new do |opts|
48
+ opts.version = VagrantPlugins::CommandDns::VERSION
49
+ opts.banner = 'Usage: vagrant dns route53 <subcommand>'
50
+ opts.separator ''
51
+ opts.separator 'Available subcommands:'
52
+
53
+ # Add the available subcommands as separators in order to print them
54
+ # out as well.
55
+ keys = []
56
+ @subcommands.each { |key, value| keys << key.to_s }
57
+
58
+ keys.sort.each do |key|
59
+ opts.separator " #{key}"
60
+ end
61
+
62
+ opts.separator ''
63
+ opts.separator 'For help on any individual subcommand run `vagrant dns route53 <subcommand> -h`'
64
+ opts.separator ''
65
+ end
66
+
67
+ @env.ui.info(opts.help, prefix: false)
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,90 @@
1
+ module VagrantPlugins
2
+ module CommandDns
3
+ class Config < Vagrant.plugin('2', :config)
4
+
5
+ # List of VM aliases in FQDN format
6
+ #
7
+ # @return [Array<String>]
8
+ attr_accessor :aliases
9
+
10
+ # AWS Route53 Settings
11
+
12
+ # The version of the AWS api to use
13
+ #
14
+ # @return [String]
15
+ attr_accessor :route53_version
16
+
17
+ # The access key ID for accessing AWS
18
+ #
19
+ # @return [String]
20
+ attr_accessor :route53_access_key_id
21
+
22
+ # The secret access key for accessing AWS
23
+ #
24
+ # @return [String]
25
+ attr_accessor :route53_secret_access_key
26
+
27
+ # The token associated with the key for accessing AWS
28
+ #
29
+ # @return [String]
30
+ attr_accessor :route53_session_token
31
+
32
+ # The Route53 Zone ID
33
+ #
34
+ # @return [String]
35
+ attr_accessor :route53_zone_id
36
+
37
+ attr_accessor :__skip
38
+ attr_reader :__available_providers
39
+
40
+ def initialize
41
+ @aliases = UNSET_VALUE
42
+
43
+ @route53_version = UNSET_VALUE
44
+ @route53_access_key_id = UNSET_VALUE
45
+ @route53_secret_access_key = UNSET_VALUE
46
+ @route53_session_token = UNSET_VALUE
47
+ @route53_zone_id = UNSET_VALUE
48
+
49
+ # Internal
50
+ @__skip = false
51
+ @__available_providers = %w(local route53)
52
+ end
53
+
54
+ def finalize!
55
+ @aliases = [] if @aliases == UNSET_VALUE
56
+
57
+ @route53_version = nil if @route53_version == UNSET_VALUE
58
+ @route53_zone_id = nil if @route53_zone_id == UNSET_VALUE
59
+
60
+ # Try to get access keys from standard AWS environment variables; they
61
+ # will default to nil if the environment variables are not present.
62
+ @route53_access_key_id = ENV['AWS_ACCESS_KEY'] if @route53_access_key_id == UNSET_VALUE
63
+ @route53_secret_access_key = ENV['AWS_SECRET_KEY'] if @route53_secret_access_key == UNSET_VALUE
64
+ @route53_session_token = ENV['AWS_SESSION_TOKEN'] if @route53_session_token == UNSET_VALUE
65
+ end
66
+
67
+ def validate(machine)
68
+ errors = _detected_errors
69
+
70
+ if @route53
71
+ if machine.provider_name == :aws
72
+ aws_config = machine.provider_config
73
+ # If these values are still not set and the AWS provider is being used, borrow it's config values
74
+ @route53_version = aws_config.version if @route53_version == nil
75
+ @route53_access_key_id = aws_config.access_key_id if @route53_access_key_id == nil
76
+ @route53_secret_access_key = aws_config.secret_access_key if @route53_secret_access_key == nil
77
+ @route53_session_token = aws_config.session_token if @route53_session_token == nil
78
+ end
79
+
80
+ errors << I18n.t('vagrant_command_dns.config.route53_zone_id_required') if @route53_zone_id.nil?
81
+ errors << I18n.t('vagrant_command_dns.config.route53_access_key_id_required') if @route53_access_key_id.nil?
82
+ errors << I18n.t('vagrant_command_dns.config.route53_secret_access_key_required') if @route53_secret_access_key.nil?
83
+ end
84
+
85
+ { 'DNS' => errors }
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,31 @@
1
+ module VagrantPlugins
2
+ module CommandDns
3
+ module Errors
4
+
5
+ class VagrantCommandDnsError < Vagrant::Errors::VagrantError
6
+ error_namespace('vagrant_command_dns.errors')
7
+ end
8
+
9
+ class MachineStateError < VagrantCommandDnsError
10
+ error_key(:machine_state_error)
11
+ end
12
+
13
+ class UnsupportedProviderError < VagrantCommandDnsError
14
+ error_key(:unsupported_provider_error)
15
+ end
16
+
17
+ class InvalidAddressError < VagrantCommandDnsError
18
+ error_key(:invalid_address_error)
19
+ end
20
+
21
+ class FogError < VagrantCommandDnsError
22
+ error_key(:fog_error)
23
+ end
24
+
25
+ class EditLocalHostsError < VagrantCommandDnsError
26
+ error_key(:edit_local_hosts_error)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,69 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant DNS Plugin must be run within Vagrant'
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install this
8
+ # into a Vagrant version earlier than it was developed on.
9
+ if Vagrant::VERSION < '1.7.4'
10
+ raise 'The Vagrant DNS Plugin is only compatible with Vagrant 1.7.4+'
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module CommandDns
15
+ class Plugin < Vagrant.plugin('2')
16
+
17
+ name 'dns command'
18
+ description 'The `dns` command gives you a way to manage DNS records.'
19
+
20
+ # This initializes the internationalization strings.
21
+ def self.setup_i18n
22
+ I18n.load_path << File.expand_path('locales/en.yml', CommandDns.source_root)
23
+ I18n.reload!
24
+ end
25
+
26
+ # This sets up our log level to be whatever VAGRANT_LOG is.
27
+ def self.setup_logging
28
+ require 'log4r'
29
+
30
+ level = nil
31
+ begin
32
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
33
+ rescue NameError
34
+ # This means that the logging constant wasn't found,
35
+ # which is fine. We just keep `level` as `nil`. But
36
+ # we tell the user.
37
+ level = nil
38
+ end
39
+
40
+ # Some constants, such as "true" resolve to booleans, so the
41
+ # above error checking doesn't catch it. This will check to make
42
+ # sure that the log level is an integer, as Log4r requires.
43
+ level = nil if !level.is_a?(Integer)
44
+
45
+ # Set the logging level on all "vagrant" namespaced
46
+ # logs as long as we have a valid level.
47
+ if level
48
+ logger = Log4r::Logger.new('vagrant_command_dns')
49
+ logger.outputters = Log4r::Outputter.stderr
50
+ logger.level = level
51
+ logger = nil
52
+ end
53
+ end
54
+
55
+ config 'dns' do
56
+ setup_i18n
57
+ require_relative 'config'
58
+ Config
59
+ end
60
+
61
+ command 'dns' do
62
+ setup_logging
63
+ require_relative 'command/root'
64
+ Command::Root
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module CommandDns
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ require 'pathname'
2
+ require 'vagrant-command-dns/version'
3
+ require 'vagrant-command-dns/plugin'
4
+
5
+ module VagrantPlugins
6
+ module CommandDns
7
+
8
+ lib_path = Pathname.new(File.expand_path('../vagrant-command-dns', __FILE__))
9
+ autoload :Action, lib_path.join('action')
10
+ autoload :Errors, lib_path.join('errors')
11
+
12
+ # This returns the path to the source of this plugin.
13
+ #
14
+ # @return [Pathname]
15
+ def self.source_root
16
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
17
+ end
18
+
19
+ end
20
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,43 @@
1
+ en:
2
+ vagrant_command_dns:
3
+
4
+ config:
5
+ route53_zone_id_required: |-
6
+ A zone ID must be specified via "route53_zone_id"
7
+ route53_access_key_id_required: |-
8
+ An access key ID must be specified via "route53_access_key_id"
9
+ route53_secret_access_key_required: |-
10
+ A secret access key is required via "route53_secret_access_key"
11
+
12
+ errors:
13
+ machine_state_error: |-
14
+ Machine must be %{state} to preform this action.
15
+ unsupported_provider_error: |-
16
+ Machine provider not supported. Pull requests and testers are welcome.
17
+ invalid_address_error: |-
18
+ invalid_address_error
19
+
20
+ command:
21
+ host:
22
+ edit_error: |-
23
+ Unable to edit /etc/hosts. Consult documentation or submit a pull request.
24
+ create_exists_match: |-
25
+ /etc/hosts record exists for %{ip} %{hostname}
26
+ create_exists_conflict: |-
27
+ this should be a friendly message telling them they have other conflicting entries to remove
28
+
29
+ route53:
30
+ fog_error: |-
31
+ AWS error: %{message}
32
+ create_success: |-
33
+ Route53 record created for %{ip} %{hostname}.
34
+ create_exists_match: |-
35
+ Route53 record exists for %{ip} %{hostname}.
36
+ create_exists_conflict: |-
37
+ Route53 record exists for %{ip} %{hostname}. Please update manually.
38
+ destroy_success: |-
39
+ Route53 record destroyed for %{hostname}
40
+ destroy_conflict: |-
41
+ Route53 record for %{hostname} does not match. Expected %{expected} got %{got}. Please update manually...
42
+ destroy_not_found: |-
43
+ Route53 record for %{hostname} not found. Skipping...
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-command-dns/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'vagrant-command-dns'
8
+ spec.version = VagrantPlugins::CommandDns::VERSION
9
+ spec.authors = ['cornfeedhobo']
10
+ spec.email = ['cornfeedhobo@fuzzlabs.org']
11
+
12
+ spec.summary = %q{Vagrant Plugin to manage DNS records}
13
+ spec.homepage = 'https://github.com/cornfeedhobo/vagrant-command-dns'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.required_ruby_version = '>= 2.0'
20
+
21
+ spec.add_runtime_dependency 'fog', '~> 1.22'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.10'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ end