digital-ocean-cli 0.5.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1be7eba963a4cdf5c1e832546d05b4a5ba57a480
4
+ data.tar.gz: 1b767d8b4b81f94f81899607cb1aee2f9fed03fc
5
+ SHA512:
6
+ metadata.gz: 93c3739ff4365ecbfdda3d642c604552d3c030a24e0e365166583783c31d9c649e99784122a8b64a3a738d170c9c368a03c63028bfee16f95bff609960c472fb
7
+ data.tar.gz: 13381b73a4290e386a8805383c6dbff1f664da447baf2925e08d21d580d970b1d16d0a95e14f475f66fa6dc2206d1338112595030a3b33c41905310af205a73e
@@ -0,0 +1 @@
1
+ pkg/*
@@ -0,0 +1,42 @@
1
+ Metrics/LineLength:
2
+ Max: 80
3
+
4
+ Style/StringLiterals:
5
+ Enabled: false
6
+
7
+ Style/ClassVars:
8
+ Enabled: false
9
+
10
+ Style/MutableConstant:
11
+ Enabled: false
12
+
13
+ Style/TrailingCommaInLiteral:
14
+ Enabled: false
15
+
16
+ Style/WordArray:
17
+ Enabled: false
18
+
19
+ Style/Documentation:
20
+ Enabled: false
21
+
22
+ Metrics/MethodLength:
23
+ Enabled: false
24
+
25
+ Style/ClassAndModuleChildren:
26
+ Enabled: false
27
+
28
+ Metrics/PerceivedComplexity:
29
+ Enabled: false
30
+
31
+ Metrics/CyclomaticComplexity:
32
+ Enabled: false
33
+
34
+ Metrics/AbcSize:
35
+ Enabled: false
36
+
37
+ Metrics/ClassLength:
38
+ Enabled: false
39
+
40
+ AllCops:
41
+ Include:
42
+ - Rakefile
@@ -0,0 +1,18 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3-p551
4
+ - 2.3.0
5
+ deploy:
6
+ provider: rubygems
7
+ api_key:
8
+ secure: GA+unl5GMrMEsqK1t6O9At23zzvKLzZ6FQMGZoYZvZehCSA/fSrhorwfv113RbanTpLOHgwtkTU/geTc9pZ2iX/EfyEWbHklucPpnVWA6KmdUaWnmD1dih72W12U9m9l0VL6pVYgOkPXxB7zk7jAgh5UBIMqNOFnkLwRRqTEIfSXrLpX45OWSgGK7JdAR9HKjNFStylXAW7LXlLfBwj1nhQoROUHmtn/XCLTlqqWFwn70w/Ke0rdZMgsKDFuAgwZakYWBKsxNKMVAMFAqCaSo9SvF56so2uMqKwSxIao2HOR79O5QsgCFbV24kQyFrSABQA+SQNqveE4JWITpQ6eHWTAOo5w+d6JOKAoyH24eBsa3FUtgxWMH1XDilnH7B+HePhM9000w0BwAa3hOTaoGfn4kyu2fUXmvHjwCYoncFKxzEC+8iin4KQp3mGtTeC6KgrWxqGHdJyOmCIkuKF9jvO8iaGY/nDGKqp6sIwF03ub69DXZ43xzOYY6B2fLozGFpW/aBVZqjcEx1pOHBZu0dVfQ8r/ezcbneq5mUt1Pcl8G+DmEp3kw2l8EPAebeUbXwKpv+cdpakegStRNec3I5jo/KYDyi9j6k4UmkRnH6pcseOM41qUeDSNu010ayc/2qOVkfiXTVvcrfRk4m/yLh9eZryJU48okakhZafln6s=
9
+ gem: digital-ocean-cli
10
+ on:
11
+ tags: true
12
+ repo: ptdorf/digital-ocean-cli
13
+ notifications:
14
+ email:
15
+ - ptdorf@gmail.com
16
+ slack:
17
+ rooms:
18
+ - secure: JP0OSIVSATUs1e8ocvcUTgqQmUfkSejDk0MJ1+HZLpFmbsVazOi2Wbzhf1vL4nVQWEL6DK/PFiIcFaFSQ9OSBh+FCPUFe/2/vSKuV/q/ssFx/yzD2GczIVcXXaCmJdddXvMuPXsR6+KW415smD/+zPsalLpsp45Jk8XaCpJPbSKRK4szOG+c49GynD3PD0bZk8jTLfhSwGyWDb8xrYgJESVXGwhBYBrxIDipct8Nexkr35K6a9gqSpAtkzS2U21X1Ts4gqHAUzAJaHtZJt6cFSh/2b0ZmfRG0YPQuOruqYCoOI75LY1QMewACps/I8E0ZVyL9Xs8Rxsqg8B0l4XSWvxA0fUmTnaYAcvgtP6WOeC16Fp9Fgudi8/4qP9zPkH+6LjjrstCs161YPy5vL5PfdWw15+h8JrOlNMRSKPY+YkshLSjKrEISSk+ELJUjc2wz2AuL6xGVZBt2yaQCzSWswBUSAUDhmfVSn8oEjs9IZVDos9NmdiDDFFArfkzccpL6NbgTLRrNHS2rGLojOmbsBmDC7wrjzah4oynW1Jnmd2yDH+ld1oB6HoDyyb2F/CZZTnuL28O1kGWJZdhMU/ck34DSPLStSowR3VQzcUXMZvL6NSWhntQxP37YLKTZ+jnR26jEfuyYZIAf0dRizJxYTdd8zIxI/nv0bjKxHyI+Mc=
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ digital-ocean-cli (0.4.0)
5
+ faker
6
+ thor
7
+ unirest
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.3.8)
13
+ ast (2.3.0)
14
+ faker (1.7.2)
15
+ i18n (~> 0.5)
16
+ i18n (0.7.0)
17
+ json (1.8.3)
18
+ mime-types (1.25.1)
19
+ parser (2.3.3.1)
20
+ ast (~> 2.2)
21
+ powerpack (0.1.1)
22
+ rainbow (2.2.1)
23
+ rake (12.0.0)
24
+ rest-client (1.6.9)
25
+ mime-types (~> 1.16)
26
+ rubocop (0.46.0)
27
+ parser (>= 2.3.1.1, < 3.0)
28
+ powerpack (~> 0.1)
29
+ rainbow (>= 1.99.1, < 3.0)
30
+ ruby-progressbar (~> 1.7)
31
+ unicode-display_width (~> 1.0, >= 1.0.1)
32
+ ruby-progressbar (1.8.1)
33
+ thor (0.19.4)
34
+ unicode-display_width (1.1.2)
35
+ unirest (1.1.2)
36
+ addressable (~> 2.3.5)
37
+ json (~> 1.8.1)
38
+ rest-client (~> 1.6.7)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ digital-ocean-cli!
45
+ rake
46
+ rubocop
47
+
48
+ BUNDLED WITH
49
+ 1.13.6
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require "rubocop/rake_task"
3
+
4
+ RuboCop::RakeTask.new do |task|
5
+ task.options = ["-D"]
6
+ task.fail_on_error = false
7
+ end
8
+
9
+ task default: [
10
+ :rubocop,
11
+ :release,
12
+ ]
@@ -0,0 +1,369 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
3
+
4
+ require "thor"
5
+ require "json"
6
+ require "faker"
7
+ require "unirest"
8
+ require "digital_ocean"
9
+
10
+ DIR = File.expand_path("~/.digital-ocean")
11
+ DEFAULT = File.read("#{DIR}/.account").chomp if File.file? "#{DIR}/.account"
12
+ ACCOUNT = ENV["DIGITALOCEAN_ACCOUNT"] || DEFAULT
13
+ FILE = "#{DIR}/#{ACCOUNT}.txt"
14
+ TOKEN = File.read(FILE).chomp if File.file? FILE
15
+ API = "https://api.digitalocean.com/v2"
16
+ SSHKEY = "main"
17
+ IMAGES = {
18
+ "centos" => "centos-7-x64",
19
+ "debian" => "debian-8-x64",
20
+ "ubuntu" => "ubuntu-16-04-x64",
21
+ }
22
+
23
+ module DigitalOcean
24
+ class Base < Thor
25
+ private
26
+
27
+ def short(token)
28
+ # "#{token[0..3]}--#{token[token.size-2..token.size]}"
29
+ token[0..6]
30
+ end
31
+
32
+ def table(data)
33
+ widths = []
34
+ data.each do |line|
35
+ c = 0
36
+ line.each do |col|
37
+ str = col.to_s
38
+ len = str.length
39
+ widths[c] = len if widths[c].nil? || len > widths[c]
40
+ c += 1
41
+ end
42
+ end
43
+
44
+ format = widths.collect { |n| "%-#{n}s" }.join(" ").chomp + "\n"
45
+ data.each do |row|
46
+ printf format, *row
47
+ end
48
+ end
49
+
50
+ def load
51
+ @headers = {
52
+ "Authorization" => "Bearer #{TOKEN}",
53
+ "Content-Type" => "application/json",
54
+ }
55
+ end
56
+
57
+ def request(method, resource, data = {})
58
+ load
59
+ url = "#{API}/#{resource}"
60
+ Unirest.send method, url, headers: @headers, parameters: data
61
+ end
62
+
63
+ def find_ids
64
+ ids = {}
65
+ res = request("get", "droplets")
66
+ res.body["droplets"].each do |d|
67
+ ids[d['id']] = public_ip(d["networks"]["v4"])
68
+ end
69
+ ids
70
+ end
71
+
72
+ def display(rows)
73
+ data = []
74
+ data << [
75
+ "ID",
76
+ "NAME",
77
+ "IMAGE",
78
+ "SLUG",
79
+ "STATUS",
80
+ "IP",
81
+ "MEMORY",
82
+ "DISK",
83
+ "REGION",
84
+ ]
85
+ rows.each do |row|
86
+ data << [
87
+ row["id"],
88
+ row["name"],
89
+ "#{row['image']['distribution']} #{row['image']['name']}",
90
+ row["image"]["slug"],
91
+ row["status"],
92
+ public_ip(row["networks"]["v4"]),
93
+ row["size"]["memory"],
94
+ row["size"]["disk"],
95
+ row["region"]["slug"],
96
+ # row["created_at"],
97
+ ]
98
+ end
99
+ table data
100
+ end
101
+
102
+ def find_keys(name = nil)
103
+ res = request("get", "account/keys")
104
+ if name
105
+ res.body["ssh_keys"].each do |d|
106
+ return d["id"] if d["name"] == name
107
+ end
108
+ return
109
+ end
110
+
111
+ data = []
112
+ data << ["ID", "NAME", "FINGERPRINT"]
113
+ res.body["ssh_keys"].each do |d|
114
+ data << [
115
+ d["id"],
116
+ d["name"],
117
+ d["fingerprint"]
118
+ ]
119
+ end
120
+ data
121
+ end
122
+
123
+ def public_ip(ips)
124
+ ips.each do |ip|
125
+ return ip["ip_address"] if ip["type"] == "public"
126
+ end
127
+ end
128
+ end
129
+
130
+ class Account < Base
131
+ desc "ls", "Shows all accounts"
132
+ def ls
133
+ rows = [["ACCOUNT", "SHORT", "TOKEN"]]
134
+ Dir["#{DIR}/*.txt"].each do |file|
135
+ name = file.sub("#{DIR}/", "").sub(".txt", "")
136
+ curr = ACCOUNT == name ? "*" : " "
137
+ token = File.read(file).chomp
138
+ short = short(token)
139
+ rows << ["#{curr} #{name}", short, token]
140
+ end
141
+ table rows
142
+ end
143
+
144
+ desc "info", "Show the account details"
145
+ def info
146
+ res = request("get", "account")
147
+ row = res.body["account"]
148
+ data = []
149
+ data << ["NAME", "VALUE"]
150
+ data << ["Account", ACCOUNT]
151
+ data << ["Short", short(TOKEN)]
152
+ data << ["Token", TOKEN]
153
+ [
154
+ "uuid",
155
+ "email",
156
+ "droplet_limit",
157
+ "floating_ip_limit",
158
+ "status",
159
+ "status_message",
160
+ ].each do |v|
161
+ data << [v, row[v]]
162
+ end
163
+ table data
164
+ end
165
+
166
+ desc "use [NAME]", "Shows or set the default account name"
167
+ def use(name = nil)
168
+ if name
169
+ File.write "#{DIR}/.account", name
170
+ else
171
+ puts ACCOUNT
172
+ end
173
+ end
174
+
175
+ desc "new [NAME] [TOKEN]", "Sets up local access to an account"
176
+ def new(name = nil, token = nil)
177
+ unless name
178
+ print "Enter the account name: "
179
+ name = STDIN.gets.chomp
180
+ end
181
+ unless token
182
+ print "Enter the account token: "
183
+ token = STDIN.gets.chomp
184
+ end
185
+ file = "#{DIR}/#{name}.txt"
186
+ File.write file, token
187
+ end
188
+
189
+ desc "keys [NAME]", "Show the account keys"
190
+ def keys(name = nil)
191
+ data = find_keys(name)
192
+ if name
193
+ puts data if data
194
+ return
195
+ end
196
+
197
+ table data
198
+ end
199
+ end
200
+
201
+ class Cli < Base
202
+ class_option :v, type: :boolean, desc: "Show more verbosity"
203
+
204
+ desc "version", "Shows the version"
205
+ def version
206
+ puts "v#{VERSION}"
207
+ end
208
+
209
+ desc "top [WAIT]", "Checks the status every WAIT seconds"
210
+ def top(wait = 5)
211
+ loop do
212
+ ls
213
+ puts
214
+ sleep wait.to_i
215
+ end
216
+ end
217
+
218
+ desc "ls [ID]", "Lists one or all your machines"
219
+ def ls(id = nil)
220
+ if id
221
+ res = request("get", "droplets/#{id}")
222
+ rows = [res.body["droplet"]]
223
+ else
224
+ res = request("get", "droplets")
225
+ rows = res.body["droplets"]
226
+ end
227
+ display rows
228
+ end
229
+
230
+ desc "show ID", "Show info about a machine"
231
+ def show(id)
232
+ res = request("get", "droplets/#{id}")
233
+ puts JSON.pretty_generate(res.body)
234
+ end
235
+
236
+ desc "regions", "Show the available regions"
237
+ def regions
238
+ res = request("get", "regions")
239
+ rows = res.body["regions"]
240
+ data = []
241
+ # data << ["SLUG", "NAME", "AVAILABLE", "SIZES", "FEATURES"]
242
+ data << ["SLUG", "NAME", "AVAILABLE", "FEATURES"]
243
+ rows.each do |row|
244
+ data << [
245
+ row["slug"],
246
+ row["name"],
247
+ row["available"],
248
+ # row["sizes"].join(" "),
249
+ row["features"].join(" "),
250
+ ]
251
+ end
252
+ table data
253
+ end
254
+
255
+ desc "ssh [NAME]", "Logs into a machine"
256
+ def ssh(name = nil)
257
+ ids = find_ids
258
+ if name.nil?
259
+ return ls if ids.size > 1
260
+ name = ids.keys.first
261
+ end
262
+ ip = ids[name.to_i]
263
+ exec "ssh root@#{ip}"
264
+ end
265
+
266
+ desc "rm ID", "Deletes a machine"
267
+ def rm(*ids)
268
+ errors = []
269
+ if ids.empty?
270
+ ids2 = find_ids
271
+ return ls if ids2.size > 1
272
+ ids << ids2.keys.first
273
+ end
274
+
275
+ ids.each do |id|
276
+ res = request("delete", "droplets/#{id}")
277
+ if res.code == 204
278
+ puts id
279
+ else
280
+ errors << "rm #{id}: " + res.body["message"]
281
+ end
282
+ end
283
+ abort errors.join("\n") unless errors.empty?
284
+ end
285
+
286
+ desc "wipe", "Deletes all machines"
287
+ def wipe
288
+ abort "This command is cancelled."
289
+ ids = []
290
+ res = request("get", "droplets")
291
+ res.body["droplets"].each do |d|
292
+ ids << d["id"]
293
+ end
294
+ rm(*ids)
295
+ end
296
+
297
+ desc "images", "Shows available images"
298
+ def images(region = nil)
299
+ data = []
300
+ data << ["KEY", "NAME", "REGIONS"]
301
+ res = request("get", "images")
302
+ res.body["images"].each do |i|
303
+ if region
304
+ next unless i["regions"].include? region
305
+ end
306
+
307
+ data << [
308
+ i["slug"],
309
+ "#{i['distribution']} #{i['name']}",
310
+ i["regions"].join(", ")
311
+ ]
312
+ end
313
+ table data
314
+ end
315
+
316
+ desc "create", "Creates a new machine"
317
+ option :name
318
+ option :image, default: "debian"
319
+ option :region, default: "lon1"
320
+ option :size, default: "512mb"
321
+ option :key, default: SSHKEY
322
+ def create
323
+ key = options[:key]
324
+ keyid = find_keys(key)
325
+ abort "Error: You need to set a #{key} key first." unless keyid
326
+
327
+ image = (image && IMAGES[image]) || IMAGES[options[:image]]
328
+ name = options[:name] \
329
+ || Faker::Hipster.words(2)
330
+ .join("-").downcase.gsub(/[^0-9A-Za-z\-.]/, "")
331
+
332
+ info = {
333
+ name: name,
334
+ image: image,
335
+ region: options[:region],
336
+ size: options[:size],
337
+ ssh_keys: [keyid],
338
+ private_networking: true,
339
+ }
340
+
341
+ res = request("post", "droplets", info)
342
+
343
+ if res.code == 202
344
+ row = res.body["droplet"]
345
+ id = row["id"]
346
+ if options[:v]
347
+ ls id
348
+ else
349
+ puts id
350
+ end
351
+ else
352
+ puts info
353
+ abort res.body["message"]
354
+ end
355
+ end
356
+
357
+ desc "account", "Account commands"
358
+ subcommand "account", Account
359
+ end
360
+ end
361
+
362
+ begin
363
+ DigitalOcean::Cli.start ARGV, debug: true
364
+ rescue Interrupt
365
+ puts "Bye"
366
+ rescue StandardError => e
367
+ puts "Error: #{e.message}"
368
+ abort
369
+ end
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+
3
+ require "digital_ocean"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "digital-ocean-cli"
7
+ s.version = DigitalOcean::VERSION
8
+ s.description = "Manage your digital ocean account"
9
+ s.summary = "Manage your digital ocean account."
10
+ s.authors = ["ptdorf"]
11
+ s.email = ["ptdorf@gmail.com"]
12
+ s.homepage = "https://github.com/ptdorf/digital-ocean-cli"
13
+ s.license = "MIT"
14
+ s.require_paths = ["lib"]
15
+
16
+ s.files = `git ls-files`.split $/
17
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename f }
18
+
19
+ s.add_dependency "thor"
20
+ s.add_dependency "json"
21
+ s.add_dependency "faker"
22
+ s.add_dependency "unirest"
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rubocop"
25
+ end
@@ -0,0 +1,5 @@
1
+ require "digital_ocean/ext/nil_class"
2
+
3
+ module DigitalOcean
4
+ VERSION = "0.5.0"
5
+ end
@@ -0,0 +1,7 @@
1
+ unless NilClass.method_defined?(:[])
2
+ class ::NilClass
3
+ def []
4
+ nil
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 ptdorf
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,12 @@
1
+ # digital-ocean-cli
2
+
3
+ Manage your digital ocean account.
4
+
5
+ [![Build Status](https://travis-ci.org/ptdorf/digital-ocean-cli.svg?branch=master)](https://travis-ci.org/ptdorf/digital-ocean-cli)
6
+ [![Gem Version](https://badge.fury.io/rb/digital-ocean-cli.svg)](https://badge.fury.io/rb/digital-ocean-cli)
7
+
8
+ ## Installation
9
+
10
+ ```shell
11
+ sudo gem install digital-ocean-cli
12
+ ```
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: digital-ocean-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - ptdorf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
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: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faker
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: unirest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Manage your digital ocean account
98
+ email:
99
+ - ptdorf@gmail.com
100
+ executables:
101
+ - digital-ocean
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rubocop.yml"
107
+ - ".travis.yml"
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - Rakefile
111
+ - bin/digital-ocean
112
+ - digital-ocean-cli.gemspec
113
+ - lib/digital_ocean.rb
114
+ - lib/digital_ocean/ext/nil_class.rb
115
+ - license.txt
116
+ - readme.md
117
+ homepage: https://github.com/ptdorf/digital-ocean-cli
118
+ licenses:
119
+ - MIT
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 2.6.6
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Manage your digital ocean account.
141
+ test_files: []