em-digitalocean 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 83254f7d7f018f7c6a0fa01acc4c343ac2e265b7
4
+ data.tar.gz: 9b408c53d2fe2ccb6ad78f4b70dc8430065bda85
5
+ SHA512:
6
+ metadata.gz: 598fb05608b7074769acbec16d2805edecc05ca3e7350cc8a3fc2be0e6d700cec9a00aef8cbfe28e781ee13f06a797d3482c40f65e00fabb9bbaf6705567c75d
7
+ data.tar.gz: 28c0557667215611d63725e2cc4306536f1da6113f9882c3683f57197b39b247ba8ba250689cd97bfdc4bafaf2e0207f4d4a044a6108852b259a911b13034d69
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ /TOKEN
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in em-digitalocean.gemspec
4
+ gemspec
@@ -0,0 +1,73 @@
1
+ # Digitalocean API
2
+
3
+
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'em-digitalocean'
11
+ ```
12
+
13
+ Then `require 'digitalocean'`
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install em-digitalocean
22
+
23
+ ## Usage
24
+
25
+ https://cloud.digitalocean.com/settings/applications
26
+
27
+ ```ruby
28
+ api = Digitalocean::API.new(token: 'TOKEN')
29
+ ```
30
+
31
+ ## API
32
+
33
+ ```ruby
34
+ api = Digitalocean::API.new(token: 'TOKEN')
35
+ droplets = api.droplets.all.sync
36
+ # {:droplets=>[{:id=>0, :name=>"droplet", :memory=>512, :vcpus=>1, :disk=>20, :locked=>false ...}]}
37
+ droplet = api.droplets.show(droplets[:droplets].first[:id]).sync
38
+ # {:droplet=>{:id=>0, :name=>"droplet", :memory=>512, :vcpus=>1, :disk=>20, :locked=>false, :status=>"active", ...}}
39
+ ```
40
+
41
+ ## Droplet Actions
42
+
43
+ * `api.droplets.disable_backups(id).sync`
44
+ * `api.droplets.reboot(id).sync`
45
+ * `api.droplets.power_cycle(id).sync`
46
+ * `api.droplets.shutdown(id).sync`
47
+ * `api.droplets.power_off(id).sync`
48
+ * `api.droplets.power_on(id).sync`
49
+ * `api.droplets.restore(id, image).sync`
50
+ * `api.droplets.password_reset(id).sync`
51
+ * `api.droplets.resize(id, disk, size).sync`
52
+ * `api.droplets.rebuild(id, image).sync`
53
+ * `api.droplets.rename(id, name).sync`
54
+ * `api.droplets.change_kernel(id, kernel).sync`
55
+ * `api.droplets.enable_ipv6(id, kernel).sync`
56
+ * `api.droplets.enable_private_networking(id, kernel).sync`
57
+ * `api.droplets.snapshot(id).sync`
58
+ * `api.droplets.upgrade(id).sync`
59
+ * `api.droplets.retrive_action(id, action).sync`
60
+
61
+ ## Raise
62
+
63
+ config/initializers/digitalocean.rb
64
+ ```ruby
65
+ require 'digitalocean'
66
+ Digitalocean.api = Digitalocean::API.new(token: 'TOKEN')
67
+ ```
68
+
69
+ Request:
70
+
71
+ ```ruby
72
+ actions = Digitalocean.api.actions.sync
73
+ ```
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'digitalocean/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "em-digitalocean"
8
+ spec.version = Digitalocean::VERSION
9
+ spec.authors = ["inre"]
10
+ spec.email = ["inre.storm@gmail.com"]
11
+
12
+ spec.summary = %q{DigitalOcean API EventMachine-based}
13
+ #spec.description = %q{TODO: Write a longer description or delete this line.}
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "emmy-machine"
21
+ spec.add_dependency "emmy-http", '>= 0.2.2'
22
+ spec.add_dependency "emmy-http-client", '>= 0.1.7'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.9"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ end
@@ -0,0 +1,12 @@
1
+ require 'event_object'
2
+ require 'emmy_http'
3
+ require 'emmy_http/client'
4
+ require 'digitalocean/version'
5
+ require 'digitalocean/concerns/class_methods'
6
+ require 'digitalocean/api'
7
+ require 'digitalocean/operation'
8
+ require 'digitalocean/requests'
9
+ require 'digitalocean/errors'
10
+
11
+ module Digitalocean
12
+ end
@@ -0,0 +1,190 @@
1
+ module Digitalocean
2
+ class API
3
+ using EventObject
4
+ extend ClassMethods
5
+
6
+ attr_accessor :token
7
+ attr_accessor :username
8
+ attr_accessor :password
9
+
10
+ def initialize(token: nil, username: nil, password: nil)
11
+ @token = token
12
+ @username = username
13
+ @password = password
14
+ end
15
+
16
+ def operation(request)
17
+ Operation.new(self, request)
18
+ end
19
+
20
+ def op(r)
21
+ operation(r)
22
+ end
23
+
24
+ ns :account do |api|
25
+ bind self, Account
26
+ end
27
+
28
+ ns :account_keys do |api|
29
+ bind self, Account::Keys
30
+ end
31
+
32
+ ns :actions do |api|
33
+ bind self, Actions
34
+ end
35
+
36
+ ns :domains do |api|
37
+ bind self, Domains
38
+ end
39
+
40
+ ns :domain_records do |api|
41
+ bind self, Domains::Records
42
+ end
43
+
44
+ ns :droplets do |api|
45
+ # Droplet Actions
46
+ self.def :execute_action do |id, params|
47
+ api.op.call Droplets.execute_action(params: {id: id}, json: params)
48
+ end
49
+
50
+ # Disable Backups
51
+ self.def :disable_backups do |id|
52
+ execute_action(id, type: 'disable_backups')
53
+ end
54
+
55
+ # Reboot a Droplet
56
+ self.def :reboot do |id|
57
+ execute_action(id, type: 'reboot')
58
+ end
59
+
60
+ # Power Cycle a Droplet
61
+ self.def :power_cycle do |id|
62
+ execute_action(id, type: 'power_cycle')
63
+ end
64
+
65
+ # Shutdown a Droplet
66
+ self.def :shutdown do |id|
67
+ execute_action(id, type: 'shutdown')
68
+ end
69
+
70
+ # Power Off a Droplet
71
+ self.def :power_off do |id|
72
+ execute_action(id, type: 'power_off')
73
+ end
74
+
75
+ # Power Off a Droplet
76
+ self.def :power_on do |id|
77
+ execute_action(id, type: 'power_on')
78
+ end
79
+
80
+ # Restore a Droplet
81
+ self.def :restore do |id, image|
82
+ execute_action(id, type: 'power_on', image: image)
83
+ end
84
+
85
+ # Password reset a Droplet
86
+ self.def :password_reset do |id|
87
+ execute_action(id, type: 'password_reset')
88
+ end
89
+
90
+ # Resize a Droplet
91
+ self.def :resize do |id, disk, size|
92
+ execute_action(id, type: 'resize', disk: disk, size: size)
93
+ end
94
+
95
+ # Rebuild a Droplet
96
+ self.def :rebuild do |id, image|
97
+ execute_action(id, type: 'rebuild', image: image)
98
+ end
99
+
100
+ # Rename a Droplet
101
+ self.def :rename do |id, name|
102
+ execute_action(id, type: 'rename', name: name)
103
+ end
104
+
105
+ # Change the Kernel
106
+ self.def :change_kernel do |id, kernel|
107
+ execute_action(id, type: 'change_kernel', kernel: kernel)
108
+ end
109
+
110
+ # Enable IPv6
111
+ self.def :enable_ipv6 do |id|
112
+ execute_action(id, type: 'enable_ipv6')
113
+ end
114
+
115
+ # Enable Private Networking
116
+ self.def :enable_private_networking do |id|
117
+ execute_action(id, type: 'enable_private_networking')
118
+ end
119
+
120
+ # Snapshot a Droplet
121
+ self.def :snapshot do |id|
122
+ execute_action(id, type: 'snapshot')
123
+ end
124
+
125
+ # Upgrade a Droplet
126
+ self.def :upgrade do |id|
127
+ execute_action(id, type: 'upgrade')
128
+ end
129
+
130
+ # Retrieve a Droplet Action
131
+ self.def :retrive_action do |id, action|
132
+ Droplets.retrieve_action(params: {id: id, action: action})
133
+ end
134
+
135
+ # Other API methods
136
+ bind self, Droplets
137
+ end
138
+
139
+ ns :images do |api|
140
+ bind self, Images
141
+ end
142
+
143
+ ns :regions do |api|
144
+ bind self, Regions
145
+ end
146
+
147
+ ns :sizes do |api|
148
+ bind self, Sizes
149
+ end
150
+
151
+ =begin
152
+ def droplet
153
+ @droplet ||= begin
154
+ droplet = Object.new
155
+ op = method(:operation)
156
+
157
+ # Droplet Actions
158
+ droplet.def :execute_action do |id, params|
159
+ op.call Droplet.execute_action(params: {id: id}, json: params)
160
+ end
161
+
162
+ # Disable Backups
163
+ droplet.def :disable_backups do |id|
164
+ op.call Droplet.execute_action
165
+ end
166
+
167
+ Droplet.api.each do |name, params|
168
+ variables = Addressable::Template.new(params[:path]).variables
169
+
170
+ if variables.empty? && !droplet.respond_to?(name)
171
+ droplet.def name do
172
+ op.call Droplet.send(name)
173
+ end
174
+ end
175
+
176
+ if variables.include?('id')
177
+ droplet.def name do |id|
178
+ op.call Droplet.send(name, params: {id: id})
179
+ end
180
+ end
181
+ end
182
+
183
+ droplet
184
+ end
185
+ end
186
+ =end
187
+
188
+ #<<<
189
+ end
190
+ end
@@ -0,0 +1,53 @@
1
+ module Digitalocean
2
+ module ClassMethods
3
+ using EventObject
4
+ extend self
5
+
6
+ def ns(name, &b)
7
+ self.def name do
8
+ this = self
9
+ Object.new.tap do |ob|
10
+ ob.def :bind do |object, klass|
11
+ ClassMethods.bind this, object, klass
12
+ end
13
+ ob.instance_exec(self, &b)
14
+ end
15
+ end
16
+ end
17
+
18
+ def bind(api, object, klass)
19
+ raise "#{klass} is not API object" unless klass.respond_to?(:api)
20
+
21
+ klass.api.each do |name, params|
22
+ variables = Addressable::Template.new(params[:path]).variables
23
+
24
+ # auto-bind for no variables
25
+ if variables.empty? && !object.respond_to?(name)
26
+ object.def name do
27
+ api.op klass.send(name)
28
+ end
29
+ end
30
+
31
+ # auto-bind for id variable
32
+ if variables.size == 1
33
+ var_name = variables.first
34
+
35
+ object.def name do |value|
36
+ api.op klass.send(name, params: {var_name => value})
37
+ end
38
+ end
39
+
40
+ if variables.size == 2
41
+ var_name1 = variables.first
42
+ var_name2 = variables.last
43
+
44
+ object.def name do |var1, var2|
45
+ api.op klass.send(name, params: { var_name1 => var1, var_name2 => var2 })
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ #<<<
52
+ end
53
+ end
@@ -0,0 +1,42 @@
1
+ module Digitalocean
2
+ # Base Error
3
+ class Error < RuntimeError
4
+ attr_accessor :code
5
+
6
+ def initialize(data=nil)
7
+ @message = case data
8
+ when Hash
9
+ @code = data[:code]
10
+ data[:message]
11
+ else
12
+ data
13
+ end
14
+ end
15
+
16
+ def message
17
+ code ? "(#{code}) #{@message}" : @message
18
+ end
19
+
20
+ def to_s
21
+ message
22
+ end
23
+ end
24
+
25
+ # Internal Server Error
26
+ class ServerError < Error
27
+ end
28
+
29
+ class ClientError < Error
30
+ attr_accessor :id
31
+
32
+ def initialize(response)
33
+ @message = response.json["message"]
34
+ @id = response.json["id"]
35
+ @code = response.status
36
+ rescue StandardError
37
+ @message = "Uncatched Error"
38
+ end
39
+ end
40
+
41
+ #<<<
42
+ end
@@ -0,0 +1,73 @@
1
+ module Digitalocean
2
+ class Operation
3
+ using EventObject
4
+
5
+ attr_accessor :api
6
+ attr_accessor :request # EmmyHttp::Client::Request
7
+ attr_accessor :operation # EmmyHttp::Client::Operation
8
+
9
+ events :success, :error
10
+
11
+ def initialize(api, request)
12
+ @api = api
13
+ @request = request
14
+ auth
15
+ new_operation
16
+ end
17
+
18
+ def connect(*a)
19
+ operation.connect(*a)
20
+ end
21
+
22
+ def sync
23
+ connect
24
+
25
+ Fiber.sync do |f|
26
+ on :success do |response, operation, conn|
27
+ f.resume response.json(symbolize_names: true)
28
+ end
29
+
30
+ on :error do |error, operation, conn|
31
+ f.leave error
32
+ end
33
+ end
34
+ end
35
+
36
+ def to_a
37
+ operation.to_a
38
+ end
39
+
40
+ protected
41
+
42
+ def auth
43
+ if api.token
44
+ request.headers["Authorization"] = "Bearer #{api.token}"
45
+ elsif api.user && api.password
46
+ request.user = api.user
47
+ request.password = api.password
48
+ end
49
+ end
50
+
51
+ def new_operation
52
+ @operation = request.new_operation
53
+ @operation.on :success do |res, op, conn|
54
+ # success
55
+ case res.status
56
+ when 200...300
57
+ success!(res, self, conn)
58
+ when 400...500
59
+ error!(Digitalocean::ClientError.new(res), self, conn)
60
+ else
61
+ error!(Digitalocean::ServerError.new({message: "Internal Server Error", code: res.status}), self, conn)
62
+ end
63
+ end
64
+
65
+ @operation.on :error do |message, op, conn|
66
+ # error
67
+ error!(message, self, conn)
68
+ end
69
+ end
70
+
71
+ #<<<
72
+ end
73
+ end
@@ -0,0 +1,120 @@
1
+ module Digitalocean
2
+ class Base
3
+ include EmmyHttp::Model
4
+ adapter EmmyHttp::Client::Adapter
5
+ url "https://api.digitalocean.com"
6
+ end
7
+
8
+ class Account < Base
9
+ # Get User Information
10
+ get '/v2/account', as: 'info'
11
+ # SSH Keys
12
+ class Keys < Base
13
+ # List all Keys
14
+ get '/v2/account/keys', as: 'all'
15
+ # Create a new Key
16
+ post '/v2/account/keys', as: 'new'
17
+ # Retrieve an existing Key
18
+ get '/v2/account/keys/{/id}', as: 'retrieve'
19
+ # Update a Key
20
+ put '/v2/account/keys/{/id}', as: 'update'
21
+ # Destroy a Key
22
+ delete '/v2/account/keys/{/id}', as: 'destroy'
23
+ end
24
+ end
25
+
26
+ class Actions < Base
27
+ # List all Actions
28
+ get '/v2/actions', as: 'all'
29
+ # Retrieve an existing Action
30
+ get '/v2/actions/{/id}', as: 'retrieve'
31
+ end
32
+
33
+ class Domains < Base
34
+ # List all Domains
35
+ get '/v2/domains', as: 'all'
36
+ # Create a new Domain
37
+ post '/v2/domains', as: 'new'
38
+ # Retrieve an existing Domain
39
+ get '/v2/domains/{/name}', as: 'retrieve'
40
+ # Delete a Domain
41
+ delete '/v2/domains/{/name}', as: 'delete'
42
+
43
+ class Records < Base
44
+ # List all Domain Records
45
+ get '/v2/domains/{/name}/records', as: 'all'
46
+ # Create a new Domain Record
47
+ post '/v2/domains/{/name}/records', as: 'new'
48
+ # Retrieve an existing Domain Record
49
+ get '/v2/domains/{/name}/records/{/record}', as: 'retrieve'
50
+ # Update a Domain Record
51
+ put '/v2/domains/{/name}/records/{/record}', as: 'update'
52
+ # Delete a Domain Record
53
+ delete '/v2/domains/{/name}/records/{/record}', as: 'delete'
54
+ end
55
+ end
56
+
57
+ class Droplets < Base
58
+ # Create a new Droplet
59
+ post '/v2/droplets', as: 'new'
60
+ # Retrieve an existing Droplet by id
61
+ get '/v2/droplets/{/id}', as: 'show'
62
+ # List all Droplets
63
+ get '/v2/droplets', as: 'all'
64
+ # List all available Kernels for a Droplet
65
+ get '/v2/droplets/{/id}/kernels', as: 'kernels'
66
+ # List snapshots for a Droplet
67
+ get '/v2/droplets/{/id}/snapshots', as: 'snapshots'
68
+ # List backups for a Droplet
69
+ get '/v2/droplets/{/id}/backups', as: 'backups'
70
+ # List actions for a Droplet
71
+ get '/v2/droplets/{/id}/actions', as: 'actions'
72
+ # Delete a Droplet
73
+ delete '/v2/droplets/{/id}', as: 'delete'
74
+ # List Neighbors for a Droplet
75
+ get '/v2/droplets/{/id}/neighbors', as: 'neighbors'
76
+ # List all Droplet Neighbors
77
+ get '/v2/reports/droplet_neighbors', as: 'droplet_neightbors'
78
+ # List Droplet Upgrades
79
+ get '/v2/droplet_upgrades', as: 'droplet_upgrades'
80
+ # Execute an Action
81
+ post '/v2/droplets/{/id}/actions', as: 'execute_action'
82
+ # Retrive a Droplet Action
83
+ post '/v2/droplets/{/id}/actions/{/action}', as: 'retrieve_action'
84
+ end
85
+
86
+ class Images < Base
87
+ # List all images
88
+ get '/v2/images', as: 'all'
89
+ # List all Distribution Images
90
+ get '/v2/images?type=distribution', as: 'distribution_images'
91
+ # List all Application Images
92
+ get '/v2/images?type=application', as: 'application_images'
93
+ # List a User's Images
94
+ get '/v2/images?private=true', as: 'private_images'
95
+ # Retrieve an existing Image by id
96
+ get '/v2/images/{/id}', as: 'retrieve'
97
+ # Retrieve on existing Image by slug
98
+ get '/v2/images/{/slug}', as: 'retrieve_by_slug'
99
+ # List all actions for an image
100
+ get '/v2/images/{/id}/actions', as: 'actions'
101
+ # Update an Image
102
+ put '/v2/images/{/id}', as: 'update'
103
+ # Delete an Image
104
+ delete '/v2/images/{/id}', as: 'delete'
105
+ # Execute an Action
106
+ post '/v2/images/{/id}/actions', as: 'execute_action'
107
+ # Retrieve an existing Image Action
108
+ get '/v2/images/{/id}/actions/{/image}', as: 'retrieve_action'
109
+ end
110
+
111
+ class Regions < Base
112
+ # List all Regions
113
+ get '/v2/regions', as: 'all'
114
+ end
115
+
116
+ class Sizes < Base
117
+ # List all Sizes
118
+ get '/v2/sizes', as: 'all'
119
+ end
120
+ end
@@ -0,0 +1,3 @@
1
+ module Digitalocean
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-digitalocean
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - inre
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: emmy-machine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: emmy-http
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: emmy-http-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.7
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.7
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ description:
84
+ email:
85
+ - inre.storm@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - em-digitalocean.gemspec
97
+ - lib/digitalocean.rb
98
+ - lib/digitalocean/api.rb
99
+ - lib/digitalocean/concerns/class_methods.rb
100
+ - lib/digitalocean/errors.rb
101
+ - lib/digitalocean/operation.rb
102
+ - lib/digitalocean/requests.rb
103
+ - lib/digitalocean/version.rb
104
+ homepage:
105
+ licenses: []
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.4.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: DigitalOcean API EventMachine-based
127
+ test_files: []