fog-core 1.21.0

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 +15 -0
  2. data/lib/fog/account.rb +25 -0
  3. data/lib/fog/billing.rb +23 -0
  4. data/lib/fog/cdn.rb +23 -0
  5. data/lib/fog/compute.rb +80 -0
  6. data/lib/fog/compute/models/server.rb +104 -0
  7. data/lib/fog/core.rb +51 -0
  8. data/lib/fog/core/attributes.rb +227 -0
  9. data/lib/fog/core/class_from_string.rb +26 -0
  10. data/lib/fog/core/collection.rb +161 -0
  11. data/lib/fog/core/connection.rb +72 -0
  12. data/lib/fog/core/credentials.rb +70 -0
  13. data/lib/fog/core/current_machine.rb +34 -0
  14. data/lib/fog/core/deprecated_connection_accessors.rb +41 -0
  15. data/lib/fog/core/deprecation.rb +23 -0
  16. data/lib/fog/core/errors.rb +118 -0
  17. data/lib/fog/core/hmac.rb +35 -0
  18. data/lib/fog/core/logger.rb +44 -0
  19. data/lib/fog/core/mock.rb +115 -0
  20. data/lib/fog/core/model.rb +80 -0
  21. data/lib/fog/core/provider.rb +34 -0
  22. data/lib/fog/core/scp.rb +96 -0
  23. data/lib/fog/core/service.rb +223 -0
  24. data/lib/fog/core/ssh.rb +137 -0
  25. data/lib/fog/core/time.rb +32 -0
  26. data/lib/fog/core/uuid.rb +23 -0
  27. data/lib/fog/core/wait_for.rb +15 -0
  28. data/lib/fog/core/wait_for_defaults.rb +21 -0
  29. data/lib/fog/dns.rb +40 -0
  30. data/lib/fog/identity.rb +28 -0
  31. data/lib/fog/image.rb +23 -0
  32. data/lib/fog/metering.rb +25 -0
  33. data/lib/fog/monitoring.rb +24 -0
  34. data/lib/fog/network.rb +28 -0
  35. data/lib/fog/orchestration.rb +25 -0
  36. data/lib/fog/schema/data_validator.rb +154 -0
  37. data/lib/fog/storage.rb +80 -0
  38. data/lib/fog/support.rb +26 -0
  39. data/lib/fog/test_helpers.rb +12 -0
  40. data/lib/fog/test_helpers/collection_helper.rb +102 -0
  41. data/lib/fog/test_helpers/compute/flavors_helper.rb +34 -0
  42. data/lib/fog/test_helpers/compute/server_helper.rb +27 -0
  43. data/lib/fog/test_helpers/compute/servers_helper.rb +12 -0
  44. data/lib/fog/test_helpers/formats_helper.rb +99 -0
  45. data/lib/fog/test_helpers/helper.rb +25 -0
  46. data/lib/fog/test_helpers/mock_helper.rb +107 -0
  47. data/lib/fog/test_helpers/model_helper.rb +35 -0
  48. data/lib/fog/test_helpers/responds_to_helper.rb +13 -0
  49. data/lib/fog/test_helpers/succeeds_helper.rb +11 -0
  50. data/lib/fog/version.rb +3 -0
  51. data/lib/fog/volume.rb +25 -0
  52. data/lib/fog/vpn.rb +25 -0
  53. data/lib/tasks/test_task.rb +46 -0
  54. metadata +267 -0
@@ -0,0 +1,80 @@
1
+ require 'mime/types'
2
+
3
+ module Fog
4
+ module Storage
5
+
6
+ def self.[](provider)
7
+ self.new(:provider => provider)
8
+ end
9
+
10
+ def self.new(attributes)
11
+ attributes = attributes.dup # prevent delete from having side effects
12
+ case provider = attributes.delete(:provider).to_s.downcase.to_sym
13
+ when :internetarchive
14
+ require 'fog/internet_archive/storage'
15
+ Fog::Storage::InternetArchive.new(attributes)
16
+ when :stormondemand
17
+ require 'fog/storm_on_demand/storage'
18
+ Fog::Storage::StormOnDemand.new(attributes)
19
+ else
20
+ if self.providers.include?(provider)
21
+ require "fog/#{provider}/storage"
22
+ return Fog::Storage.const_get(Fog.providers[provider]).new(attributes)
23
+ end
24
+
25
+ raise ArgumentError.new("#{provider} is not a recognized storage provider")
26
+ end
27
+ end
28
+
29
+ def self.directories
30
+ directories = []
31
+ for provider in self.providers
32
+ begin
33
+ directories.concat(self[provider].directories)
34
+ rescue # ignore any missing credentials/etc
35
+ end
36
+ end
37
+ directories
38
+ end
39
+
40
+ def self.get_body_size(body)
41
+ if body.respond_to?(:force_encoding)
42
+ body.force_encoding('BINARY')
43
+ end
44
+ if body.respond_to?(:bytesize)
45
+ body.bytesize
46
+ elsif body.respond_to?(:size)
47
+ body.size
48
+ elsif body.respond_to?(:stat)
49
+ body.stat.size
50
+ else
51
+ 0
52
+ end
53
+ end
54
+
55
+ def self.get_content_type(data)
56
+ if data.respond_to?(:path) and !data.path.nil?
57
+ filename = ::File.basename(data.path)
58
+ unless (mime_types = MIME::Types.of(filename)).empty?
59
+ mime_types.first.content_type
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.parse_data(data)
65
+ {
66
+ :body => data,
67
+ :headers => {
68
+ 'Content-Length' => get_body_size(data),
69
+ 'Content-Type' => get_content_type(data)
70
+ #'Content-MD5' => Base64.encode64(Digest::MD5.digest(metadata[:body])).strip
71
+ }
72
+ }
73
+ end
74
+
75
+ def self.providers
76
+ Fog.services[:storage]
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,26 @@
1
+ module Fog
2
+ module Support
3
+
4
+ def self.[](provider)
5
+ self.new(:provider => provider)
6
+ end
7
+
8
+ def self.new(attributes)
9
+ attributes = attributes.dup
10
+ provider = attributes.delete(:provider).to_s.downcase.to_sym
11
+
12
+ if provider == :stormondemand
13
+ require 'fog/storm_on_demand/support'
14
+ Fog::Support::StormOnDemand.new(attributes)
15
+ else
16
+ raise ArgumentError.new("#{provider} has no support service")
17
+ end
18
+
19
+ end
20
+
21
+ def self.providers
22
+ Fog.services[:support]
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ # So downstream users can use the test_helpers
2
+
3
+ require 'fog/test_helpers/helper'
4
+ require 'fog/test_helpers/collection_helper'
5
+ require 'fog/test_helpers/formats_helper'
6
+ require 'fog/test_helpers/mock_helper'
7
+ require 'fog/test_helpers/model_helper'
8
+ require 'fog/test_helpers/responds_to_helper'
9
+ require 'fog/test_helpers/succeeds_helper'
10
+ require 'fog/test_helpers/compute/flavors_helper'
11
+ require 'fog/test_helpers/compute/server_helper'
12
+ require 'fog/test_helpers/compute/servers_helper'
@@ -0,0 +1,102 @@
1
+ def collection_tests(collection, params = {}, mocks_implemented = true)
2
+
3
+ tests('success') do
4
+
5
+ tests("#new(#{params.inspect})").succeeds do
6
+ pending if Fog.mocking? && !mocks_implemented
7
+ collection.new(params)
8
+ end
9
+
10
+ tests("#create(#{params.inspect})").succeeds do
11
+ pending if Fog.mocking? && !mocks_implemented
12
+ @instance = collection.create(params)
13
+ end
14
+
15
+ # FIXME: work around for timing issue on AWS describe_instances mocks
16
+ if Fog.mocking? && @instance.respond_to?(:ready?)
17
+ @instance.wait_for { ready? }
18
+ end
19
+
20
+ tests("#all").succeeds do
21
+ pending if Fog.mocking? && !mocks_implemented
22
+ collection.all
23
+ end
24
+
25
+
26
+
27
+ if !Fog.mocking? || mocks_implemented
28
+ @identity = @instance.identity
29
+ end
30
+
31
+ tests("#get(#{@identity})").succeeds do
32
+ pending if Fog.mocking? && !mocks_implemented
33
+ collection.get(@identity)
34
+ end
35
+
36
+ tests('Enumerable') do
37
+ pending if Fog.mocking? && !mocks_implemented
38
+
39
+ methods = [
40
+ 'all?', 'any?', 'find', 'detect', 'collect', 'map',
41
+ 'find_index', 'flat_map', 'collect_concat', 'group_by',
42
+ 'none?', 'one?'
43
+ ]
44
+
45
+ # JRuby 1.7.5+ issue causes a SystemStackError: stack level too deep
46
+ # https://github.com/jruby/jruby/issues/1265
47
+ if RUBY_PLATFORM == "java" and JRUBY_VERSION =~ /1\.7\.[5-8]/
48
+ methods.delete('all?')
49
+ end
50
+
51
+ methods.each do |enum_method|
52
+ if collection.respond_to?(enum_method)
53
+ tests("##{enum_method}").succeeds do
54
+ block_called = false
55
+ collection.send(enum_method) {|x| block_called = true }
56
+ block_called
57
+ end
58
+ end
59
+ end
60
+
61
+ [
62
+ 'max_by','min_by'
63
+ ].each do |enum_method|
64
+ if collection.respond_to?(enum_method)
65
+ tests("##{enum_method}").succeeds do
66
+ block_called = false
67
+ collection.send(enum_method) {|x| block_called = true; 0 }
68
+ block_called
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+
77
+ if block_given?
78
+ yield
79
+ end
80
+
81
+ if !Fog.mocking? || mocks_implemented
82
+ @instance.destroy
83
+ end
84
+ end
85
+
86
+ tests('failure') do
87
+
88
+ if !Fog.mocking? || mocks_implemented
89
+ @identity = @identity.to_s
90
+ @identity = @identity.gsub(/[a-zA-Z]/) { Fog::Mock.random_letters(1) }
91
+ @identity = @identity.gsub(/\d/) { Fog::Mock.random_numbers(1) }
92
+ @identity
93
+ end
94
+
95
+ tests("#get('#{@identity}')").returns(nil) do
96
+ pending if Fog.mocking? && !mocks_implemented
97
+ collection.get(@identity)
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,34 @@
1
+ def flavors_tests(connection, params = {}, mocks_implemented = true)
2
+
3
+ tests('success') do
4
+
5
+ tests("#all").succeeds do
6
+ pending if Fog.mocking? && !mocks_implemented
7
+ connection.flavors.all
8
+ end
9
+
10
+ if !Fog.mocking? || mocks_implemented
11
+ @identity = connection.flavors.first.identity
12
+ end
13
+
14
+ tests("#get('#{@identity}')").succeeds do
15
+ pending if Fog.mocking? && !mocks_implemented
16
+ connection.flavors.get(@identity)
17
+ end
18
+
19
+ end
20
+
21
+ tests('failure') do
22
+
23
+ if !Fog.mocking? || mocks_implemented
24
+ invalid_flavor_identity = connection.flavors.first.identity.to_s.gsub(/\w/, '0')
25
+ end
26
+
27
+ tests("#get('#{invalid_flavor_identity}')").returns(nil) do
28
+ pending if Fog.mocking? && !mocks_implemented
29
+ connection.flavors.get(invalid_flavor_identity)
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,27 @@
1
+ def server_tests(connection, params = {}, mocks_implemented = true)
2
+
3
+ model_tests(connection.servers, params, mocks_implemented) do
4
+
5
+ tests('#reload').returns(true) do
6
+ pending if Fog.mocking? && !mocks_implemented
7
+ @instance.wait_for { ready? }
8
+ identity = @instance.identity
9
+ !identity.nil? && identity == @instance.reload.identity
10
+ end
11
+
12
+ responds_to([:ready?, :state])
13
+ yield if block_given?
14
+
15
+ tests('#reboot').succeeds do
16
+ pending if Fog.mocking? && !mocks_implemented
17
+ @instance.wait_for { ready? }
18
+ @instance.reboot
19
+ end
20
+
21
+ if !Fog.mocking? || mocks_implemented
22
+ @instance.wait_for { ready? }
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,12 @@
1
+ def servers_tests(connection, params = {}, mocks_implemented = true)
2
+
3
+ collection_tests(connection.servers, params, mocks_implemented) do
4
+
5
+ if !Fog.mocking? || mocks_implemented
6
+ @instance.wait_for { ready? }
7
+ yield if block_given?
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,99 @@
1
+ require "fog/schema/data_validator"
2
+
3
+ # format related hackery
4
+ # allows both true.is_a?(Fog::Boolean) and false.is_a?(Fog::Boolean)
5
+ # allows both nil.is_a?(Fog::Nullable::String) and ''.is_a?(Fog::Nullable::String)
6
+ module Fog
7
+ module Boolean; end
8
+ module Nullable
9
+ module Boolean; end
10
+ module Integer; end
11
+ module String; end
12
+ module Time; end
13
+ module Float; end
14
+ module Hash; end
15
+ module Array; end
16
+ end
17
+ end
18
+ [FalseClass, TrueClass].each {|klass| klass.send(:include, Fog::Boolean)}
19
+ [FalseClass, TrueClass, NilClass, Fog::Boolean].each {|klass| klass.send(:include, Fog::Nullable::Boolean)}
20
+ [NilClass, String].each {|klass| klass.send(:include, Fog::Nullable::String)}
21
+ [NilClass, Time].each {|klass| klass.send(:include, Fog::Nullable::Time)}
22
+ [Integer, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Integer)}
23
+ [Float, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Float)}
24
+ [Hash, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Hash)}
25
+ [Array, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Array)}
26
+
27
+ module Shindo
28
+ class Tests
29
+
30
+ # Generates a Shindo test that compares a hash schema to the result
31
+ # of the passed in block returning true if they match.
32
+ #
33
+ # The schema that is passed in is a Hash or Array of hashes that
34
+ # have Classes in place of values. When checking the schema the
35
+ # value should match the Class.
36
+ #
37
+ # Strict mode will fail if the data has additional keys. Setting
38
+ # +strict+ to +false+ will allow additional keys to appear.
39
+ #
40
+ # @param [Hash] schema A Hash schema
41
+ # @param [Hash] options Options to change validation rules
42
+ # @option options [Boolean] :allow_extra_keys
43
+ # If +true+ does not fail when keys are in the data that are
44
+ # not specified in the schema. This allows new values to
45
+ # appear in API output without breaking the check.
46
+ # @option options [Boolean] :allow_optional_rules
47
+ # If +true+ does not fail if extra keys are in the schema
48
+ # that do not match the data. Not recommended!
49
+ # @yield Data to check with schema
50
+ #
51
+ # @example Using in a test
52
+ # Shindo.tests("comparing welcome data against schema") do
53
+ # data = {:welcome => "Hello" }
54
+ # data_matches_schema(:welcome => String) { data }
55
+ # end
56
+ #
57
+ # comparing welcome data against schema
58
+ # + data matches schema
59
+ #
60
+ # @example Example schema
61
+ # {
62
+ # "id" => String,
63
+ # "ram" => Integer,
64
+ # "disks" => [
65
+ # {
66
+ # "size" => Float
67
+ # }
68
+ # ],
69
+ # "dns_name" => Fog::Nullable::String,
70
+ # "active" => Fog::Boolean,
71
+ # "created" => DateTime
72
+ # }
73
+ #
74
+ # @return [Boolean]
75
+ def data_matches_schema(schema, options = {})
76
+ test('data matches schema') do
77
+ validator = Fog::Schema::DataValidator.new
78
+ valid = validator.validate(yield, schema, options)
79
+ @message = validator.message unless valid
80
+ valid
81
+ end
82
+ end
83
+
84
+ # @deprecated #formats is deprecated. Use #data_matches_schema instead
85
+ def formats(format, strict = true)
86
+ test('has proper format') do
87
+ if strict
88
+ options = {:allow_extra_keys => false, :allow_optional_rules => true}
89
+ else
90
+ options = {:allow_extra_keys => true, :allow_optional_rules => true}
91
+ end
92
+ validator = Fog::Schema::DataValidator.new
93
+ valid = validator.validate(yield, format, options)
94
+ @message = validator.message unless valid
95
+ valid
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,25 @@
1
+ require 'excon'
2
+
3
+ ENV['FOG_RC'] = ENV['FOG_RC'] || File.expand_path('../.fog', __FILE__)
4
+ ENV['FOG_CREDENTIAL'] = ENV['FOG_CREDENTIAL'] || 'default'
5
+
6
+ Excon.defaults.merge!(:debug_request => true, :debug_response => true)
7
+
8
+ LOREM = <<HERE
9
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
10
+ HERE
11
+
12
+ require "tempfile"
13
+
14
+ def lorem_file
15
+ Tempfile.new("lorem").tap do |f|
16
+ f.write(LOREM)
17
+ f.rewind
18
+ end
19
+ end
20
+
21
+ def array_differences(array_a, array_b)
22
+ (array_a - array_b) | (array_b - array_a)
23
+ end
24
+
25
+ __END__
@@ -0,0 +1,107 @@
1
+ require 'fog/core'
2
+
3
+ # Use so you can run in mock mode from the command line
4
+ #
5
+ # FOG_MOCK=true fog
6
+
7
+ if ENV["FOG_MOCK"] == "true"
8
+ Fog.mock!
9
+ end
10
+
11
+ # if in mocked mode, fill in some fake credentials for us
12
+ if Fog.mock?
13
+ Fog.credentials = {
14
+ :aws_access_key_id => 'aws_access_key_id',
15
+ :aws_secret_access_key => 'aws_secret_access_key',
16
+ :ia_access_key_id => 'aws_access_key_id',
17
+ :ia_secret_access_key => 'aws_secret_access_key',
18
+ :atmos_storage_token => 'atmos_token',
19
+ :atmos_storage_secret => 'atmos_secret',
20
+ :atmos_storage_endpoint => 'http://atmos.is.cool:1000/test1.0',
21
+ :bluebox_api_key => 'bluebox_api_key',
22
+ :bluebox_customer_id => 'bluebox_customer_id',
23
+ :brightbox_client_id => 'brightbox_client_id',
24
+ :brightbox_secret => 'brightbox_secret',
25
+ :cloudstack_disk_offering_id => '',
26
+ :cloudstack_host => 'http://cloudstack.example.org',
27
+ :cloudstack_network_ids => '',
28
+ :cloudstack_service_offering_id => '4437ac6c-9fe3-477a-57ec-60a5a45896a4',
29
+ :cloudstack_template_id => '8a31cf9c-f248-0588-256e-9dbf58785216',
30
+ :cloudstack_zone_id => 'c554c592-e09c-9df5-7688-4a32754a4305',
31
+ :clodo_api_key => 'clodo_api_key',
32
+ :clodo_username => 'clodo_username',
33
+ :digitalocean_api_key => 'digitalocean_api_key',
34
+ :digitalocean_client_id => 'digitalocean_client_id',
35
+ :dnsimple_email => 'dnsimple_email',
36
+ :dnsimple_password => 'dnsimple_password',
37
+ :dnsmadeeasy_api_key => 'dnsmadeeasy_api_key',
38
+ :dnsmadeeasy_secret_key => 'dnsmadeeasy_secret_key',
39
+ :ecloud_username => 'ecloud_username',
40
+ :ecloud_password => 'ecloud_password',
41
+ :ecloud_versions_uri => 'http://ecloud.versions.uri',
42
+ :glesys_username => 'glesys_username',
43
+ :glesys_api_key => 'glesys_api_key',
44
+ :go_grid_api_key => 'go_grid_api_key',
45
+ :go_grid_shared_secret => 'go_grid_shared_secret',
46
+ :google_storage_access_key_id => 'google_storage_access_key_id',
47
+ :google_storage_secret_access_key => 'google_storage_secret_access_key',
48
+ :google_project => 'google_project_name',
49
+ :google_client_email => 'fake@developer.gserviceaccount.com',
50
+ :google_key_location => '~/fake.p12',
51
+ :hp_access_key => 'hp_access_key',
52
+ :hp_secret_key => 'hp_secret_key',
53
+ :hp_tenant_id => 'hp_tenant_id',
54
+ :hp_avl_zone => 'hp_avl_zone',
55
+ :os_account_meta_temp_url_key => 'os_account_meta_temp_url_key',
56
+ :ibm_username => 'ibm_username',
57
+ :ibm_password => 'ibm_password',
58
+ :joyent_username => "joyentuser",
59
+ :joyent_password => "joyentpass",
60
+ :linode_api_key => 'linode_api_key',
61
+ :local_root => '~/.fog',
62
+ :bare_metal_cloud_password => 'bare_metal_cloud_password',
63
+ :bare_metal_cloud_username => 'bare_metal_cloud_username',
64
+ :ninefold_compute_key => 'ninefold_compute_key',
65
+ :ninefold_compute_secret => 'ninefold_compute_secret',
66
+ :ninefold_storage_secret => 'ninefold_storage_secret',
67
+ :ninefold_storage_token => 'ninefold_storage_token',
68
+ # :public_key_path => '~/.ssh/id_rsa.pub',
69
+ # :private_key_path => '~/.ssh/id_rsa',
70
+ :openstack_api_key => 'openstack_api_key',
71
+ :openstack_username => 'openstack_username',
72
+ :openstack_tenant => 'openstack_tenant',
73
+ :openstack_auth_url => 'http://openstack:35357/v2.0/tokens',
74
+ :ovirt_url => 'http://ovirt:8080/api',
75
+ :ovirt_username => 'admin@internal',
76
+ :ovirt_password => '123123',
77
+ :libvirt_uri => 'qemu://libvirt/system',
78
+ :rackspace_api_key => 'rackspace_api_key',
79
+ :rackspace_username => 'rackspace_username',
80
+ :riakcs_access_key_id => 'riakcs_access_key_id',
81
+ :riakcs_secret_access_key => 'riakcs_secret_access_key',
82
+ :storm_on_demand_username => 'storm_on_demand_username',
83
+ :storm_on_demand_password => 'storm_on_demand_password',
84
+ :vcloud_host => 'vcloud_host',
85
+ :vcloud_password => 'vcloud_password',
86
+ :vcloud_username => 'vcloud_username',
87
+ :vcloud_director_host => 'vcloud-director-host',
88
+ :vcloud_director_password => 'vcloud_director_password',
89
+ :vcloud_director_username => 'vcd_user@vcd_org_name',
90
+ :voxel_api_key => 'voxel_api_key',
91
+ :voxel_api_secret => 'voxel_api_secret',
92
+ :zerigo_email => 'zerigo_email',
93
+ :zerigo_token => 'zerigo_token',
94
+ :dynect_customer => 'dynect_customer',
95
+ :dynect_username => 'dynect_username',
96
+ :dynect_password => 'dynect_password',
97
+ :vsphere_server => 'virtualcenter.lan',
98
+ :vsphere_username => 'apiuser',
99
+ :vsphere_password => 'apipassword',
100
+ :vsphere_expected_pubkey_hash => 'abcdef1234567890',
101
+ :libvirt_uri => 'qemu:///system',
102
+ :libvirt_username => 'root',
103
+ :libvirt_password => 'password',
104
+ :cloudsigma_username => 'csuname',
105
+ :cloudsigma_password => 'cspass'
106
+ }.merge(Fog.credentials)
107
+ end