pebblescape 0.0.1

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: b61c815f3675629bb730094db75548baece46b75
4
+ data.tar.gz: 0f249f837f26ba716ac0c083c86b20b80a28d1d1
5
+ SHA512:
6
+ metadata.gz: 707f47a976e2fe070d73df12c843108fdcbce586d95178e75d4d194c3271b5e944e9d16bb5bbba592aead59e119ab5fbb84226f95f8655b300a405275bf94d8c
7
+ data.tar.gz: 085deccebcf684a5a462e1c5f3bb6fb612f1638a3be8306a766fd31ef4d603f5d3411cbe0ae23d9a2a137d024ef83541c4038f054389a6e1b1a216b3c9df0594
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pebbles.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'pry'
8
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Kristjan Rang
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,23 @@
1
+ # Pebbles
2
+
3
+ CLI client for Pebblescape.
4
+
5
+ This project is mostly a fork of https://github.com/heroku/heroku
6
+
7
+ ## Installation
8
+
9
+ Install it:
10
+
11
+ $ gem install pebbles
12
+
13
+ ## Usage
14
+
15
+ TODO: Write usage instructions here
16
+
17
+ ## Contributing
18
+
19
+ 1. Fork it ( https://github.com/[my-github-username]/pebbles/fork )
20
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
21
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
22
+ 4. Push to the branch (`git push origin my-new-feature`)
23
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Exit cleanly from an early interrupt
4
+ Signal.trap("INT") { exit 1 }
5
+
6
+ # resolve bin path, ignoring symlinks
7
+ require "pathname"
8
+ bin_file = Pathname.new(__FILE__).realpath
9
+
10
+ # add self to libpath
11
+ $:.unshift File.expand_path("../../lib", bin_file)
12
+
13
+ require 'pebbles/cli'
14
+ Pebbles::CLI.start(*ARGV)
@@ -0,0 +1,23 @@
1
+ require "pebbles/version"
2
+
3
+ module Pebbles
4
+ @@app_name = nil
5
+
6
+ USER_AGENT = "pebbles-gem/#{Pebbles::VERSION} (#{RUBY_PLATFORM}) ruby/#{RUBY_VERSION}"
7
+
8
+ def self.user_agent
9
+ @@user_agent ||= USER_AGENT
10
+ end
11
+
12
+ def self.user_agent=(agent)
13
+ @@user_agent = agent
14
+ end
15
+
16
+ def self.app_name
17
+ @@app_name
18
+ end
19
+
20
+ def self.app_name=(app_name)
21
+ @@app_name = app_name
22
+ end
23
+ end
@@ -0,0 +1,122 @@
1
+ require "base64"
2
+ require "cgi"
3
+ require "excon"
4
+ require "multi_json"
5
+ require "securerandom"
6
+ require "uri"
7
+ require "zlib"
8
+
9
+ require "pebbles/command"
10
+ require "pebbles/api/errors"
11
+ require "pebbles/api/apps"
12
+ require "pebbles/api/config_vars"
13
+ require "pebbles/api/login"
14
+ require "pebbles/api/releases"
15
+ require "pebbles/api/user"
16
+
17
+ module Pebbles
18
+ class API
19
+ HEADERS = {
20
+ 'Accept' => 'application/vnd.pebblescape+json; version=1',
21
+ 'Accept-Encoding' => 'gzip',
22
+ #'Accept-Language' => 'en-US, en;q=0.8',
23
+ 'User-Agent' => Pebbles.user_agent,
24
+ 'X-Ruby-Version' => RUBY_VERSION,
25
+ 'X-Ruby-Platform' => RUBY_PLATFORM
26
+ }
27
+
28
+ OPTIONS = {
29
+ :headers => {},
30
+ :host => 'api.pebblesinspace.com',
31
+ :nonblock => false,
32
+ :scheme => 'https'
33
+ }
34
+
35
+ def initialize(options={})
36
+ options = OPTIONS.merge(options)
37
+ options[:headers] = HEADERS.merge(options[:headers])
38
+
39
+ @api_key = options.delete(:api_key) || ENV['PEBBLES_API_KEY']
40
+ if !@api_key && options.has_key?(:username) && options.has_key?(:password)
41
+ username = options.delete(:username)
42
+ password = options.delete(:password)
43
+ @connection = Excon.new("#{options[:scheme]}://#{options[:host]}", options)
44
+ @api_key = self.post_login(username, password).body["api_key"]
45
+ end
46
+
47
+ @connection = Excon.new("#{options[:scheme]}://#{options[:host]}", options)
48
+ end
49
+
50
+ def request(params, &block)
51
+ if @api_key
52
+ params[:query] = {
53
+ 'api_key' => @api_key,
54
+ }.merge(params[:query] || {})
55
+ end
56
+
57
+ begin
58
+ response = @connection.request(params, &block)
59
+ rescue Excon::Errors::HTTPStatusError => error
60
+ klass = case error.response.status
61
+ when 401 then Pebbles::API::Errors::Unauthorized
62
+ when 402 then Pebbles::API::Errors::VerificationRequired
63
+ when 403 then Pebbles::API::Errors::Forbidden
64
+ when 404
65
+ if error.request[:path].match /\/apps\/\/.*/
66
+ Pebbles::API::Errors::NilApp
67
+ else
68
+ Pebbles::API::Errors::NotFound
69
+ end
70
+ when 408 then Pebbles::API::Errors::Timeout
71
+ when 422 then Pebbles::API::Errors::RequestFailed
72
+ when 423 then Pebbles::API::Errors::Locked
73
+ when 429 then Pebbles::API::Errors::RateLimitExceeded
74
+ when /50./ then Pebbles::API::Errors::RequestFailed
75
+ else Pebbles::API::Errors::ErrorWithResponse
76
+ end
77
+
78
+ decompress_response!(error.response)
79
+ reerror = klass.new(error.message, error.response)
80
+ reerror.set_backtrace(error.backtrace)
81
+ raise(reerror)
82
+ end
83
+
84
+ if response.body && !response.body.empty?
85
+ decompress_response!(response)
86
+ begin
87
+ response.body = MultiJson.load(response.body)
88
+ rescue
89
+ # leave non-JSON body as is
90
+ end
91
+ end
92
+
93
+ # reset (non-persistent) connection
94
+ @connection.reset
95
+
96
+ if response.headers.has_key?('X-Pebbles-Warning')
97
+ Pebbles::Command.warnings.concat(response.headers['X-Pebbles-Warning'].split("\n"))
98
+ end
99
+
100
+ response
101
+ end
102
+
103
+ private
104
+
105
+ def decompress_response!(response)
106
+ return unless response.headers['Content-Encoding'] == 'gzip'
107
+ response.body = Zlib::GzipReader.new(StringIO.new(response.body)).read
108
+ end
109
+
110
+ def app_params(params)
111
+ app_params = {}
112
+ params.each do |key, value|
113
+ app_params["app[#{key}]"] = value
114
+ end
115
+ app_params
116
+ end
117
+
118
+ def escape(string)
119
+ CGI.escape(string).gsub('.', '%2E')
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,71 @@
1
+ module Pebbles
2
+ class API
3
+
4
+ # DELETE /apps/:app
5
+ def delete_app(app)
6
+ request(
7
+ :expects => 200,
8
+ :method => :delete,
9
+ :path => "/apps/#{app}"
10
+ )
11
+ end
12
+
13
+ # GET /apps
14
+ def get_apps
15
+ request(
16
+ :expects => 200,
17
+ :method => :get,
18
+ :path => "/apps"
19
+ )
20
+ end
21
+
22
+ # GET /apps/:app
23
+ def get_app(app)
24
+ request(
25
+ :expects => 200,
26
+ :method => :get,
27
+ :path => "/apps/#{app}"
28
+ )
29
+ end
30
+
31
+ # GET /apps/:app/server/maintenance
32
+ def get_app_maintenance(app)
33
+ request(
34
+ :expects => 200,
35
+ :method => :get,
36
+ :path => "/apps/#{app}/server/maintenance"
37
+ )
38
+ end
39
+
40
+ # POST /apps
41
+ def post_app(params={})
42
+ request(
43
+ :expects => 201,
44
+ :method => :post,
45
+ :path => '/apps',
46
+ :query => app_params(params)
47
+ )
48
+ end
49
+
50
+ # POST /apps/:app/server/maintenance
51
+ def post_app_maintenance(app, maintenance_mode)
52
+ request(
53
+ :expects => 200,
54
+ :method => :post,
55
+ :path => "/apps/#{app}/server/maintenance",
56
+ :query => {'maintenance_mode' => maintenance_mode}
57
+ )
58
+ end
59
+
60
+ # PUT /apps/:app
61
+ def put_app(app, params)
62
+ request(
63
+ :expects => 200,
64
+ :method => :put,
65
+ :path => "/apps/#{app}",
66
+ :query => app_params(params)
67
+ )
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,33 @@
1
+ module Pebbles
2
+ class API
3
+
4
+ # DELETE /apps/:app/config_vars/:key
5
+ def delete_config_var(app, key)
6
+ request(
7
+ :expects => 200,
8
+ :method => :delete,
9
+ :path => "/apps/#{app}/config_vars/#{escape(key)}"
10
+ )
11
+ end
12
+
13
+ # GET /apps/:app/config_vars
14
+ def get_config_vars(app)
15
+ request(
16
+ :expects => 200,
17
+ :method => :get,
18
+ :path => "/apps/#{app}/config_vars"
19
+ )
20
+ end
21
+
22
+ # PUT /apps/:app/config_vars
23
+ def put_config_vars(app, vars)
24
+ request(
25
+ :body => MultiJson.dump(vars),
26
+ :expects => 200,
27
+ :method => :put,
28
+ :path => "/apps/#{app}/config_vars"
29
+ )
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ module Pebbles
2
+ class API
3
+ module Errors
4
+ class Error < StandardError; end
5
+
6
+ class ErrorWithResponse < Error
7
+ attr_reader :response
8
+
9
+ def initialize(message, response)
10
+ message = message << "\nbody: #{response.body.inspect}"
11
+ super message
12
+ @response = response
13
+ end
14
+ end
15
+
16
+ class Unauthorized < ErrorWithResponse; end
17
+ class VerificationRequired < ErrorWithResponse; end
18
+ class Forbidden < ErrorWithResponse; end
19
+ class NotFound < ErrorWithResponse; end
20
+ class Timeout < ErrorWithResponse; end
21
+ class Locked < ErrorWithResponse; end
22
+ class RateLimitExceeded < ErrorWithResponse; end
23
+ class RequestFailed < ErrorWithResponse; end
24
+ class NilApp < ErrorWithResponse; end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module Pebbles
2
+ class API
3
+
4
+ def post_login(username, password)
5
+ request(
6
+ :expects => 200,
7
+ :method => :post,
8
+ :path => '/login',
9
+ :query => { 'username' => username, 'password' => password }
10
+ )
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Pebbles
2
+ class API
3
+
4
+ # GET /apps/:app/releases
5
+ def get_releases(app)
6
+ request(
7
+ :expects => 200,
8
+ :method => :get,
9
+ :path => "/apps/#{app}/releases"
10
+ )
11
+ end
12
+
13
+ # GET /apps/:app/releases/:release
14
+ def get_release(app, release)
15
+ request(
16
+ :expects => 200,
17
+ :method => :get,
18
+ :path => "/apps/#{app}/releases/#{release}"
19
+ )
20
+ end
21
+
22
+ # POST /apps/:app/releases/:release
23
+ def post_release(app, release=nil)
24
+ request(
25
+ :expects => 200,
26
+ :method => :post,
27
+ :path => "/apps/#{app}/releases",
28
+ :query => {'rollback' => release}
29
+ )
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module Pebbles
2
+ class API
3
+
4
+ # GET /user
5
+ def get_user
6
+ request(
7
+ :expects => 200,
8
+ :method => :get,
9
+ :path => "/user"
10
+ )
11
+ end
12
+
13
+ end
14
+ end