fog-scaleway 0.1.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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +58 -0
  8. data/Rakefile +21 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/fog-scaleway.gemspec +31 -0
  12. data/lib/fog/scaleway.rb +15 -0
  13. data/lib/fog/scaleway/account.rb +306 -0
  14. data/lib/fog/scaleway/client.rb +54 -0
  15. data/lib/fog/scaleway/compute.rb +350 -0
  16. data/lib/fog/scaleway/errors.rb +37 -0
  17. data/lib/fog/scaleway/models/account/organization.rb +42 -0
  18. data/lib/fog/scaleway/models/account/organizations.rb +22 -0
  19. data/lib/fog/scaleway/models/account/token.rb +60 -0
  20. data/lib/fog/scaleway/models/account/tokens.rb +22 -0
  21. data/lib/fog/scaleway/models/account/user.rb +69 -0
  22. data/lib/fog/scaleway/models/account/users.rb +23 -0
  23. data/lib/fog/scaleway/models/compute/bootscript.rb +19 -0
  24. data/lib/fog/scaleway/models/compute/bootscripts.rb +22 -0
  25. data/lib/fog/scaleway/models/compute/image.rb +83 -0
  26. data/lib/fog/scaleway/models/compute/images.rb +22 -0
  27. data/lib/fog/scaleway/models/compute/ip.rb +70 -0
  28. data/lib/fog/scaleway/models/compute/ips.rb +22 -0
  29. data/lib/fog/scaleway/models/compute/security_group.rb +77 -0
  30. data/lib/fog/scaleway/models/compute/security_group_rule.rb +59 -0
  31. data/lib/fog/scaleway/models/compute/security_group_rules.rb +34 -0
  32. data/lib/fog/scaleway/models/compute/security_groups.rb +22 -0
  33. data/lib/fog/scaleway/models/compute/server.rb +243 -0
  34. data/lib/fog/scaleway/models/compute/servers.rb +47 -0
  35. data/lib/fog/scaleway/models/compute/snapshot.rb +90 -0
  36. data/lib/fog/scaleway/models/compute/snapshots.rb +22 -0
  37. data/lib/fog/scaleway/models/compute/task.rb +31 -0
  38. data/lib/fog/scaleway/models/compute/tasks.rb +22 -0
  39. data/lib/fog/scaleway/models/compute/volume.rb +96 -0
  40. data/lib/fog/scaleway/models/compute/volumes.rb +22 -0
  41. data/lib/fog/scaleway/request_helper.rb +32 -0
  42. data/lib/fog/scaleway/requests/account/create_token.rb +62 -0
  43. data/lib/fog/scaleway/requests/account/delete_token.rb +21 -0
  44. data/lib/fog/scaleway/requests/account/get_organization.rb +19 -0
  45. data/lib/fog/scaleway/requests/account/get_organization_quotas.rb +21 -0
  46. data/lib/fog/scaleway/requests/account/get_token.rb +19 -0
  47. data/lib/fog/scaleway/requests/account/get_token_permissions.rb +21 -0
  48. data/lib/fog/scaleway/requests/account/get_user.rb +19 -0
  49. data/lib/fog/scaleway/requests/account/list_organizations.rb +19 -0
  50. data/lib/fog/scaleway/requests/account/list_tokens.rb +19 -0
  51. data/lib/fog/scaleway/requests/account/update_token.rb +27 -0
  52. data/lib/fog/scaleway/requests/account/update_user.rb +39 -0
  53. data/lib/fog/scaleway/requests/compute/create_image.rb +61 -0
  54. data/lib/fog/scaleway/requests/compute/create_ip.rb +68 -0
  55. data/lib/fog/scaleway/requests/compute/create_security_group.rb +49 -0
  56. data/lib/fog/scaleway/requests/compute/create_security_group_rule.rb +49 -0
  57. data/lib/fog/scaleway/requests/compute/create_server.rb +129 -0
  58. data/lib/fog/scaleway/requests/compute/create_snapshot.rb +54 -0
  59. data/lib/fog/scaleway/requests/compute/create_volume.rb +88 -0
  60. data/lib/fog/scaleway/requests/compute/delete_image.rb +27 -0
  61. data/lib/fog/scaleway/requests/compute/delete_ip.rb +29 -0
  62. data/lib/fog/scaleway/requests/compute/delete_security_group.rb +31 -0
  63. data/lib/fog/scaleway/requests/compute/delete_security_group_rule.rb +23 -0
  64. data/lib/fog/scaleway/requests/compute/delete_server.rb +40 -0
  65. data/lib/fog/scaleway/requests/compute/delete_snapshot.rb +29 -0
  66. data/lib/fog/scaleway/requests/compute/delete_task.rb +21 -0
  67. data/lib/fog/scaleway/requests/compute/delete_user_data.rb +21 -0
  68. data/lib/fog/scaleway/requests/compute/delete_volume.rb +31 -0
  69. data/lib/fog/scaleway/requests/compute/execute_server_action.rb +101 -0
  70. data/lib/fog/scaleway/requests/compute/get_bootscript.rb +19 -0
  71. data/lib/fog/scaleway/requests/compute/get_container.rb +19 -0
  72. data/lib/fog/scaleway/requests/compute/get_dashboard.rb +37 -0
  73. data/lib/fog/scaleway/requests/compute/get_image.rb +19 -0
  74. data/lib/fog/scaleway/requests/compute/get_ip.rb +19 -0
  75. data/lib/fog/scaleway/requests/compute/get_security_group.rb +19 -0
  76. data/lib/fog/scaleway/requests/compute/get_security_group_rule.rb +23 -0
  77. data/lib/fog/scaleway/requests/compute/get_server.rb +48 -0
  78. data/lib/fog/scaleway/requests/compute/get_snapshot.rb +19 -0
  79. data/lib/fog/scaleway/requests/compute/get_task.rb +25 -0
  80. data/lib/fog/scaleway/requests/compute/get_user_data.rb +25 -0
  81. data/lib/fog/scaleway/requests/compute/get_volume.rb +19 -0
  82. data/lib/fog/scaleway/requests/compute/list_bootscripts.rb +23 -0
  83. data/lib/fog/scaleway/requests/compute/list_containers.rb +19 -0
  84. data/lib/fog/scaleway/requests/compute/list_images.rb +27 -0
  85. data/lib/fog/scaleway/requests/compute/list_ips.rb +19 -0
  86. data/lib/fog/scaleway/requests/compute/list_security_group_rules.rb +21 -0
  87. data/lib/fog/scaleway/requests/compute/list_security_groups.rb +19 -0
  88. data/lib/fog/scaleway/requests/compute/list_server_actions.rb +21 -0
  89. data/lib/fog/scaleway/requests/compute/list_servers.rb +19 -0
  90. data/lib/fog/scaleway/requests/compute/list_snapshots.rb +19 -0
  91. data/lib/fog/scaleway/requests/compute/list_tasks.rb +19 -0
  92. data/lib/fog/scaleway/requests/compute/list_user_data.rb +21 -0
  93. data/lib/fog/scaleway/requests/compute/list_volumes.rb +19 -0
  94. data/lib/fog/scaleway/requests/compute/update_image.rb +31 -0
  95. data/lib/fog/scaleway/requests/compute/update_ip.rb +47 -0
  96. data/lib/fog/scaleway/requests/compute/update_security_group.rb +29 -0
  97. data/lib/fog/scaleway/requests/compute/update_security_group_rule.rb +31 -0
  98. data/lib/fog/scaleway/requests/compute/update_server.rb +71 -0
  99. data/lib/fog/scaleway/requests/compute/update_snapshot.rb +24 -0
  100. data/lib/fog/scaleway/requests/compute/update_user_data.rb +25 -0
  101. data/lib/fog/scaleway/requests/compute/update_volume.rb +24 -0
  102. data/lib/fog/scaleway/version.rb +5 -0
  103. metadata +285 -0
@@ -0,0 +1,54 @@
1
+ module Fog
2
+ module Scaleway
3
+ class Client
4
+ def initialize(endpoint, token)
5
+ @endpoint = endpoint
6
+ @token = token
7
+ end
8
+
9
+ def request(params)
10
+ params[:headers] ||= {}
11
+ params[:headers]['Content-Type'] ||= 'application/json'
12
+ params[:headers]['X-Auth-Token'] ||= @token
13
+
14
+ params[:body] = encode_body(params)
15
+
16
+ response = connection.request(params)
17
+
18
+ response.body = decode_body(response)
19
+
20
+ response
21
+ end
22
+
23
+ private
24
+
25
+ def connection
26
+ @connection ||= Fog::Core::Connection.new(@endpoint)
27
+ end
28
+
29
+ def encode_body(params)
30
+ body = params[:body]
31
+ content_type = params[:headers]['Content-Type']
32
+
33
+ if body.nil? || body.is_a?(String)
34
+ body
35
+ elsif content_type =~ %r{application/json.*}i
36
+ Fog::JSON.encode(body)
37
+ else
38
+ body.to_s
39
+ end
40
+ end
41
+
42
+ def decode_body(response)
43
+ body = response.body
44
+ content_type = response.headers['Content-Type']
45
+
46
+ if !body.nil? && !body.empty? && content_type =~ %r{application/json.*}i
47
+ Fog::JSON.decode(body)
48
+ else
49
+ body
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,350 @@
1
+ require 'fog/scaleway/client'
2
+ require 'fog/scaleway/errors'
3
+ require 'fog/scaleway/request_helper'
4
+
5
+ module Fog
6
+ module Scaleway
7
+ class Compute < Fog::Service
8
+ class InvalidRequestError < Error; end
9
+ class InvalidAuth < Error; end
10
+ class AuthorizationRequired < Error; end
11
+ class UnknownResource < Error; end
12
+ class Conflict < Error; end
13
+ class APIError < Error; end
14
+
15
+ requires :scaleway_token
16
+ requires :scaleway_organization
17
+ secrets :scaleway_token
18
+
19
+ model_path 'fog/scaleway/models/compute'
20
+
21
+ model :server
22
+ collection :servers
23
+ model :volume
24
+ collection :volumes
25
+ model :snapshot
26
+ collection :snapshots
27
+ model :image
28
+ collection :images
29
+ model :ip
30
+ collection :ips
31
+ model :security_group
32
+ collection :security_groups
33
+ model :security_group_rule
34
+ collection :security_group_rules
35
+ model :bootscript
36
+ collection :bootscripts
37
+ model :task
38
+ collection :tasks
39
+
40
+ request_path 'fog/scaleway/requests/compute'
41
+
42
+ # Servers
43
+ request :create_server
44
+ request :list_servers
45
+ request :get_server
46
+ request :update_server
47
+ request :delete_server
48
+ request :list_server_actions
49
+ request :execute_server_action
50
+ request :list_user_data
51
+ request :get_user_data
52
+ request :update_user_data
53
+ request :delete_user_data
54
+
55
+ # Volumes
56
+ request :create_volume
57
+ request :list_volumes
58
+ request :get_volume
59
+ request :update_volume
60
+ request :delete_volume
61
+
62
+ # Snapshots
63
+ request :create_snapshot
64
+ request :list_snapshots
65
+ request :get_snapshot
66
+ request :update_snapshot
67
+ request :delete_snapshot
68
+
69
+ # Images
70
+ request :create_image
71
+ request :list_images
72
+ request :get_image
73
+ request :update_image
74
+ request :delete_image
75
+
76
+ # IPs
77
+ request :create_ip
78
+ request :list_ips
79
+ request :get_ip
80
+ request :update_ip
81
+ request :delete_ip
82
+
83
+ # Security Groups
84
+ request :create_security_group
85
+ request :list_security_groups
86
+ request :get_security_group
87
+ request :update_security_group
88
+ request :delete_security_group
89
+ request :create_security_group_rule
90
+ request :list_security_group_rules
91
+ request :get_security_group_rule
92
+ request :update_security_group_rule
93
+ request :delete_security_group_rule
94
+
95
+ # Bootscripts
96
+ request :list_bootscripts
97
+ request :get_bootscript
98
+
99
+ # Tasks
100
+ request :list_tasks
101
+ request :get_task
102
+ request :delete_task
103
+
104
+ # Containers
105
+ request :list_containers
106
+ request :get_container
107
+
108
+ # Dashboard
109
+ request :get_dashboard
110
+
111
+ class Real
112
+ include Fog::Scaleway::RequestHelper
113
+
114
+ def initialize(options)
115
+ @token = options[:scaleway_token]
116
+ @organization = options[:scaleway_organization]
117
+ end
118
+
119
+ def request(params)
120
+ client.request(params)
121
+ rescue Excon::Errors::HTTPStatusError => error
122
+ decoded = Fog::Scaleway::Errors.decode_error(error)
123
+ raise if decoded.nil?
124
+
125
+ type = decoded[:type]
126
+ message = decoded[:message]
127
+
128
+ raise case type
129
+ when 'invalid_request_error', 'invalid_auth', 'authorization_required', 'unknown_resource', 'conflict'
130
+ Fog::Scaleway::Compute.const_get(camelize(type)).slurp(error, message)
131
+ when 'api_error'
132
+ Fog::Scaleway::Compute::APIError.slurp(error, message)
133
+ else
134
+ Fog::Scaleway::Compute::Error.slurp(error, message)
135
+ end
136
+ end
137
+
138
+ private
139
+
140
+ def client
141
+ @client ||= Fog::Scaleway::Client.new('https://api.scaleway.com', @token)
142
+ end
143
+
144
+ def camelize(str)
145
+ str.split('_').collect(&:capitalize).join
146
+ end
147
+ end
148
+
149
+ class Mock
150
+ INITIAL_IMAGES = [{
151
+ 'default_bootscript' => {
152
+ 'kernel' => 'http://169.254.42.24/kernel/x86_64-4.5.7-std-3/vmlinuz-4.5.7-std-3',
153
+ 'initrd' => 'http://169.254.42.24/initrd/initrd-Linux-x86_64-v3.11.1.gz',
154
+ 'default' => true,
155
+ 'bootcmdargs' => 'LINUX_COMMON ip=:::::eth0: boot=local',
156
+ 'architecture' => 'x86_64',
157
+ 'title' => 'x86_64 4.5.7 std #3 (latest/stable)',
158
+ 'dtb' => '',
159
+ 'organization' => '11111111-1111-4111-8111-111111111111',
160
+ 'id' => '3b522e7a-8468-4577-ab3e-2b9535384bb8',
161
+ 'public' => true
162
+ },
163
+ 'creation_date' => '2016-05-20T09:35:48.735687+00:00',
164
+ 'name' => 'Ubuntu Xenial (16.04 latest)',
165
+ 'modification_date' => '2016-07-12T15:19:54.680577+00:00',
166
+ 'organization' => 'abaeb1aa-760b-4391-aeab-c0622be90abf',
167
+ 'extra_volumes' => '[]',
168
+ 'arch' => 'x86_64',
169
+ 'id' => '75c28f52-6c64-40fc-bb31-f53ca9d02de9',
170
+ 'root_volume' => {
171
+ 'size' => 50_000_000_000,
172
+ 'id' => '714abe6f-5721-4222-ae69-15b4a6488f22',
173
+ 'volume_type' => 'l_ssd',
174
+ 'name' => 'x86_64-ubuntu-xenial-2016-05-20_09:25'
175
+ },
176
+ 'public' => true
177
+ }, {
178
+ 'default_bootscript' => {
179
+ 'kernel' => 'kernel/armv7l-4.5.7-std-4',
180
+ 'initrd' => 'initrd/uInitrd-Linux-armv7l-v3.11.1',
181
+ 'default' => true,
182
+ 'bootcmdargs' => 'LINUX_COMMON ip=:::::eth0: boot=local',
183
+ 'architecture' => 'arm',
184
+ 'title' => 'armv7l 4.5.7 std #4 (latest)',
185
+ 'dtb' => 'dtb/c1-armv7l-4.5.7-std-4',
186
+ 'organization' => '11111111-1111-4111-8111-111111111111',
187
+ 'id' => '599b736c-48b5-4530-9764-f04d06ecadc7',
188
+ 'public' => true
189
+ },
190
+ 'creation_date' => '2016-05-20T09:00:08.222054+00:00',
191
+ 'name' => 'Ubuntu Xenial (16.04 latest)',
192
+ 'modification_date' => '2016-07-12T15:21:13.269384+00:00',
193
+ 'organization' => 'abaeb1aa-760b-4391-aeab-c0622be90abf',
194
+ 'extra_volumes' => '[]',
195
+ 'arch' => 'arm',
196
+ 'id' => 'eeb73cbf-78a9-4481-9e38-9aaadaf8e0c9',
197
+ 'root_volume' => {
198
+ 'size' => 50_000_000_000,
199
+ 'id' => 'ea3aaf5a-c91b-463d-9093-00fae8632cfd',
200
+ 'volume_type' => 'l_ssd',
201
+ 'name' => 'armv7l-ubuntu-xenial-2016-05-20_08:51'
202
+ },
203
+ 'public' => true
204
+ }].freeze
205
+
206
+ def self.data
207
+ @data ||= Hash.new do |hash, token|
208
+ hash[token] = {
209
+ servers: {},
210
+ user_data: Hash.new({}),
211
+ volumes: {},
212
+ snapshots: {},
213
+ images: Hash[INITIAL_IMAGES.map { |i| [i['id'], i] }],
214
+ ips: {},
215
+ security_groups: {},
216
+ security_group_rules: Hash.new({}),
217
+ bootscripts: Hash[INITIAL_IMAGES.map do |i|
218
+ [i['default_bootscript']['id'], i['default_bootscript']]
219
+ end],
220
+ tasks: {},
221
+ containers: {},
222
+ server_actions: Hash.new(%w(poweron poweroff reboot terminate))
223
+ }
224
+ end
225
+ end
226
+
227
+ def initialize(options)
228
+ @token = options[:scaleway_token]
229
+ end
230
+
231
+ def self.reset
232
+ @data = nil
233
+ end
234
+
235
+ private
236
+
237
+ def data
238
+ self.class.data[@token]
239
+ end
240
+
241
+ def lookup(type, id)
242
+ data[type][id] || raise_unknown_resource(id)
243
+ end
244
+
245
+ def default_security_group
246
+ data[:security_groups].values.find { |s| s['organization_default'] }
247
+ end
248
+
249
+ def create_default_security_group
250
+ name = 'Default security group'
251
+ options = {
252
+ description: 'Auto generated security group.',
253
+ organization_default: true
254
+ }
255
+
256
+ create_security_group(name, options).body['security_group']
257
+ end
258
+
259
+ def create_dynamic_ip
260
+ {
261
+ 'dynamic' => true,
262
+ 'id' => Fog::UUID.uuid,
263
+ 'address' => Fog::Mock.random_ip
264
+ }
265
+ end
266
+
267
+ def create_ipv6
268
+ {
269
+ 'netmask' => '127',
270
+ 'gateway' => random_ipv6.mask(127).to_s,
271
+ 'address' => random_ipv6.mask(127).succ.to_s
272
+ }
273
+ end
274
+
275
+ def terminate_server(server)
276
+ data[:servers].delete(server['id'])
277
+
278
+ security_group = lookup(:security_groups, server['security_group']['id'])
279
+ security_group['servers'].reject! { |s| s['id'] == server['id'] }
280
+
281
+ server['volumes'].values.each do |volume|
282
+ volume['server'] = nil
283
+ delete_volume(volume['id'])
284
+ end
285
+ end
286
+
287
+ def response(params)
288
+ params[:headers] ||= {}
289
+ params[:headers]['Content-Type'] ||= 'application/json'
290
+
291
+ params[:body] = encode_body(params)
292
+
293
+ response = Excon::Response.new(params)
294
+
295
+ response.body = decode_body(response)
296
+
297
+ response
298
+ end
299
+
300
+ def encode_body(params)
301
+ body = params[:body]
302
+ content_type = params[:headers]['Content-Type']
303
+
304
+ if body.nil? || body.is_a?(String)
305
+ body
306
+ elsif content_type =~ %r{application/json.*}i
307
+ Fog::JSON.encode(body)
308
+ else
309
+ body.to_s
310
+ end
311
+ end
312
+
313
+ def decode_body(response)
314
+ body = response.body
315
+ content_type = response.headers['Content-Type']
316
+
317
+ if !body.nil? && !body.empty? && content_type =~ %r{application/json.*}i
318
+ Fog::JSON.decode(body)
319
+ else
320
+ body
321
+ end
322
+ end
323
+
324
+ def raise_invalid_request_error(message)
325
+ raise Fog::Scaleway::Compute::InvalidRequestError, message
326
+ end
327
+
328
+ def raise_unknown_resource(id)
329
+ raise Fog::Scaleway::Compute::UnknownResource, "\"#{id}\" not found"
330
+ end
331
+
332
+ def raise_conflict(message)
333
+ raise Fog::Scaleway::Compute::Conflict, message
334
+ end
335
+
336
+ def now
337
+ Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S.%6N%:z')
338
+ end
339
+
340
+ def jsonify(value)
341
+ Fog::JSON.decode(Fog::JSON.encode(value))
342
+ end
343
+
344
+ def random_ipv6
345
+ IPAddr.new(1 + rand((2**128) - 1), Socket::AF_INET6)
346
+ end
347
+ end
348
+ end
349
+ end
350
+ end
@@ -0,0 +1,37 @@
1
+ module Fog
2
+ module Scaleway
3
+ module Errors
4
+ def self.decode_error(error)
5
+ body = begin
6
+ Fog::JSON.decode(error.response.body)
7
+ rescue Fog::JSON::DecodeError
8
+ nil
9
+ end
10
+
11
+ return if body.nil?
12
+
13
+ type = body['type']
14
+ message = body['message']
15
+ fields = body['fields']
16
+
17
+ return if type.nil? || message.nil?
18
+
19
+ unless fields.nil?
20
+ message << "\n"
21
+ message << format_fields(fields)
22
+ end
23
+
24
+ { type: type, message: message }
25
+ end
26
+
27
+ def self.format_fields(fields)
28
+ fields.map { |field, msgs| format_field(field, msgs) }.join("\n")
29
+ end
30
+
31
+ def self.format_field(field, msgs)
32
+ msgs = msgs.map { |msg| "\t\t- #{msg}" }
33
+ "\t#{field}:\n#{msgs.join("\n")}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,42 @@
1
+ module Fog
2
+ module Scaleway
3
+ class Account
4
+ class Organization < Fog::Model
5
+ identity :id
6
+
7
+ attribute :address_city_name
8
+ attribute :address_country_code
9
+ attribute :address_line1
10
+ attribute :address_line2
11
+ attribute :address_postal_code
12
+ attribute :address_subdivision_code
13
+ attribute :creation_date
14
+ attribute :currency
15
+ attribute :customer_class
16
+ attribute :locale
17
+ attribute :modification_date
18
+ attribute :name
19
+ attribute :support_id
20
+ attribute :support_level
21
+ attribute :support_pin
22
+ attribute :timezone
23
+ attribute :users
24
+ attribute :vat_number
25
+ attribute :warnings
26
+
27
+ def users=(value)
28
+ attributes[:users] = value.map do |v|
29
+ case v
30
+ when Hash
31
+ service.users.new(v)
32
+ when String
33
+ service.users.new(identity: v)
34
+ else
35
+ v
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end