digital-ocean-cli 0.5.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: 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: []