deltacloud-client 1.1.2 → 1.1.3

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 (205) hide show
  1. data/README.md +73 -0
  2. data/Rakefile +88 -5
  3. data/lib/deltacloud/client.rb +79 -0
  4. data/lib/deltacloud/client/base_error.rb +80 -0
  5. data/lib/deltacloud/client/connection.rb +139 -0
  6. data/lib/deltacloud/client/helpers/model_helper.rb +69 -0
  7. data/lib/deltacloud/client/helpers/property_helper.rb +103 -0
  8. data/lib/deltacloud/client/helpers/xml_helper.rb +33 -0
  9. data/lib/deltacloud/client/methods.rb +33 -0
  10. data/lib/deltacloud/client/methods/address.rb +67 -0
  11. data/lib/deltacloud/client/methods/api.rb +96 -0
  12. data/lib/deltacloud/client/methods/backward_compatiblity.rb +72 -0
  13. data/lib/deltacloud/client/methods/blob.rb +91 -0
  14. data/lib/deltacloud/client/methods/bucket.rb +55 -0
  15. data/lib/deltacloud/client/methods/common.rb +46 -0
  16. data/lib/deltacloud/client/methods/driver.rb +53 -0
  17. data/lib/deltacloud/client/methods/firewall.rb +67 -0
  18. data/lib/deltacloud/client/methods/hardware_profile.rb +41 -0
  19. data/lib/deltacloud/client/methods/image.rb +61 -0
  20. data/lib/deltacloud/client/methods/instance.rb +141 -0
  21. data/lib/deltacloud/client/methods/instance_state.rb +41 -0
  22. data/lib/deltacloud/client/methods/key.rb +58 -0
  23. data/lib/deltacloud/client/methods/load_balancer.rb +96 -0
  24. data/lib/deltacloud/client/methods/metric.rb +54 -0
  25. data/lib/deltacloud/client/methods/realm.rb +42 -0
  26. data/lib/deltacloud/client/methods/storage_snapshot.rb +61 -0
  27. data/lib/deltacloud/client/methods/storage_volume.rb +94 -0
  28. data/lib/deltacloud/client/models.rb +32 -0
  29. data/lib/deltacloud/client/models/address.rb +57 -0
  30. data/lib/deltacloud/client/models/base.rb +153 -0
  31. data/lib/deltacloud/client/models/blob.rb +56 -0
  32. data/lib/deltacloud/client/models/bucket.rb +65 -0
  33. data/lib/deltacloud/client/models/driver.rb +87 -0
  34. data/lib/deltacloud/client/models/firewall.rb +64 -0
  35. data/lib/deltacloud/client/models/hardware_profile.rb +68 -0
  36. data/lib/deltacloud/client/models/image.rb +60 -0
  37. data/lib/deltacloud/client/models/instance.rb +142 -0
  38. data/lib/deltacloud/client/models/instance_address.rb +40 -0
  39. data/lib/{instance_state.rb → deltacloud/client/models/instance_state.rb} +11 -3
  40. data/lib/deltacloud/client/models/key.rb +52 -0
  41. data/lib/deltacloud/client/models/load_balancer.rb +55 -0
  42. data/lib/deltacloud/client/models/metric.rb +72 -0
  43. data/lib/deltacloud/client/models/realm.rb +29 -0
  44. data/lib/deltacloud/client/models/storage_snapshot.rb +54 -0
  45. data/lib/deltacloud/client/models/storage_volume.rb +96 -0
  46. data/lib/deltacloud/core_ext.rb +19 -0
  47. data/lib/deltacloud/core_ext/element.rb +32 -0
  48. data/lib/deltacloud/core_ext/fixnum.rb +30 -0
  49. data/lib/deltacloud/core_ext/nil.rb +22 -0
  50. data/lib/{string.rb → deltacloud/core_ext/string.rb} +16 -26
  51. data/lib/deltacloud/error_response.rb +93 -0
  52. data/tests/client/client_test.rb +51 -0
  53. data/tests/client/connection_test.rb +77 -0
  54. data/tests/core_ext/element_test.rb +40 -0
  55. data/tests/core_ext/fixnum_test.rb +35 -0
  56. data/tests/core_ext/nil.rb +27 -0
  57. data/tests/core_ext/string_test.rb +47 -0
  58. data/tests/fixtures/instances_cleanup.yml +681 -0
  59. data/tests/fixtures/test_0001_connects_to_Deltacloud_API.yml +60 -0
  60. data/tests/fixtures/test_0001_support_cpu.yml +444 -0
  61. data/tests/fixtures/test_0001_support_original_body.yml +116 -0
  62. data/tests/fixtures/test_0001_supports_addresses.yml +178 -0
  63. data/tests/fixtures/test_0001_supports_api_host.yml +60 -0
  64. data/tests/fixtures/test_0001_supports_attached_.yml +282 -0
  65. data/tests/fixtures/test_0001_supports_blobs.yml +475 -0
  66. data/tests/fixtures/test_0001_supports_bucket.yml +200 -0
  67. data/tests/fixtures/test_0001_supports_buckets.yml +160 -0
  68. data/tests/fixtures/test_0001_supports_drivers.yml +202 -0
  69. data/tests/fixtures/test_0001_supports_firewalls.yml +399 -0
  70. data/tests/fixtures/test_0001_supports_hardware_profiles.yml +262 -0
  71. data/tests/fixtures/test_0001_supports_images.yml +224 -0
  72. data/tests/fixtures/test_0001_supports_instance_states.yml +156 -0
  73. data/tests/fixtures/test_0001_supports_instances.yml +486 -0
  74. data/tests/fixtures/test_0001_supports_keys.yml +198 -0
  75. data/tests/fixtures/test_0001_supports_path.yml +60 -0
  76. data/tests/fixtures/test_0001_supports_realms.yml +152 -0
  77. data/tests/fixtures/test_0001_supports_storage_snapshots.yml +164 -0
  78. data/tests/fixtures/test_0001_supports_storage_volumes.yml +176 -0
  79. data/tests/fixtures/test_0001_supports_to_get_providers.yml +410 -0
  80. data/tests/fixtures/test_0002_support_blob.yml +148 -0
  81. data/tests/fixtures/test_0002_support_instance_state.yml +204 -0
  82. data/tests/fixtures/test_0002_support_memory.yml +444 -0
  83. data/tests/fixtures/test_0002_support_on_Provider.yml +130 -0
  84. data/tests/fixtures/test_0002_supports_api_port.yml +60 -0
  85. data/tests/fixtures/test_0002_supports_api_uri.yml +60 -0
  86. data/tests/fixtures/test_0002_supports_driver.yml +219 -0
  87. data/tests/fixtures/test_0002_supports_extract_xml_body_using_faraday_connection.yml +117 -0
  88. data/tests/fixtures/test_0002_supports_filtering_addresses_by_id_param.yml +156 -0
  89. data/tests/fixtures/test_0002_supports_filtering_buckets_by_id_param.yml +156 -0
  90. data/tests/fixtures/test_0002_supports_filtering_firewalls_by_id_param.yml +207 -0
  91. data/tests/fixtures/test_0002_supports_filtering_hardware_profiles_by_id_param.yml +158 -0
  92. data/tests/fixtures/test_0002_supports_filtering_images_by_id_param.yml +165 -0
  93. data/tests/fixtures/test_0002_supports_filtering_instances_by_id_param.yml +164 -0
  94. data/tests/fixtures/test_0002_supports_filtering_keys_by_id_param.yml +178 -0
  95. data/tests/fixtures/test_0002_supports_filtering_realms_by_id.yml +104 -0
  96. data/tests/fixtures/test_0002_supports_filtering_storage_snapshots_by_id_param.yml +155 -0
  97. data/tests/fixtures/test_0002_supports_filtering_storage_volumes_by_id_param.yml +157 -0
  98. data/tests/fixtures/test_0002_supports_hardware_profiles.yml +262 -0
  99. data/tests/fixtures/test_0002_supports_is_compatible_.yml +116 -0
  100. data/tests/fixtures/test_0002_supports_snapshot_.yml +202 -0
  101. data/tests/fixtures/test_0002_supports_version.yml +60 -0
  102. data/tests/fixtures/test_0003_caches_the_API_entrypoint.yml +60 -0
  103. data/tests/fixtures/test_0003_support_address.yml +197 -0
  104. data/tests/fixtures/test_0003_support_bucket.yml +198 -0
  105. data/tests/fixtures/test_0003_support_create_blob.yml +105 -0
  106. data/tests/fixtures/test_0003_support_create_blob_and_destroy_blob.yml +138 -0
  107. data/tests/fixtures/test_0003_support_firewall.yml +768 -0
  108. data/tests/fixtures/test_0003_support_hardware_profile.yml +199 -0
  109. data/tests/fixtures/test_0003_support_image.yml +207 -0
  110. data/tests/fixtures/test_0003_support_instance.yml +206 -0
  111. data/tests/fixtures/test_0003_support_key.yml +220 -0
  112. data/tests/fixtures/test_0003_support_realm.yml +195 -0
  113. data/tests/fixtures/test_0003_support_storage.yml +444 -0
  114. data/tests/fixtures/test_0003_support_storage_snapshot.yml +196 -0
  115. data/tests/fixtures/test_0003_support_storage_volume.yml +197 -0
  116. data/tests/fixtures/test_0003_support_to_change_driver_with_Client.yml +72 -0
  117. data/tests/fixtures/test_0003_supports_connect.yml +60 -0
  118. data/tests/fixtures/test_0003_supports_extract_xml_body_using_nokogiri_document.yml +117 -0
  119. data/tests/fixtures/test_0003_supports_instance.yml +396 -0
  120. data/tests/fixtures/test_0003_supports_is_compatible_.yml +116 -0
  121. data/tests/fixtures/test_0003_supports_lunch_image.yml +367 -0
  122. data/tests/fixtures/test_0003_supports_providers.yml +102 -0
  123. data/tests/fixtures/test_0003_supports_version.yml +60 -0
  124. data/tests/fixtures/test_0004_support_architecture.yml +444 -0
  125. data/tests/fixtures/test_0004_support_create_address.yml +197 -0
  126. data/tests/fixtures/test_0004_support_create_blob_and_destroy_blob_with_meta_params.yml +139 -0
  127. data/tests/fixtures/test_0004_support_create_bucket.yml +180 -0
  128. data/tests/fixtures/test_0004_support_create_bucket_and_destroy_bucket.yml +180 -0
  129. data/tests/fixtures/test_0004_support_create_firewall_and_destroy_firewall.yml +496 -0
  130. data/tests/fixtures/test_0004_support_create_image_and_destroy_image.yml +1527 -0
  131. data/tests/fixtures/test_0004_support_create_instance.yml +115 -0
  132. data/tests/fixtures/test_0004_support_create_key_and_destroy_key.yml +206 -0
  133. data/tests/fixtures/test_0004_support_create_volume.yml +105 -0
  134. data/tests/fixtures/test_0004_support_create_volume_and_destroy_volume.yml +181 -0
  135. data/tests/fixtures/test_0004_support_to_test_of_valid_DC_connection.yml +60 -0
  136. data/tests/fixtures/test_0004_supports_current_driver.yml +60 -0
  137. data/tests/fixtures/test_0004_supports_extract_xml_body_using_nokogiri_element.yml +117 -0
  138. data/tests/fixtures/test_0004_supports_lunch_image.yml +312 -0
  139. data/tests/fixtures/test_0004_supports_valid_credentials_.yml +215 -0
  140. data/tests/fixtures/test_0004_supports_with_config.yml +129 -0
  141. data/tests/fixtures/test_0005_support_attach_storage_volume.yml +102 -0
  142. data/tests/fixtures/test_0005_support_attach_storage_volume_and_detach_storage_volume.yml +142 -0
  143. data/tests/fixtures/test_0005_support_create_instance_with_hwp_id.yml +115 -0
  144. data/tests/fixtures/test_0005_support_opaque_.yml +152 -0
  145. data/tests/fixtures/test_0005_supports_current_provider.yml +134 -0
  146. data/tests/fixtures/test_0005_supports_id.yml +116 -0
  147. data/tests/fixtures/test_0005_supports_switching_drivers_per_instance.yml +129 -0
  148. data/tests/fixtures/test_0005_supports_use_driver.yml +60 -0
  149. data/tests/fixtures/test_0006_support_create_instance_with_realm_id.yml +115 -0
  150. data/tests/fixtures/test_0006_supports_discovered_.yml +60 -0
  151. data/tests/fixtures/test_0006_supports_supported_collections.yml +60 -0
  152. data/tests/fixtures/test_0006_supports_switching_providers_per_instance.yml +208 -0
  153. data/tests/fixtures/test_0007_support_create_instance_with_name.yml +115 -0
  154. data/tests/fixtures/test_0007_support_switching_provider_without_credentials.yml +208 -0
  155. data/tests/fixtures/test_0007_supports_support_.yml +60 -0
  156. data/tests/fixtures/test_0007_supports_valid_credentials_on_class.yml +370 -0
  157. data/tests/fixtures/test_0008_support_stop_instance.yml +166 -0
  158. data/tests/fixtures/test_0008_supports_must_support_.yml +60 -0
  159. data/tests/fixtures/test_0009_support_start_instance.yml +217 -0
  160. data/tests/fixtures/test_0009_supports_features.yml +60 -0
  161. data/tests/fixtures/test_0010_support_reboot_instance.yml +166 -0
  162. data/tests/fixtures/test_0010_supports_feature_.yml +60 -0
  163. data/tests/helpers/model_test.rb +33 -0
  164. data/tests/helpers/xml_test.rb +56 -0
  165. data/tests/methods/address_test.rb +64 -0
  166. data/tests/methods/api_test.rb +97 -0
  167. data/tests/methods/backward_compatibility_test.rb +87 -0
  168. data/tests/methods/blob_test.rb +64 -0
  169. data/tests/methods/bucket_test.rb +62 -0
  170. data/tests/methods/driver_test.rb +48 -0
  171. data/tests/methods/firewall_test.rb +84 -0
  172. data/tests/methods/hardware_profile_test.rb +53 -0
  173. data/tests/methods/image_test.rb +64 -0
  174. data/tests/methods/instance_state_test.rb +43 -0
  175. data/tests/methods/instance_test.rb +126 -0
  176. data/tests/methods/key_test.rb +63 -0
  177. data/tests/methods/realm_test.rb +50 -0
  178. data/tests/methods/storage_snapshot_test.rb +53 -0
  179. data/tests/methods/storage_volume_test.rb +81 -0
  180. data/tests/models/blob_test.rb +40 -0
  181. data/tests/models/bucket_test.rb +37 -0
  182. data/tests/models/driver_test.rb +42 -0
  183. data/tests/models/hardware_profile_test.rb +80 -0
  184. data/tests/models/image_test.rb +65 -0
  185. data/tests/models/storage_volume_test.rb +52 -0
  186. data/tests/test_helper.rb +59 -11
  187. metadata +392 -41
  188. data/lib/base_object.rb +0 -386
  189. data/lib/client_bucket_methods.rb +0 -69
  190. data/lib/deltacloud.rb +0 -486
  191. data/lib/documentation.rb +0 -59
  192. data/lib/errors.rb +0 -140
  193. data/lib/hwp_properties.rb +0 -61
  194. data/tests/buckets_test.rb +0 -141
  195. data/tests/client_test.rb +0 -59
  196. data/tests/content_negotiation_test.rb +0 -127
  197. data/tests/errors_test.rb +0 -57
  198. data/tests/hardware_profiles_test.rb +0 -75
  199. data/tests/images_test.rb +0 -102
  200. data/tests/instance_states_test.rb +0 -66
  201. data/tests/instances_test.rb +0 -203
  202. data/tests/keys_test.rb +0 -81
  203. data/tests/realms_test.rb +0 -64
  204. data/tests/storage_snapshot_test.rb +0 -76
  205. data/tests/storage_volume_test.rb +0 -86
@@ -0,0 +1,73 @@
1
+ # deltacloud-client
2
+
3
+ The Deltacloud project includes a Ruby client. Other language-bindings
4
+ are possible and will be supported soon. The client aims to insulate
5
+ users from having to deal with HTTP and REST directly.
6
+
7
+ Each resource type has an associated model to ease usage. Where
8
+ resource reference other resources, natural navigation across the
9
+ object model is possible.
10
+
11
+ This is a Ruby client library for the [Deltacloud API](http://deltacloud.apache.org).
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ require 'deltacloud/client'
17
+
18
+ API_URL = "http://localhost:3001/api" # Deltacloud API endpoint
19
+
20
+ # Simple use-cases
21
+ client = Deltacloud::Client(API_URL, 'mockuser', 'mockpassword')
22
+
23
+ pp client.instances # List all instances
24
+ pp client.instance('i-12345') # Get one instance
25
+
26
+ inst = client.create_instance 'ami-1234', :hwp_id => 'm1.small' # Create instance
27
+
28
+ inst.reboot! # Reboot instance
29
+
30
+ # Advanced usage
31
+
32
+ # Deltacloud API supports changing driver per-request:
33
+
34
+ client.use(:ec2, 'API_KEY', 'API_SECRET').instances # List EC2 instances
35
+ client.use(:openstack, 'admin@tenant', 'password', KEYSTONE_URL).instances # List Openstack instances
36
+
37
+ ```
38
+ # Want help?
39
+
40
+ ## Adding new Deltacloud collection to client
41
+
42
+ ```
43
+ $ rake generate[YOUR_COLLECTION] # eg. 'storage_snapshot'
44
+ # Hit Enter 2x
45
+ ```
46
+
47
+ - Edit `lib/deltacloud/client/methods/YOUR_COLLECTION.rb` and add all
48
+ methods for manipulating your collection. The list/show methods
49
+ should already be generated for you, but double-check them.
50
+
51
+ - Edit `lib/deltacloud/client/model/YOUR_COLLECTION.rb` and add model
52
+ methods. Model methods should really be just a syntax sugar and exercise
53
+ the *Deltacloud::Client::Methods* methods.
54
+ The purpose of *model* class life is to deserialize XML body received
55
+ from Deltacloud API to a Ruby class.
56
+
57
+ ## Debugging a nasty bug?
58
+
59
+ - You can easily debug deltacloud-client using powerful **pry**.
60
+
61
+ - `gem install deltacloud-core`
62
+ - optional: `rbenv rehash` ;-)
63
+ - `deltacloudd -i mock -p 3002`
64
+ - `rake console`
65
+
66
+ Console require **pry** gem installed. If you are not using this awesome
67
+ gem, you can fix it by `gem install pry`.
68
+
69
+ # License
70
+
71
+ Apache License
72
+ Version 2.0, January 2004
73
+ http://www.apache.org/licenses/
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- #
2
1
  # Licensed to the Apache Software Foundation (ASF) under one or more
3
2
  # contributor license agreements. See the NOTICE file distributed with
4
3
  # this work for additional information regarding copyright ownership. The
@@ -14,26 +13,110 @@
14
13
  # License for the specific language governing permissions and limitations
15
14
  # under the License.
16
15
 
16
+ require 'rubygems'
17
17
  require 'rubygems/package_task'
18
+ require 'rake'
18
19
  require 'rake/testtask'
19
20
 
20
- load 'deltacloud-client.gemspec'
21
-
22
21
  spec = Gem::Specification.load('deltacloud-client.gemspec')
23
22
 
24
23
  Gem::PackageTask.new(spec) do |pkg|
25
24
  pkg.need_tar = true
26
25
  end
27
26
 
28
- desc "Re-install the deltacloud-client gem"
27
+ desc "Re-install the deltacloud-client gem (used for development)"
29
28
  task :reinstall do
30
29
  puts %x{gem uninstall deltacloud-client --all -I -x}
31
30
  puts %x{gem build deltacloud-client.gemspec}
32
31
  puts %x{gem install deltacloud-client-*.gem --local}
33
32
  end
34
33
 
34
+ desc 'Generate model/methods files for collection.'
35
+ task :generate, :name do |t, args|
36
+ require 'erb'
37
+ require_relative './lib/deltacloud/core_ext'
38
+ model_tpl = ERB.new(File.read('support/model_template.erb'))
39
+ methods_tpl = ERB.new(File.read('support/methods_template.erb'))
40
+ name = args[:name]
41
+ model_file = "lib/deltacloud/client/models/#{name}.rb"
42
+ methods_file = "lib/deltacloud/client/methods/#{name}.rb"
43
+ puts model_body = model_tpl.result(binding)
44
+ print "Save model to '#{model_file}'? [Y/n]"
45
+ answer = $stdin.gets.chomp
46
+ if answer.empty? or answer == 'Y'
47
+ File.open(model_file, 'w') { |f|
48
+ f.write(model_body)
49
+ }
50
+ File.open('lib/deltacloud/client/models.rb', 'a') { |f|
51
+ f.puts "require_relative './models/#{name}'"
52
+ }
53
+ end
54
+ puts methods_body = methods_tpl.result(binding)
55
+ print "Save methods to '#{methods_file}'? [Y/n]"
56
+ answer = $stdin.gets.chomp
57
+ if answer.empty? or answer == 'Y'
58
+ File.open(methods_file, 'w') { |f|
59
+ f.write(methods_body)
60
+ }
61
+ File.open('lib/deltacloud/client/methods.rb', 'a') { |f|
62
+ f.puts "require_relative './methods/#{name}'"
63
+ }
64
+ end
65
+ puts
66
+ puts "Don't forget to add this line to 'lib/deltacloud/client/connection.rb':"
67
+ puts
68
+ puts "include Deltacloud::Client::Methods::#{name.to_s.camelize}"
69
+ puts
70
+ end
71
+
72
+ desc 'Generate method test file'
73
+ task :test_generate, :name do |t, args|
74
+ require 'erb'
75
+ require_relative './lib/deltacloud/core_ext'
76
+ method_tpl = ERB.new(File.read('support/method_test_template.erb'))
77
+ name = args[:name]
78
+ methods_file = "tests/methods/#{name}_test.rb"
79
+ puts method_body = method_tpl.result(binding)
80
+ print "Save method test to '#{methods_file}'? [Y/n]"
81
+ answer = $stdin.gets.chomp
82
+ if answer.empty? or answer == 'Y'
83
+ File.open(methods_file, 'w') { |f|
84
+ f.write(method_body)
85
+ }
86
+ end
87
+ end
88
+
89
+
90
+ desc "Open console with client connected to #{ENV['API_URL'] || 'localhost:3002/api'}"
91
+ task :console do
92
+ require 'pry'
93
+ unless binding.respond_to? :pry
94
+ puts 'To open a console, you need to have "pry" installed (gem install pry)'
95
+ exit(1)
96
+ end
97
+ require_relative './lib/deltacloud/client'
98
+ client = Deltacloud::Client(
99
+ ENV['API_URL'] || 'http://localhost:3002/api',
100
+ ENV['API_USER'] || 'mockuser',
101
+ ENV['API_PASSWORD'] || 'mockpassword'
102
+ )
103
+ binding.pry
104
+ end
105
+
35
106
  Rake::TestTask.new(:test) do |t|
36
107
  t.test_files = FileList[
37
- 'tests/*test.rb', # EC2 frontend internal API tests
108
+ 'tests/*/*_test.rb'
38
109
  ]
39
110
  end
111
+
112
+ desc "Execute test against live Deltacloud API"
113
+ task :test_live do
114
+ ENV['NO_VCR'] = 'true'
115
+ Rake::Task[:test].invoke
116
+ end
117
+
118
+ desc "Generate test coverage report"
119
+ task :coverage do
120
+ ENV['COVERAGE'] = 'true'
121
+ Rake::Task[:test].invoke
122
+ end
@@ -0,0 +1,79 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ module Deltacloud
17
+ module Client
18
+ require 'require_relative' if RUBY_VERSION < '1.9'
19
+ require 'ostruct'
20
+ require 'nokogiri'
21
+ require 'faraday'
22
+ require 'base64'
23
+
24
+ # Core extensions
25
+ require_relative './core_ext'
26
+
27
+ # Errors && Helpers
28
+ require_relative './client/helpers/model_helper'
29
+ require_relative './client/helpers/xml_helper'
30
+ require_relative './client/helpers/property_helper'
31
+
32
+ # Exceptions goes here
33
+ require_relative './client/base_error'
34
+
35
+ # Faraday Middleware for Deltacloud errors
36
+ require_relative './error_response'
37
+
38
+ # Deltacloud API methods
39
+ require_relative './client/methods/api'
40
+ require_relative './client/methods/backward_compatiblity'
41
+
42
+ # Extend Client module with methods that existed in old client
43
+ # that need to be kept.
44
+ # Deprecation warnings should be provided to users if they use something
45
+ # from these modules.
46
+ #
47
+ extend Deltacloud::Client::Methods::BackwardCompatibility::ClassMethods
48
+
49
+ # Deltacloud methods
50
+ require_relative './client/methods'
51
+
52
+ # Deltacloud models
53
+ require_relative './client/models'
54
+
55
+ require_relative './client/connection'
56
+
57
+ VERSION = '1.1.2'
58
+
59
+ # Check if the connection to Deltacloud API is valid
60
+ def self.valid_connection?(api_url)
61
+ begin
62
+ Deltacloud::Client(api_url, '', '') && true
63
+ rescue Faraday::Error::ConnectionFailed
64
+ false
65
+ rescue Deltacloud::Client::AuthenticationError
66
+ false
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ def self.Client(url, api_user, api_password, opts={})
73
+ Client::Connection.new({
74
+ :url => url,
75
+ :api_user => api_user,
76
+ :api_password => api_password
77
+ }.merge(opts))
78
+ end
79
+ end
@@ -0,0 +1,80 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ module Deltacloud::Client
17
+
18
+ # Reporting internal client errors
19
+ #
20
+ class Error < StandardError; end
21
+
22
+ class BaseError < Error
23
+ attr_reader :server_backtrace
24
+ attr_reader :driver
25
+ attr_reader :provider
26
+ attr_reader :status
27
+ attr_reader :original_error
28
+
29
+ def initialize(opts={})
30
+ if opts.is_a? Hash
31
+ @server_backtrace = opts[:server_backtrace]
32
+ @driver = opts[:driver]
33
+ @provider = opts[:provider]
34
+ @status = opts[:status]
35
+ @original_error = opts[:original_error]
36
+ super(opts[:message])
37
+ else
38
+ super(opts)
39
+ end
40
+ end
41
+
42
+ # If the Deltacloud API server error response contain backtrace from
43
+ # server,then make this backtrace available as part of this exception
44
+ # backtrace
45
+ #
46
+ def set_backtrace(backtrace)
47
+ return super(backtrace) if @server_backtrace.nil?
48
+ super([
49
+ backtrace[0..3],
50
+ "-------Deltacloud API backtrace-------",
51
+ @server_backtrace.split[0..10],
52
+ ].flatten)
53
+ end
54
+
55
+ end
56
+
57
+ # Report 401 errors
58
+ class AuthenticationError < BaseError; end
59
+
60
+ # Report 502 errors (back-end cloud provider encounter error)
61
+ class BackendError < BaseError; end
62
+
63
+ # Report 5xx errors (error on Deltacloud API server)
64
+ class ServerError < BaseError; end
65
+
66
+ # Report 501 errors (collection or operation is not supported)
67
+ class NotSupported < ServerError; end
68
+
69
+ # Report 4xx failures (client failures)
70
+ class ClientFailure < BaseError; end
71
+
72
+ # Report 404 error (object not found)
73
+ class NotFound < BaseError; end
74
+
75
+ # Report 405 failures (resource state does not permit the requested operation)
76
+ class InvalidState < ClientFailure; end
77
+
78
+ # Report this when client do Image#launch using incompatible HWP
79
+ class IncompatibleHardwareProfile < ClientFailure; end
80
+ end
@@ -0,0 +1,139 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ module Deltacloud::Client
17
+ class Connection
18
+
19
+ attr_accessor :connection
20
+ attr_reader :request_driver
21
+ attr_reader :request_provider
22
+ attr_reader :entrypoint
23
+
24
+ include Deltacloud::Client::Helpers::Model
25
+
26
+ include Deltacloud::Client::Methods::Address
27
+ include Deltacloud::Client::Methods::Api
28
+ include Deltacloud::Client::Methods::BackwardCompatibility
29
+ include Deltacloud::Client::Methods::Blob
30
+ include Deltacloud::Client::Methods::Bucket
31
+ include Deltacloud::Client::Methods::Common
32
+ include Deltacloud::Client::Methods::Driver
33
+ include Deltacloud::Client::Methods::Firewall
34
+ include Deltacloud::Client::Methods::HardwareProfile
35
+ include Deltacloud::Client::Methods::Image
36
+ include Deltacloud::Client::Methods::Instance
37
+ include Deltacloud::Client::Methods::InstanceState
38
+ include Deltacloud::Client::Methods::Key
39
+ include Deltacloud::Client::Methods::Realm
40
+ include Deltacloud::Client::Methods::StorageSnapshot
41
+ include Deltacloud::Client::Methods::StorageVolume
42
+ include Deltacloud::Client::Methods::LoadBalancer
43
+ include Deltacloud::Client::Methods::Metric
44
+
45
+ def initialize(opts={})
46
+ @request_driver = opts[:driver]
47
+ @request_provider = opts[:provider]
48
+ @connection = Faraday.new(:url => opts[:url]) do |f|
49
+ # NOTE: The order of this is somehow important for VCR
50
+ # recording.
51
+ f.request :url_encoded
52
+ f.headers = deltacloud_request_headers
53
+ f.basic_auth opts[:api_user], opts[:api_password]
54
+ f.use Deltacloud::ErrorResponse
55
+ f.adapter :net_http
56
+ end
57
+ cache_entrypoint!
58
+ @request_driver ||= current_driver
59
+ @request_provider ||= current_provider
60
+ end
61
+
62
+ # Change the current driver and return copy of the client
63
+ # This allows chained calls like: client.driver(:ec2).instances
64
+ #
65
+ # - driver_id -> The new driver id (:mock, :ec2, :rhevm, ...)
66
+ # - api_user -> API user name
67
+ # - api_password -> API password
68
+ # - api_provider -> API provider (aka API_PROVIDER string)
69
+ #
70
+ def use(driver_id, api_user, api_password, api_provider=nil, &block)
71
+ new_client = self.class.new(
72
+ :url => @connection.url_prefix.to_s,
73
+ :api_user => api_user,
74
+ :api_password => api_password,
75
+ :provider => api_provider,
76
+ :driver => driver_id
77
+ )
78
+ new_client.cache_entrypoint!
79
+ yield new_client if block_given?
80
+ new_client
81
+ end
82
+
83
+ # Change the API provider but keep the current client credentials.
84
+ # This allows to change the EC2 region and list instances in that
85
+ # region without need to supply credentials.
86
+ #
87
+ # client.use_provider('eu-west-1') { |p| p.instances }
88
+ #
89
+ # - provider_id -> API provider (aka API_PROVIDER)
90
+ #
91
+ def use_provider(provider_id, &block)
92
+ new_client = self.clone
93
+ new_connection = @connection.clone
94
+ new_connection.headers['X-Deltacloud-Provider'] = provider_id
95
+ new_client.connection = new_connection
96
+ new_client.cache_entrypoint!(true)
97
+ yield new_client if block_given?
98
+ new_client
99
+ end
100
+
101
+ # Cache the API entrypoint (/api) for the current connection,
102
+ # so we don't need to query /api everytime we ask if certain
103
+ # collection/operation is supported
104
+ #
105
+ # - force -> If 'true' force to refresh stored cached entrypoint
106
+ #
107
+ def cache_entrypoint!(force=false)
108
+ @entrypoint = nil if force
109
+ @entrypoint ||= connection.get(path).body
110
+ end
111
+
112
+ # Check if the credentials used are valid for the current @connection
113
+ #
114
+ def valid_credentials?
115
+ begin
116
+ r = connection.get(path, { :force_auth => 'true' })
117
+ r.status == 200
118
+ rescue error(:authentication_error)
119
+ false
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ # Default Deltacloud HTTP headers. Common for *all* requests
126
+ # to Deltacloud API
127
+ #
128
+ def deltacloud_request_headers
129
+ headers = {}
130
+ headers['Accept'] = 'application/xml'
131
+ headers['X-Deltacloud-Driver'] = @request_driver.to_s \
132
+ if @request_driver
133
+ headers['X-Deltacloud-Provider'] = @request_provider.to_s \
134
+ if @request_provider
135
+ headers
136
+ end
137
+
138
+ end
139
+ end