fog-scaleway 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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