fog-core 1.21.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 (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,26 @@
1
+ module Fog
2
+ # get class by string or nil
3
+ def self.class_from_string classname, defaultpath=""
4
+ if classname and classname.is_a? String then
5
+ chain = classname.split("::")
6
+ klass = Kernel
7
+ chain.each do |klass_string|
8
+ klass = klass.const_get klass_string
9
+ end
10
+ if klass.is_a? Class then
11
+ klass
12
+ elsif defaultpath != nil then
13
+ Fog.class_from_string((defaultpath.split("::")+chain).join("::"), nil)
14
+ else
15
+ nil
16
+ end
17
+ elsif classname and classname.is_a? Class then
18
+ classname
19
+ else
20
+ nil
21
+ end
22
+ rescue NameError
23
+ defaultpath != nil ? Fog.class_from_string((defaultpath.split("::")+chain).join("::"), nil) : nil
24
+ end
25
+ end
26
+
@@ -0,0 +1,161 @@
1
+ require "fog/core/deprecated_connection_accessors"
2
+
3
+ module Fog
4
+ class Collection < Array
5
+ extend Fog::Attributes::ClassMethods
6
+ include Fog::Attributes::InstanceMethods
7
+ include Fog::Core::DeprecatedConnectionAccessors
8
+
9
+ attr_reader :service
10
+
11
+ Array.public_instance_methods(false).each do |method|
12
+ unless [:reject, :select, :slice, :clear, :inspect].include?(method.to_sym)
13
+ class_eval <<-EOS, __FILE__, __LINE__
14
+ def #{method}(*args)
15
+ unless @loaded
16
+ lazy_load
17
+ end
18
+ super
19
+ end
20
+ EOS
21
+ end
22
+ end
23
+
24
+ %w[reject select slice].each do |method|
25
+ class_eval <<-EOS, __FILE__, __LINE__
26
+ def #{method}(*args)
27
+ unless @loaded
28
+ lazy_load
29
+ end
30
+ data = super
31
+ self.clone.clear.concat(data)
32
+ end
33
+ EOS
34
+ end
35
+
36
+ def self.model(new_model=nil)
37
+ if new_model == nil
38
+ @model
39
+ else
40
+ @model = new_model
41
+ end
42
+ end
43
+
44
+ def clear
45
+ @loaded = true
46
+ super
47
+ end
48
+
49
+ def create(attributes = {})
50
+ object = new(attributes)
51
+ object.save
52
+ object
53
+ end
54
+
55
+ def destroy(identity)
56
+ object = new(:identity => identity)
57
+ object.destroy
58
+ end
59
+
60
+ # Creates a new Fog::Collection based around the passed service
61
+ #
62
+ # @param [Hash] attributes
63
+ # @option attributes [Fog::Service] service Instance of a service
64
+ #
65
+ # @return [Fog::Collection]
66
+ #
67
+ def initialize(attributes = {})
68
+ @service = attributes.delete(:service)
69
+ @loaded = false
70
+ merge_attributes(attributes)
71
+ end
72
+
73
+
74
+ def inspect
75
+ Thread.current[:formatador] ||= Formatador.new
76
+ data = "#{Thread.current[:formatador].indentation}<#{self.class.name}\n"
77
+ Thread.current[:formatador].indent do
78
+ unless self.class.attributes.empty?
79
+ data << "#{Thread.current[:formatador].indentation}"
80
+ data << self.class.attributes.map {|attribute| "#{attribute}=#{send(attribute).inspect}"}.join(",\n#{Thread.current[:formatador].indentation}")
81
+ data << "\n"
82
+ end
83
+ data << "#{Thread.current[:formatador].indentation}["
84
+ unless self.empty?
85
+ data << "\n"
86
+ Thread.current[:formatador].indent do
87
+ data << self.map {|member| member.inspect}.join(",\n")
88
+ data << "\n"
89
+ end
90
+ data << Thread.current[:formatador].indentation
91
+ end
92
+ data << "]\n"
93
+ end
94
+ data << "#{Thread.current[:formatador].indentation}>"
95
+ data
96
+ end
97
+
98
+ def load(objects)
99
+ clear
100
+ for object in objects
101
+ self << new(object)
102
+ end
103
+ self
104
+ end
105
+
106
+ def model
107
+ self.class.instance_variable_get('@model')
108
+ end
109
+
110
+ def new(attributes = {})
111
+ unless attributes.is_a?(::Hash)
112
+ raise(ArgumentError.new("Initialization parameters must be an attributes hash, got #{attributes.class} #{attributes.inspect}"))
113
+ end
114
+ model.new(
115
+ {
116
+ :collection => self,
117
+ :service => service
118
+ }.merge(attributes)
119
+ )
120
+ end
121
+
122
+ def reload
123
+ clear
124
+ lazy_load
125
+ self
126
+ end
127
+
128
+ def table(attributes = nil)
129
+ Formatador.display_table(self.map {|instance| instance.attributes}, attributes)
130
+ end
131
+
132
+ def to_json(options = {})
133
+ Fog::JSON.encode(self.map {|member| member.attributes})
134
+ end
135
+
136
+ private
137
+
138
+ def lazy_load
139
+ self.all
140
+ end
141
+
142
+ end
143
+
144
+ # Base class for collection classes whose 'all' method returns only a single page of results and passes the
145
+ # 'Marker' option along as self.filters[:marker]
146
+ class PagedCollection < Collection
147
+
148
+ def each(filters=filters)
149
+ if block_given?
150
+ begin
151
+ page = self.all(filters)
152
+ # We need to explicitly use the base 'each' method here on the page, otherwise we get infinite recursion
153
+ base_each = Fog::Collection.instance_method(:each)
154
+ base_each.bind(page).call { |item| yield item }
155
+ end while self.filters[:marker]
156
+ end
157
+ self
158
+ end
159
+
160
+ end
161
+ end
@@ -0,0 +1,72 @@
1
+ module Fog
2
+ module Core
3
+
4
+ # Fog::Core::Connection is a generic class to contain a HTTP link to an API.
5
+ #
6
+ # It is intended to be subclassed by providers who can then add their own
7
+ # modifications such as authentication or response object.
8
+ #
9
+ class Connection
10
+ # Prepares the connection and sets defaults for any future requests.
11
+ #
12
+ # @param [String] url The destination URL
13
+ # @param persistent [Boolean]
14
+ # @param [Hash] params
15
+ # @option params [String] :body Default text to be sent over a socket. Only used if :body absent in Connection#request params
16
+ # @option params [Hash<Symbol, String>] :headers The default headers to supply in a request. Only used if params[:headers] is not supplied to Connection#request
17
+ # @option params [String] :host The destination host's reachable DNS name or IP, in the form of a String
18
+ # @option params [String] :path Default path; appears after 'scheme://host:port/'. Only used if params[:path] is not supplied to Connection#request
19
+ # @option params [Fixnum] :port The port on which to connect, to the destination host
20
+ # @option params [Hash] :query Default query; appended to the 'scheme://host:port/path/' in the form of '?key=value'. Will only be used if params[:query] is not supplied to Connection#request
21
+ # @option params [String] :scheme The protocol; 'https' causes OpenSSL to be used
22
+ # @option params [String] :proxy Proxy server; e.g. 'http://myproxy.com:8888'
23
+ # @option params [Fixnum] :retry_limit Set how many times we'll retry a failed request. (Default 4)
24
+ # @option params [Class] :instrumentor Responds to #instrument as in ActiveSupport::Notifications
25
+ # @option params [String] :instrumentor_name Name prefix for #instrument events. Defaults to 'excon'
26
+ #
27
+ def initialize(url, persistent=false, params={})
28
+ unless params.has_key?(:debug_response)
29
+ params[:debug_response] = true
30
+ end
31
+ params[:headers] ||= {}
32
+ params[:headers]['User-Agent'] ||= "fog/#{Fog::VERSION}"
33
+ params.merge!(:persistent => params.fetch(:persistent, persistent))
34
+ @excon = Excon.new(url, params)
35
+ end
36
+
37
+ # Makes a request using the connection using Excon
38
+ #
39
+ # @param [Hash] params
40
+ # @option params [String] :body text to be sent over a socket
41
+ # @option params [Hash<Symbol, String>] :headers The default headers to supply in a request
42
+ # @option params [String] :host The destination host's reachable DNS name or IP, in the form of a String
43
+ # @option params [String] :path appears after 'scheme://host:port/'
44
+ # @option params [Fixnum] :port The port on which to connect, to the destination host
45
+ # @option params [Hash] :query appended to the 'scheme://host:port/path/' in the form of '?key=value'
46
+ # @option params [String] :scheme The protocol; 'https' causes OpenSSL to be used
47
+ # @option params [Proc] :response_block
48
+ #
49
+ # @return [Excon::Response]
50
+ #
51
+ # @raise [Excon::Errors::StubNotFound]
52
+ # @raise [Excon::Errors::Timeout]
53
+ # @raise [Excon::Errors::SocketError]
54
+ #
55
+ def request(params, &block)
56
+ @excon.request(params, &block)
57
+ end
58
+
59
+ # Make {#request} available even when it has been overidden by a subclass
60
+ # to allow backwards compatibility.
61
+ #
62
+ alias_method :original_request, :request
63
+ protected :original_request
64
+
65
+ # Closes the connection
66
+ #
67
+ def reset
68
+ @excon.reset
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,70 @@
1
+ require 'yaml'
2
+
3
+ module Fog
4
+ require 'fog/core/deprecation'
5
+
6
+ # Assign a new credential to use from configuration file
7
+ # @param [String, Symbol] new_credential name of new credential to use
8
+ # @ return [Symbol] name of the new credential
9
+ def self.credential=(new_credential)
10
+ @credentials = nil
11
+ @credential = new_credential && new_credential.to_sym
12
+ end
13
+
14
+ # @return [String, Symbol] The credential to use in Fog
15
+ def self.credential
16
+ @credential ||= ( ENV["FOG_CREDENTIAL"] && ENV["FOG_CREDENTIAL"].to_sym ) || :default
17
+ end
18
+
19
+ # @return [String] The path for configuration_file
20
+ def self.credentials_path
21
+ @credential_path ||= begin
22
+ path = ENV["FOG_RC"] || (ENV['HOME'] && File.directory?(ENV['HOME']) && '~/.fog')
23
+ File.expand_path(path) if path
24
+ rescue
25
+ nil
26
+ end
27
+ end
28
+
29
+ # @return [String] The new path for credentials file
30
+ def self.credentials_path=(new_credentials_path)
31
+ @credentials = nil
32
+ @credential_path = new_credentials_path
33
+ end
34
+
35
+ # @return [Hash] The credentials pulled from the configuration file
36
+ # @raise [LoadError] Configuration unavailable in configuration file
37
+ def self.credentials
38
+ @credentials ||= begin
39
+ if credentials_path && File.exists?(credentials_path)
40
+ credentials = self.symbolize_credentials(YAML.load_file(credentials_path))
41
+ (credentials && credentials[credential]) || Fog::Errors.missing_credentials
42
+ else
43
+ {}
44
+ end
45
+ end
46
+ end
47
+
48
+ # @return [Hash] The newly assigned credentials
49
+ def self.credentials=(new_credentials)
50
+ @credentials = new_credentials
51
+ end
52
+
53
+ def self.symbolize_credential?(key)
54
+ ![:headers].include?(key)
55
+ end
56
+
57
+ def self.symbolize_credentials(args)
58
+ if args.is_a? Hash
59
+ copy = Array.new
60
+ args.each do |key, value|
61
+ obj = symbolize_credential?(key) ? self.symbolize_credentials(value) : value
62
+ copy.push(key.to_sym, obj)
63
+ end
64
+ Hash[*copy]
65
+ else
66
+ args
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,34 @@
1
+ require 'thread'
2
+ module Fog
3
+ class CurrentMachine
4
+ @@lock = Mutex.new
5
+ AMAZON_AWS_CHECK_IP = 'http://checkip.amazonaws.com'
6
+
7
+ def self.ip_address= ip_address
8
+ @@lock.synchronize do
9
+ @@ip_address = ip_address
10
+ end
11
+ end
12
+
13
+ # Get the ip address of the machine from which this command is run. It is
14
+ # recommended that you surround calls to this function with a timeout block
15
+ # to ensure optimum performance in the case where the amazonaws checkip
16
+ # service is unavailable.
17
+ #
18
+ # @example Get the current ip address
19
+ # begin
20
+ # Timeout::timeout(5) do
21
+ # puts "Your ip address is #{Fog::CurrentMachine.ip_address}"
22
+ # end
23
+ # rescue Timeout::Error
24
+ # puts "Service timeout"
25
+ # end
26
+ #
27
+ # @raise [Excon::Errors::Error] if the net/http request fails.
28
+ def self.ip_address
29
+ @@lock.synchronize do
30
+ @@ip_address ||= Excon.get(AMAZON_AWS_CHECK_IP).body.chomp
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ module Fog
2
+ module Core
3
+ # This module covers the shared code used by models and collections
4
+ # that deprecates the confusing usage of 'connection' which was
5
+ # actually intended to be an instance of Fog::Service
6
+ module DeprecatedConnectionAccessors
7
+ # Sets the Service but using the wrong name!
8
+ #
9
+ # @deprecated The connection name was wrong and confusing since it refered to the service
10
+ # @param [Fog::Service] service An instance of a Fog service this collection is for
11
+ #
12
+ def connection=(service)
13
+ Fog::Logger.deprecation("#connection= is deprecated, pass :service in at creation [light_black](#{caller.first})[/]")
14
+ @service = service
15
+ end
16
+
17
+ # Returns the Service the collection is part of
18
+ #
19
+ # @deprecated #connection is deprecated due to confusing name, use #service instead
20
+ # @return [Fog::Service]
21
+ #
22
+ def connection
23
+ Fog::Logger.deprecation("#connection is deprecated, use #service instead [light_black](#{caller.first})[/]")
24
+ @service
25
+ end
26
+
27
+ # Prepares the value of the service based on the passed attributes
28
+ #
29
+ # @note Intended for use where the service is required before the normal
30
+ # initializer runs. The logic is run there with deprecation warnings.
31
+ #
32
+ # @param [Hash] attributes
33
+ # @return [Fog::Service]
34
+ #
35
+ def prepare_service_value(attributes)
36
+ @service = attributes[:service] || attributes[:connection]
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ module Fog
2
+ module Deprecation
3
+
4
+ def deprecate(older, newer)
5
+ module_eval <<-EOS, __FILE__, __LINE__
6
+ def #{older}(*args)
7
+ Fog::Logger.deprecation("#{self} => ##{older} is deprecated, use ##{newer} instead [light_black](#{caller.first})[/]")
8
+ send(:#{newer}, *args)
9
+ end
10
+ EOS
11
+ end
12
+
13
+ def self_deprecate(older, newer)
14
+ module_eval <<-EOS, __FILE__, __LINE__
15
+ def self.#{older}(*args)
16
+ Fog::Logger.deprecation("#{self} => ##{older} is deprecated, use ##{newer} instead [light_black](#{caller.first})[/]")
17
+ send(:#{newer}, *args)
18
+ end
19
+ EOS
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,118 @@
1
+ module Fog
2
+ module Errors
3
+
4
+ class Error < StandardError
5
+ attr_accessor :verbose
6
+
7
+ def self.slurp(error, message = nil)
8
+ new_error = new(message || error.message)
9
+ new_error.set_backtrace(error.backtrace)
10
+ new_error.verbose = error.message
11
+ new_error
12
+ end
13
+ end
14
+
15
+ class MockNotImplemented < Fog::Errors::Error; end
16
+
17
+ class NotFound < Fog::Errors::Error; end
18
+
19
+ class LoadError < LoadError; end
20
+
21
+ class TimeoutError< Fog::Errors::Error; end
22
+
23
+ class NotImplemented < Fog::Errors::Error; end
24
+
25
+ # @return [String] The error message that will be raised, if credentials cannot be found
26
+ def self.missing_credentials
27
+ missing_credentials_message = <<-YML
28
+ Missing Credentials
29
+
30
+ To run as '#{Fog.credential}', add the following to your resource config file: #{Fog.credentials_path}
31
+ An alternate file may be used by placing its path in the FOG_RC environment variable
32
+
33
+ #######################################################
34
+ # Fog Credentials File
35
+ #
36
+ # Key-value pairs should look like:
37
+ # :aws_access_key_id: 022QF06E7MXBSAMPLE
38
+ :#{Fog.credential}:
39
+ :aws_access_key_id:
40
+ :aws_secret_access_key:
41
+ :bluebox_api_key:
42
+ :bluebox_customer_id:
43
+ :brightbox_client_id:
44
+ :brightbox_secret:
45
+ :clodo_api_key:
46
+ :clodo_username:
47
+ :go_grid_api_key:
48
+ :go_grid_shared_secret:
49
+ :google_client_email:
50
+ :google_key_location:
51
+ :google_project:
52
+ :google_storage_access_key_id:
53
+ :google_storage_secret_access_key:
54
+ :hp_access_key:
55
+ :hp_secret_key:
56
+ :hp_tenant_id:
57
+ :hp_avl_zone:
58
+ :linode_api_key:
59
+ :local_root:
60
+ :bare_metal_cloud_password:
61
+ :bare_metal_cloud_username:
62
+ :public_key_path:
63
+ :private_key_path:
64
+ :openstack_api_key:
65
+ :openstack_username:
66
+ :openstack_auth_url:
67
+ :openstack_tenant:
68
+ :openstack_region:
69
+ :ovirt_username:
70
+ :ovirt_password:
71
+ :ovirt_url:
72
+ :libvirt_uri:
73
+ :rackspace_api_key:
74
+ :rackspace_username:
75
+ :rackspace_servicenet:
76
+ :rackspace_cdn_ssl:
77
+ :rage4_email:
78
+ :rage4_password:
79
+ :riakcs_access_key_id:
80
+ :riakcs_secret_access_key:
81
+ :stormondemand_username:
82
+ :stormondemand_password:
83
+ :terremark_username:
84
+ :terremark_password:
85
+ :voxel_api_key:
86
+ :voxel_api_secret:
87
+ :zerigo_email:
88
+ :zerigo_token:
89
+ :dnsimple_email:
90
+ :dnsimple_password:
91
+ :dnsmadeeasy_api_key:
92
+ :dnsmadeeasy_secret_key:
93
+ :dreamhost_api_key:
94
+ :cloudstack_host:
95
+ :cloudstack_api_key:
96
+ :cloudstack_secret_access_key:
97
+ :vsphere_server:
98
+ :vsphere_username:
99
+ :vsphere_password:
100
+ :libvirt_username:
101
+ :libvirt_password:
102
+ :libvirt_uri:
103
+ :libvirt_ip_command:
104
+ :ibm_username:
105
+ :ibm_password:
106
+ :vcloud_director_host:
107
+ :vcloud_director_username:
108
+ :vcloud_director_password:
109
+ #
110
+ # End of Fog Credentials File
111
+ #######################################################
112
+
113
+ YML
114
+ raise(Fog::Errors::LoadError.new(missing_credentials_message))
115
+ end
116
+
117
+ end
118
+ end