pearl 0.0.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d6467e461a96b75d2007d98c2d649df5cc46a653
4
+ data.tar.gz: e3159cde72e0b07c87275980bb02a0e50eec0784
5
+ SHA512:
6
+ metadata.gz: 1907733bf543d07eef72e81f8f211e002d6d929fab70b7477db52bcfd247432c5271e86e337e95026c4df4b87ee22d4c0c3ab21aa7c416c777cd0dbb09344b06
7
+ data.tar.gz: 8e3751f899dc90f914c1e44229c8d7ed5a1c6e4d92663a657f957aa57e195f57da4127b0cd5840549d28e2eabd3ee7c18f8184876da6eb655f5f6e0b5dc47c67
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pearl.gemspec
4
+ gemspec
5
+
6
+ gem 'rake', group: [:development, :test]
7
+
8
+ # Development dependencies
9
+ group :development do
10
+ gem 'yard'
11
+ end
12
+
13
+ group :test do
14
+ gem 'minitest'
15
+ gem 'minitest-wscolor' if RUBY_VERSION >= '1.9.3'
16
+ gem 'mocha', require: 'mocha/setup'
17
+ gem 'simplecov', require: false
18
+ gem 'turn'
19
+ gem 'vcr'
20
+ gem 'webmock', require: 'webmock/minitest'
21
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Manish Valechha
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.
data/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # Pearl
2
+
3
+ Pearl is a command line interface to DigitlOcean's API.
4
+
5
+ ## Setup
6
+
7
+ Run the following command to install
8
+
9
+ $ gem install pearl
10
+
11
+ Add your client id and api key as enviroment variables
12
+
13
+ ENV['DIGITAL_OCEAN_CLIENT_ID']
14
+ ENV['DIGITAL_OCEAN_API_KEY']
15
+
16
+ ## Usage
17
+
18
+ ### Droplets
19
+
20
+ To see all your droplets
21
+
22
+ $ pearl droplets
23
+
24
+ To view a droplet
25
+
26
+ $ pearl droplet -d <droplet id>
27
+
28
+ To create a droplet
29
+
30
+ $ pearl droplet add 'name' --size <size id> --image <image id> --region <region id>
31
+
32
+ or
33
+
34
+ $ pearl droplet add 'name' -s <size id> -i <image id> -r <region id>
35
+
36
+ Reboot a droplet
37
+
38
+ $ pearl droplet reboot -d <droplet id>
39
+
40
+ Power cycle droplet
41
+
42
+ $ pearl droplet power cycle -d <droplet id>
43
+
44
+ Shutdown droplet
45
+
46
+ $ pearl droplet shutdown -d <droplet id>
47
+
48
+ Power Off droplet
49
+
50
+ $ pearl droplet power off -d <droplet id>
51
+
52
+ Power On droplet
53
+
54
+ $ pearl droplet power_on -d <droplet id>
55
+
56
+ Reset root password
57
+
58
+ $ pearl droplet password_reset -d <droplet id>
59
+
60
+ Resize droplet
61
+
62
+ $ pearl droplet resize -d <droplet id> -s <size id>
63
+
64
+ Take a snapshot
65
+
66
+ $ pearl droplet snapshot 'snapshot_name' -d <droplet id>
67
+
68
+ Restore droplet
69
+
70
+ $ pearl droplet restore -d <droplet id> -i <image id>
71
+
72
+ Rebuild droplet
73
+
74
+ $ pearl droplet rebuild -d <droplet id> -i <image id>
75
+
76
+ Enable automatic backups
77
+
78
+ $ pearl droplet enable backups -d <droplet id>
79
+
80
+ Disable automatic backups
81
+
82
+ $ pearl droplet disable backups -d <droplet id>
83
+
84
+ Destroy droplet
85
+
86
+ $ pearl droplet destroy -d <droplet id>
87
+
88
+ ### Regions
89
+
90
+ Display regions
91
+
92
+ $ pearl regions
93
+
94
+ ### Sizes
95
+
96
+ Display regions
97
+
98
+ $ pearl sizes
99
+
100
+ ### Images
101
+
102
+ Display all images
103
+
104
+ $ pearl images
105
+
106
+ To display your images
107
+
108
+ $ pearl images --filter my
109
+
110
+ To display global images (default)
111
+
112
+ $ pearl images --filter global
113
+
114
+ View a single image
115
+
116
+ $ pearl image -i <image id>
117
+
118
+ To destroy an image
119
+
120
+ $ pearl image destroy -i <image id>
121
+
122
+ ## TODO
123
+
124
+ * Format output instead of just printing the json response.
125
+ * Add SSH resource.
126
+
127
+ ## Contributing
128
+
129
+ 1. Fork it
130
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
131
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
132
+ 4. Push to the branch (`git push origin my-new-feature`)
133
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << 'test'
7
+ t.pattern = 'test/**/*_test.rb'
8
+ end
9
+ task default: :test
10
+
11
+ begin
12
+ require 'yard'
13
+ YARD::Rake::YardocTask.new(:doc) do |task|
14
+ task.files = ['READEME.md', 'LICENSE.txt', 'lib/**/*.rb']
15
+ task.options = [
16
+ '--output-dir', 'doc',
17
+ '--markup', 'markdown',
18
+ ]
19
+ end
20
+ rescue LoadError
21
+ end
data/bin/pearl ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # resolve bin path, ignoring symlinks
5
+ require "pathname"
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ # add self to libpath
9
+ $:.unshift File.expand_path("../../lib", bin_file)
10
+
11
+ require 'pearl/cli'
12
+ Pearl::CLI.execute(*ARGV)
data/lib/pearl/cli.rb ADDED
@@ -0,0 +1,215 @@
1
+ require "optparse"
2
+
3
+ require 'pearl'
4
+
5
+ module Pearl
6
+ module CLI
7
+ # Parse command line arguments
8
+ def self.execute(*args)
9
+ droplet = nil
10
+ image = nil
11
+ region = nil
12
+ size = nil
13
+
14
+ images_filter = nil
15
+
16
+ opts = OptionParser.new do |opts|
17
+ opts.banner = "Usage: pearl [resource] [options]"
18
+
19
+ opts.on('-d', '--droplet [DROPLET ID]', 'Select the droplet with this id') do |d|
20
+ droplet = d
21
+ end
22
+
23
+ opts.on('-f', '--filter', 'Display either your images or global images') do |filter|
24
+ images_filter = filter
25
+ end
26
+
27
+ opts.on('-h', '--help', 'Display this message') do
28
+ puts opts
29
+ exit
30
+ end
31
+
32
+ opts.on('-i', '--image [IMAGE ID]', 'Set the image for the droplet') do |i|
33
+ image = i
34
+ end
35
+
36
+ opts.on('-r', '--region [REGION ID]', 'Set the region for the droplet') do |r|
37
+ region = r
38
+ end
39
+
40
+ opts.on('-s', '--size [SIZE ID]', 'Set the size forthe droplet') do |s|
41
+ size = s
42
+ end
43
+
44
+ opts.on('-v', '--version', 'Display version') do
45
+ puts Pearl::VERSION
46
+ exit
47
+ end
48
+
49
+ begin
50
+ opts.parse!(args)
51
+
52
+ if $stdin.tty? && args[0] != '-'
53
+
54
+ # Print help when args is empty
55
+ if args.empty?
56
+ puts opts
57
+ exit
58
+ end
59
+
60
+ # Join command(s) to make it easier to catch using regex
61
+ command = args.join(' ')
62
+
63
+ case command.to_s
64
+ when /\Adroplets\z/i
65
+ Pearl.droplets
66
+ exit
67
+ when /\Adroplet\z/i
68
+ droplet_id = droplet.to_i
69
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
70
+
71
+ Pearl.droplet(droplet_id)
72
+ exit
73
+ when /\Adroplet add \w{3,}\z/i
74
+ image_id = image.to_i
75
+ raise 'Error: Invalid image id.' if image_id == 0 || !image_id.is_a?(Fixnum)
76
+
77
+ region_id = region.to_i
78
+ raise 'Error: Invalid region id.' if region_id == 0 || !region_id.is_a?(Fixnum)
79
+
80
+ size_id = size.to_i
81
+ raise 'Error: Invalid size id.' if size_id == 0 || !size_id.is_a?(Fixnum)
82
+
83
+ name = command.split(' ', 3)[2]
84
+ raise 'Error: Invalid droplet name.' if name.nil? || name.length <= 0
85
+
86
+ options = { name: name, image_id: image_id, region_id: region_id, size_id: size_id }
87
+
88
+ Pearl.create_droplet(options)
89
+ exit
90
+ when /\Adroplet reboot\z/i
91
+ droplet_id = droplet.to_i
92
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
93
+
94
+ Pearl.reboot(droplet_id)
95
+ exit
96
+ when /\Adroplet power cycle\z/i
97
+ droplet_id = droplet.to_i
98
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
99
+
100
+ Pearl.power_cycle(droplet_id)
101
+ exit
102
+ when /\Adroplet shutdown\z/i
103
+ droplet_id = droplet.to_i
104
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
105
+
106
+ Pearl.shutdown(droplet_id)
107
+ exit
108
+ when /\Adroplet power off\z/i
109
+ droplet_id = droplet.to_i
110
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
111
+
112
+ Pearl.power_off(droplet_id)
113
+ exit
114
+ when /\Adroplet power on\z/i
115
+ droplet_id = droplet.to_i
116
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
117
+
118
+ Pearl.power_on(droplet_id)
119
+ exit
120
+ when /\Adroplet password reset\z/i
121
+ droplet_id = droplet.to_i
122
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
123
+
124
+ Pearl.password_reset(droplet_id)
125
+ exit
126
+ when /\Adroplet resize\z/i
127
+ droplet_id = droplet.to_i
128
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
129
+
130
+ size_id = size.to_i
131
+ raise 'Error: Invalid size id.' if size_id == 0 || !size_id.is_a?(Fixnum)
132
+
133
+ Pearl.resize(droplet_id, size_id)
134
+ exit
135
+ when /\Adroplet snapshot \w{3,}\z/i
136
+ droplet_id = droplet.to_i
137
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
138
+
139
+ name = command.split(' ', 2)
140
+ raise 'Error: Invalid snapshot name.' if name.nil? || name.length <= 0
141
+
142
+ Pearl.snapshot(droplet_id, name)
143
+ exit
144
+ when /\Adroplet restore\z/i
145
+ droplet_id = droplet.to_i
146
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
147
+
148
+ image_id = image.to_i
149
+ raise 'Error: Invalid size id.' if image_id == 0 || !image_id.is_a?(Fixnum)
150
+
151
+ Pearl.restore(droplet_id, image_id)
152
+ exit
153
+ when /\Adroplet rebuild\z/i
154
+ droplet_id = droplet.to_i
155
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
156
+
157
+ image_id = image.to_i
158
+ raise 'Error: Invalid size id.' if image_id == 0 || !image_id.is_a?(Fixnum)
159
+
160
+ Pearl.rebuild(droplet_id, image_id)
161
+ exit
162
+ when /\Adroplet enable backups\z/i
163
+ droplet_id = droplet.to_i
164
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
165
+
166
+ Pearl.enable_backups(droplet_id)
167
+ exit
168
+ when /\Adroplet disable backups\z/i
169
+ droplet_id = droplet.to_i
170
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
171
+
172
+ Pearl.disable_backups(droplet_id)
173
+ exit
174
+ when /\Adroplet (destroy|delete)\z/i
175
+ droplet_id = droplet.to_i
176
+ raise 'Error: Invalid droplet id.' if droplet_id == 0 || !droplet_id.is_a?(Fixnum)
177
+
178
+ Pearl.destroy_droplet(droplet_id)
179
+ exit
180
+ when /\Aimages\z/i
181
+ Pearl.images(images_filter)
182
+ exit
183
+ when /\Aimage\z/i
184
+ image_id = image.to_i
185
+ raise 'Error: Invalid image id.' if image_id == 0 || !image_id.is_a?(Fixnum)
186
+
187
+ Pearl.image(image_id)
188
+ exit
189
+ when /\Aimage (destroy|delete)\z/i
190
+ image_id = image.to_i
191
+ raise 'Error: Invalid image id.' if image_id == 0 || !image_id.is_a?(Fixnum)
192
+
193
+ Pearl.destroy_image(image_id)
194
+ exit
195
+ when /\Aregions\z/i
196
+ Pearl.regions
197
+ exit
198
+ when /\Asizes\z/i
199
+ Pearl.sizes
200
+ exit
201
+ else
202
+ puts "Error: '#{command}' is an invalid command."
203
+ exit
204
+ end
205
+ end
206
+ rescue Interrupt
207
+ error("Command cancelled.")
208
+ rescue => error
209
+ warn error
210
+ puts opts
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,79 @@
1
+ module Pearl
2
+ class Client
3
+
4
+ module Droplets
5
+ def droplets
6
+ puts request("droplets").body
7
+ end
8
+
9
+ def droplet(id)
10
+ puts request("droplets/#{id}").body
11
+ end
12
+
13
+ def create_droplet(options = {})
14
+ params = { name: options[:name],
15
+ size_id: options[:size_id],
16
+ image_id: options[:image_id],
17
+ region_id: options[:region_id]
18
+ }
19
+ puts request("droplets/new", params).body
20
+ end
21
+
22
+ def reboot(id)
23
+ puts request("droplets/#{id}/reboot").body
24
+ end
25
+
26
+ def power_cycle(id)
27
+ puts request("droplets/#{id}/power_cycle").body
28
+ end
29
+
30
+ def shutdown(id)
31
+ puts request("droplets/#{id}/shutdown").body
32
+ end
33
+
34
+ def power_off(id)
35
+ puts request("droplets/#{id}/power_off").body
36
+ end
37
+
38
+ def power_on(id)
39
+ puts request("droplets/#{id}/power_on").body
40
+ end
41
+
42
+ def password_reset(id)
43
+ puts request("droplets/#{id}/password_reset").body
44
+ end
45
+
46
+ def resize(id, size_id)
47
+ params = { size_id: size_id }
48
+ puts request("droplets/#{id}/resize", params).body
49
+ end
50
+
51
+ def snapshot(id, name)
52
+ params = { name: name }
53
+ puts request("droplets/#{id}/snapshot", params).body
54
+ end
55
+
56
+ def restore(id, image_id)
57
+ params = { image_id: image_id }
58
+ puts request("droplets/#{id}/restore", params).body
59
+ end
60
+
61
+ def rebuild(id, image_id)
62
+ params = { image_id: image_id }
63
+ puts request("droplets/#{id}/rebuild", params).body
64
+ end
65
+
66
+ def enable_backups(id)
67
+ puts request("droplets/#{id}/enable_backups").body
68
+ end
69
+
70
+ def disable_backups(id)
71
+ puts request("droplets/#{id}/disable_backups").body
72
+ end
73
+
74
+ def destroy_droplet(id)
75
+ puts request("droplets/#{id}/destroy").body
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ module Pearl
2
+ class Client
3
+
4
+ module Images
5
+ # TODO: image filters
6
+ def images(filter)
7
+ if filter === /\A(my|global)\z/
8
+ params = { filter: name }
9
+ puts request("images", params).body
10
+ else
11
+ puts request("images").body
12
+ end
13
+ end
14
+
15
+ def image(id)
16
+ puts request("images/#{id}").body
17
+ end
18
+
19
+ def destroy_image(id)
20
+ puts request("images/#{id}").body
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module Pearl
2
+ class Client
3
+
4
+ module Regions
5
+ def regions
6
+ puts request("regions").body
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Pearl
2
+ class Client
3
+
4
+ module Sizes
5
+ def sizes
6
+ puts request("sizes").body
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ require 'pearl/http'
2
+
3
+ module Pearl
4
+ class Client
5
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each { |f| require f }
6
+
7
+ include Droplets
8
+ include Images
9
+ include Regions
10
+ include Sizes
11
+
12
+ attr_reader :client_id
13
+ attr_reader :api_key
14
+ attr_reader :api_host
15
+
16
+ def initialize(options = {})
17
+ @client_id = options[:client_id] || ENV['DIGITAL_OCEAN_CLIENT_ID']
18
+ @api_key = options[:api_key] || ENV['DIGITAL_OCEAN_API_KEY']
19
+ @api_host = options[:api_host] || 'api.digitalocean.com'
20
+
21
+ extend Pearl::HTTP
22
+
23
+ raise 'Error: Invalid client id.' if @client_id.nil?
24
+ raise 'Error: Invalid api key.' if @api_key.nil?
25
+ end
26
+
27
+ def base_url
28
+ "https://#{@api_host}/"
29
+ end
30
+
31
+ def authenticated?
32
+ @client_id != nil && @api_key != nil
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Pearl
2
+
3
+ # Standard Pearl Error for rescuing form all Peal errors
4
+ class Error < StandardError; end
5
+
6
+ # Raised when Peal returns a 400 HTTP status code
7
+ class BadRequest < Error; end
8
+
9
+ # Raised when Peal returns a 401 HTTP status code
10
+ class Unauthorized < Error; end
11
+
12
+ # Raised when Peal returns a 403 HTTP status code
13
+ class Forbidden < Error; end
14
+
15
+ # Raised when Peal returns a 404 HTTP status code
16
+ class NotFound < Error; end
17
+
18
+ # Raised when Peal returns a 406 HTTP status code
19
+ class NotAcceptable < Error; end
20
+
21
+ # Raised when Peal returns a 422 HTTP status code
22
+ class UnprocessableEntity < Error; end
23
+
24
+ # Raised when Peal returns a 500 HTTP status code
25
+ class InternalServerError < Error; end
26
+
27
+ # Raised when Peal returns a 501 HTTP status code
28
+ class NotImplemented < Error; end
29
+
30
+ # Raised when Peal returns a 502 HTTP status code
31
+ class BadGateway < Error; end
32
+
33
+ # Raised when Peal returns a 503 HTTP status code
34
+ class ServiceUnavailable < Error; end
35
+ end
data/lib/pearl/http.rb ADDED
@@ -0,0 +1,51 @@
1
+ module Pearl
2
+ module HTTP
3
+ require 'net/https'
4
+ require 'uri'
5
+
6
+ private
7
+ def http
8
+ return @http if @http
9
+
10
+ uri = URI.parse(self.base_url)
11
+ @http = Net::HTTP.new(uri.host, uri.port)
12
+
13
+ @http.use_ssl = true
14
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
15
+
16
+ @http
17
+ end
18
+
19
+ def request(path, params = nil)
20
+ uri = URI.parse("#{self.base_url}#{path}")
21
+
22
+ auth_params = { client_id: self.client_id, api_key: self.api_key }
23
+
24
+ if params.nil? || params.empty?
25
+ params = auth_params
26
+ else
27
+ params.merge!(auth_params)
28
+ end
29
+
30
+ uri.query = URI.encode_www_form(params)
31
+
32
+ request = Net::HTTP::Get.new(uri.request_uri)
33
+
34
+ request['Content-Type'] = 'application/json'
35
+
36
+ response = http.request(request)
37
+
38
+ Response.new(response)
39
+ end
40
+
41
+ class Response
42
+ attr_accessor :code
43
+ attr_accessor :body
44
+
45
+ def initialize(response)
46
+ @code = response.code
47
+ @body = response.body
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module Pearl
2
+ VERSION = "0.0.3"
3
+ end
data/lib/pearl.rb ADDED
@@ -0,0 +1,26 @@
1
+ require "pearl/version"
2
+ require "pearl/error"
3
+ require "pearl/client"
4
+
5
+ module Pearl
6
+ class << self
7
+
8
+ # Alias for Pearl::Client.new
9
+ #
10
+ # @return [Peal::Client]
11
+ def new(options = {})
12
+ Client.new(options)
13
+ end
14
+
15
+ # Delegate to Pearl::Client
16
+ def method_missing(method, *args, &block)
17
+ return super unless new.respond_to?(method)
18
+ new.send(method, *args, &block)
19
+ end
20
+
21
+ # Forward respond_to? to Pearl::Client
22
+ def respond_to?(method, include_private = false)
23
+ new.respond_to?(method, include_private) || super(method, include_private)
24
+ end
25
+ end
26
+ end
data/pearl.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pearl/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pearl"
8
+ spec.version = Pearl::VERSION
9
+ spec.authors = ["Manish Valechha"]
10
+ spec.email = ["manishval@hotmail.com"]
11
+ spec.description = "Command line interface for DigitalOcean's API"
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/manishval/pearl"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.executables = "pearl"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ class DropletsTest < Pearl::TestCase
4
+ def test_droplets
5
+ end
6
+
7
+ def test_droplet
8
+ end
9
+
10
+ def test_create_droplet
11
+ end
12
+
13
+ def test_reboot
14
+ end
15
+
16
+ def test_power_cycle
17
+ end
18
+
19
+ def test_shutdown
20
+ end
21
+
22
+ def test_power_off
23
+ end
24
+
25
+ def test_power_on
26
+ end
27
+
28
+ def test_password_reset
29
+ end
30
+
31
+ def test_resize
32
+ end
33
+
34
+ def test_snapshot
35
+ end
36
+
37
+ def test_restore
38
+ end
39
+
40
+ def test_rebuild
41
+ end
42
+
43
+ def test_enable_backups
44
+ end
45
+
46
+ def test_disable_backups
47
+ end
48
+
49
+ def test_destroy_droplet
50
+ end
51
+ end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ class ImagesTest < Pearl::TestCase
4
+ def test_images
5
+ end
6
+
7
+ def test_image
8
+ end
9
+
10
+ def test_detroy_image
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ require 'test_helper'
2
+
3
+ class RegionsTest < Pearl::TestCase
4
+ def test_regions
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'test_helper'
2
+
3
+ class SizesTest < Pearl::TestCase
4
+ def test_sizes
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class ClientTest < Pearl::TestCase
4
+ def test_initialization
5
+ client = Pearl::Client.new(client_id: 'qwerty')
6
+ assert_equal 'qwerty', client.client_id
7
+
8
+ client = Pearl::Client.new(api_key: 'ytrewq')
9
+ assert_equal 'ytrewq', client.api_key
10
+
11
+ client = Pearl::Client.new(client_id: 'qwerty', api_key: 'ytrewq')
12
+ assert_equal true, client.authenticated?
13
+
14
+ client = Pearl::Client.new
15
+ refute client.authenticated?
16
+ end
17
+
18
+ def test_base_url
19
+ client = Pearl::Client.new
20
+ assert_equal 'https://api.digitalocean.com/', client.base_url
21
+
22
+ client = Pearl::Client.new(api_host: 'www.example.com')
23
+ assert_equal 'https://www.example.com/', client.base_url
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ class PearlTest < Pearl::TestCase
4
+ def test_respond_to
5
+ assert Pearl.respond_to?(:new, true)
6
+ end
7
+
8
+ def test_new
9
+ assert_equal Pearl.new.class, Pearl::Client
10
+ end
11
+
12
+ def test_method_missing
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ module ClientMacros
2
+ def local_client
3
+ client = Pearl::Client.new(client_id: 'qwerty',
4
+ api_key: 'qwerty12345')
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require :test
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+
8
+ require 'minitest/autorun'
9
+ require 'pearl'
10
+
11
+ # Support files
12
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/support/*.rb"].each do |file|
13
+ require file
14
+ end
15
+
16
+ # VCR
17
+ VCR.configure do |c|
18
+ c.cassette_library_dir = 'test/cassettes'
19
+ c.hook_into :webmock
20
+ end
21
+
22
+ class Pearl::TestCase < MiniTest::Unit::TestCase
23
+ include ::ClientMacros
24
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pearl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Manish Valechha
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Command line interface for DigitalOcean's API
42
+ email:
43
+ - manishval@hotmail.com
44
+ executables:
45
+ - pearl
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/pearl
55
+ - lib/pearl.rb
56
+ - lib/pearl/cli.rb
57
+ - lib/pearl/client.rb
58
+ - lib/pearl/client/droplets.rb
59
+ - lib/pearl/client/images.rb
60
+ - lib/pearl/client/regions.rb
61
+ - lib/pearl/client/sizes.rb
62
+ - lib/pearl/error.rb
63
+ - lib/pearl/http.rb
64
+ - lib/pearl/version.rb
65
+ - pearl.gemspec
66
+ - test/pearl/client/droplets_test.rb
67
+ - test/pearl/client/images_test.rb
68
+ - test/pearl/client/regions_test.rb
69
+ - test/pearl/client/sizes_test.rb
70
+ - test/pearl/client_test.rb
71
+ - test/pearl_test.rb
72
+ - test/support/client_macros.rb
73
+ - test/test_helper.rb
74
+ homepage: https://github.com/manishval/pearl
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.0.0
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Command line interface for DigitalOcean's API
98
+ test_files:
99
+ - test/pearl/client/droplets_test.rb
100
+ - test/pearl/client/images_test.rb
101
+ - test/pearl/client/regions_test.rb
102
+ - test/pearl/client/sizes_test.rb
103
+ - test/pearl/client_test.rb
104
+ - test/pearl_test.rb
105
+ - test/support/client_macros.rb
106
+ - test/test_helper.rb
107
+ has_rdoc: