pi 0.1.13
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.
- data/README +402 -0
- data/Rakefile +17 -0
- data/bin/pi +6 -0
- data/lib/cli.rb +25 -0
- data/lib/cli/commands/base.rb +47 -0
- data/lib/cli/commands/misc.rb +17 -0
- data/lib/cli/commands/projects.rb +294 -0
- data/lib/cli/commands/user.rb +153 -0
- data/lib/cli/config.rb +96 -0
- data/lib/cli/core_ext.rb +118 -0
- data/lib/cli/errors.rb +19 -0
- data/lib/cli/runner.rb +269 -0
- data/lib/cli/usage.rb +53 -0
- data/lib/cli/version.rb +5 -0
- data/lib/pi.rb +3 -0
- data/lib/pi/client.rb +250 -0
- data/lib/pi/const.rb +15 -0
- metadata +198 -0
data/lib/cli/usage.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
class PI::Cli::Runner
|
2
|
+
|
3
|
+
def basic_usage
|
4
|
+
"Usage: pi [options] command [<args>] [command_options]\n" +
|
5
|
+
"Try 'pi help [command]' or 'pi help options' for more information."
|
6
|
+
end
|
7
|
+
|
8
|
+
def display_usage
|
9
|
+
if @usage
|
10
|
+
say @usage_error if @usage_error
|
11
|
+
say "Usage: #{@usage}"
|
12
|
+
return
|
13
|
+
elsif @verb_usage
|
14
|
+
say @verb_usage
|
15
|
+
return
|
16
|
+
end
|
17
|
+
say command_usage
|
18
|
+
end
|
19
|
+
|
20
|
+
def command_usage
|
21
|
+
<<-USAGE
|
22
|
+
|
23
|
+
#{basic_usage}
|
24
|
+
|
25
|
+
Currently available pi commands are:
|
26
|
+
|
27
|
+
User
|
28
|
+
pi login [url] Login
|
29
|
+
pi logout Logs current user out of the system
|
30
|
+
pi info List system information
|
31
|
+
pi user Display user information
|
32
|
+
pi targets List available targets infomation
|
33
|
+
pi password [newpassword] Change the password for the current user
|
34
|
+
pi github [name] Bind to the github account
|
35
|
+
pi runtimes Display the supported runtimes of the system
|
36
|
+
pi frameworks Display the supported frameworks of the system
|
37
|
+
pi version Display version information
|
38
|
+
pi help [command] Get general help or help on a specific command
|
39
|
+
pi help options Get help on available options
|
40
|
+
|
41
|
+
Project
|
42
|
+
projects List created projects
|
43
|
+
create-project [projectname] Create a new project
|
44
|
+
delete-project [projectname] Delete the project
|
45
|
+
project-events [projectname] List the event info for the project
|
46
|
+
project-tags [projectname] List the tags for the project
|
47
|
+
project-commits [projectname] List the commit log for the project
|
48
|
+
project-apps [projectname] List the applications for the project
|
49
|
+
upload [projectname] Upload the war package for java project
|
50
|
+
USAGE
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
data/lib/cli/version.rb
ADDED
data/lib/pi.rb
ADDED
data/lib/pi/client.rb
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
require "uri"
|
2
|
+
require 'rubygems'
|
3
|
+
require 'json/pure'
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
require File.expand_path('../const', __FILE__)
|
7
|
+
|
8
|
+
class PI::Client
|
9
|
+
|
10
|
+
def self.version
|
11
|
+
PI::VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :target, :host, :auth_token
|
15
|
+
attr_accessor :trace
|
16
|
+
|
17
|
+
# Error codes
|
18
|
+
PI_HTTP_ERROR_CODES = [ 400, 500 ]
|
19
|
+
|
20
|
+
# Errors
|
21
|
+
class BadTarget < RuntimeError; end
|
22
|
+
class AuthError < RuntimeError; end
|
23
|
+
class TargetError < RuntimeError; end
|
24
|
+
class NotFound < RuntimeError; end
|
25
|
+
class BadResponse < RuntimeError; end
|
26
|
+
class HTTPException < RuntimeError; end
|
27
|
+
|
28
|
+
|
29
|
+
def initialize(target_urls=PI::DEFAULT_TARGET, auth_token=nil)
|
30
|
+
target_urls = "http://#{target_urls}" unless /^https?/ =~ target_urls
|
31
|
+
target_urls = target_urls.gsub(/\/+$/, '')
|
32
|
+
@target = target_urls
|
33
|
+
@auth_token = auth_token
|
34
|
+
end
|
35
|
+
|
36
|
+
#####################################################
|
37
|
+
# Users
|
38
|
+
#####################################################
|
39
|
+
|
40
|
+
def login(user, password)
|
41
|
+
status, body, headers = json_post("#{PI::TOKEN_PATH}", {:password => password,:userName => user})
|
42
|
+
response_info = json_parse(body)
|
43
|
+
if response_info
|
44
|
+
@auth_token = response_info[:token]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def info
|
49
|
+
json_get(PI::INFO_PATH)
|
50
|
+
end
|
51
|
+
|
52
|
+
def user_info
|
53
|
+
json_get(PI::USER_PATH)
|
54
|
+
end
|
55
|
+
|
56
|
+
def github_info
|
57
|
+
json_get("#{PI::USER_PATH}/github")
|
58
|
+
end
|
59
|
+
|
60
|
+
def targets
|
61
|
+
json_get("#{PI::USER_PATH}/targets")
|
62
|
+
end
|
63
|
+
|
64
|
+
def password(newpassword)
|
65
|
+
status, body, headers = json_post("#{PI::USER_PATH}/password/#{newpassword}",{:newpass => newpassword})
|
66
|
+
end
|
67
|
+
|
68
|
+
def github(manifest={})
|
69
|
+
json_post("#{PI::USER_PATH}/bind",manifest)
|
70
|
+
end
|
71
|
+
|
72
|
+
def runtimes
|
73
|
+
json_get("#{PI::INFO_PATH}/runtimes")
|
74
|
+
end
|
75
|
+
|
76
|
+
def frameworks(runtime)
|
77
|
+
json_get("#{PI::INFO_PATH}/frameworks/#{runtime}")
|
78
|
+
end
|
79
|
+
|
80
|
+
#####################################################
|
81
|
+
# projects
|
82
|
+
#####################################################
|
83
|
+
|
84
|
+
def projects
|
85
|
+
json_get("#{PI::PROJECT_PATH}/list")
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_project(name, manifest={})
|
89
|
+
status, body, headers = json_post("#{PI::PROJECT_PATH}/create", manifest)
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete_project(projectname)
|
93
|
+
http_delete("#{PI::PROJECT_PATH}/delete/#{projectname}",'application/json')
|
94
|
+
end
|
95
|
+
|
96
|
+
def upload(manifest={})
|
97
|
+
status, body, headers = http_post("#{PI::PROJECT_PATH}/upload", manifest)
|
98
|
+
response_info = json_parse(body)
|
99
|
+
end
|
100
|
+
|
101
|
+
def project_events(projectname)
|
102
|
+
json_get("#{PI::PROJECT_PATH}/events/#{projectname}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def project_tags(projectname)
|
106
|
+
json_get("#{PI::PROJECT_PATH}/tags/#{projectname}")
|
107
|
+
end
|
108
|
+
|
109
|
+
def project_commits(projectname,tag)
|
110
|
+
json_get("#{PI::PROJECT_PATH}/commitinfo/#{projectname}/#{tag}")
|
111
|
+
end
|
112
|
+
|
113
|
+
def project_apps(projectname)
|
114
|
+
json_get("#{PI::PROJECT_PATH}/apps/#{projectname}")
|
115
|
+
end
|
116
|
+
|
117
|
+
######################################################
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def json_get(url)
|
122
|
+
status, body, headers = http_get(url, 'application/json')
|
123
|
+
if body.empty?
|
124
|
+
body = nil
|
125
|
+
end
|
126
|
+
json_parse(body)
|
127
|
+
rescue JSON::ParserError
|
128
|
+
raise BadResponse, "Can't parse response into JSON", body
|
129
|
+
end
|
130
|
+
|
131
|
+
def json_post(url, payload)
|
132
|
+
http_post(url, payload.to_json, 'application/json')
|
133
|
+
end
|
134
|
+
|
135
|
+
def json_put(url, payload)
|
136
|
+
http_put(url, payload.to_json, 'application/json')
|
137
|
+
end
|
138
|
+
|
139
|
+
def json_parse(str)
|
140
|
+
if str
|
141
|
+
JSON.parse(str, :symbolize_names => true)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
require 'rest_client'
|
146
|
+
|
147
|
+
# HTTP helpers
|
148
|
+
|
149
|
+
def http_get(path, content_type=nil)
|
150
|
+
request(:get, path, content_type)
|
151
|
+
end
|
152
|
+
|
153
|
+
def http_post(path, body, content_type=nil)
|
154
|
+
request(:post, path, content_type, body)
|
155
|
+
end
|
156
|
+
|
157
|
+
def http_put(path, body, content_type=nil)
|
158
|
+
request(:put, path, content_type, body)
|
159
|
+
end
|
160
|
+
|
161
|
+
def http_delete(path,content_type=nil)
|
162
|
+
request(:delete, path,content_type)
|
163
|
+
end
|
164
|
+
|
165
|
+
def request(method, path, content_type = nil, payload = nil, headers = {})
|
166
|
+
headers = headers.dup
|
167
|
+
headers['Authentication'] = @auth_token if @auth_token
|
168
|
+
if content_type
|
169
|
+
headers['Content-Type'] = content_type
|
170
|
+
headers['Accept'] = content_type
|
171
|
+
end
|
172
|
+
req = {
|
173
|
+
:method => method, :url => "#{@target}#{path}",
|
174
|
+
:payload => payload, :headers => headers
|
175
|
+
}
|
176
|
+
status, body, response_headers = perform_http_request(req)
|
177
|
+
if request_failed?(status)
|
178
|
+
err = (status == 404 || status == 400) ? NotFound : TargetError
|
179
|
+
raise err, parse_error_message(status, body)
|
180
|
+
else
|
181
|
+
return status, body, response_headers
|
182
|
+
end
|
183
|
+
rescue URI::Error, SocketError, Errno::ECONNREFUSED => e
|
184
|
+
raise BadTarget, "Cannot access target (%s)" % [ e.message ]
|
185
|
+
end
|
186
|
+
|
187
|
+
def request_failed?(status)
|
188
|
+
PI_HTTP_ERROR_CODES.detect{|error_code| status >= error_code}
|
189
|
+
end
|
190
|
+
|
191
|
+
def perform_http_request(req)
|
192
|
+
unless trace.nil?
|
193
|
+
req[:headers]['X-VCAP-Trace'] = (trace == true ? '22' : trace)
|
194
|
+
end
|
195
|
+
|
196
|
+
result = nil
|
197
|
+
RestClient::Request.execute(req) do |response, request|
|
198
|
+
result = [ response.code, response.body, response.headers ]
|
199
|
+
unless trace.nil?
|
200
|
+
puts '>>>'
|
201
|
+
puts "REQUEST: #{req[:method]} #{req[:url]}"
|
202
|
+
puts "RESPONSE_HEADERS:"
|
203
|
+
response.headers.each do |key, value|
|
204
|
+
puts " #{key} : #{value}"
|
205
|
+
end
|
206
|
+
puts "REQUEST_BODY: #{req[:payload]}" if req[:payload]
|
207
|
+
puts "RESPONSE: [#{response.code}]"
|
208
|
+
begin
|
209
|
+
puts JSON.pretty_generate(JSON.parse(response.body))
|
210
|
+
rescue
|
211
|
+
puts "#{response.body}"
|
212
|
+
end
|
213
|
+
puts '<<<'
|
214
|
+
end
|
215
|
+
end
|
216
|
+
result
|
217
|
+
rescue Net::HTTPBadResponse => e
|
218
|
+
raise BadTarget "Received bad HTTP response from target: #{e}"
|
219
|
+
rescue SystemCallError, RestClient::Exception => e
|
220
|
+
raise HTTPException, "HTTP exception: #{e.class}:#{e}"
|
221
|
+
end
|
222
|
+
|
223
|
+
def truncate(str, limit = 30)
|
224
|
+
etc = '...'
|
225
|
+
stripped = str.strip[0..limit]
|
226
|
+
if stripped.length > limit
|
227
|
+
stripped + etc
|
228
|
+
else
|
229
|
+
stripped
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def parse_error_message(status, body)
|
234
|
+
parsed_body = json_parse(body.to_s)
|
235
|
+
if parsed_body && parsed_body[:code] && parsed_body[:description]
|
236
|
+
desc = parsed_body[:description].gsub("\"","'")
|
237
|
+
"Error #{parsed_body[:code]}: #{desc}"
|
238
|
+
else
|
239
|
+
"Error (HTTP #{status}): #{body}"
|
240
|
+
end
|
241
|
+
rescue JSON::ParserError
|
242
|
+
if body.nil? || body.empty?
|
243
|
+
"Error (#{status}): No Response Received"
|
244
|
+
else
|
245
|
+
body_out = trace ? body : truncate(body)
|
246
|
+
"Error (JSON #{status}): #{body_out}"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
data/lib/pi/const.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module PI
|
2
|
+
|
3
|
+
VERSION = 'Bougatsa 0.6.0'
|
4
|
+
|
5
|
+
# Targets
|
6
|
+
DEFAULT_TARGET = 'https://api.staging.samsungcloud.org'
|
7
|
+
DEFAULT_LOCAL_TARGET = 'http://www.samsungcloud.org'
|
8
|
+
|
9
|
+
# General Paths
|
10
|
+
INFO_PATH = '/info'
|
11
|
+
TOKEN_PATH = '/token'
|
12
|
+
PROJECT_PATH = '/project'
|
13
|
+
USER_PATH = '/user'
|
14
|
+
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 1
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 13
|
10
|
+
version: 0.1.13
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Samsung
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-07-09 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: json_pure
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 1
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 5
|
32
|
+
- 1
|
33
|
+
version: 1.5.1
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: highline
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 13
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 6
|
48
|
+
- 1
|
49
|
+
version: 1.6.1
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rest-client
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 13
|
61
|
+
segments:
|
62
|
+
- 1
|
63
|
+
- 6
|
64
|
+
- 1
|
65
|
+
version: 1.6.1
|
66
|
+
- - <
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 11
|
69
|
+
segments:
|
70
|
+
- 1
|
71
|
+
- 7
|
72
|
+
- 0
|
73
|
+
version: 1.7.0
|
74
|
+
type: :runtime
|
75
|
+
version_requirements: *id003
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: terminal-table
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ~>
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 1
|
87
|
+
- 4
|
88
|
+
- 2
|
89
|
+
version: 1.4.2
|
90
|
+
type: :runtime
|
91
|
+
version_requirements: *id004
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: rake
|
94
|
+
prerelease: false
|
95
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
type: :development
|
105
|
+
version_requirements: *id005
|
106
|
+
- !ruby/object:Gem::Dependency
|
107
|
+
name: rspec
|
108
|
+
prerelease: false
|
109
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ~>
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
hash: 27
|
115
|
+
segments:
|
116
|
+
- 1
|
117
|
+
- 3
|
118
|
+
- 0
|
119
|
+
version: 1.3.0
|
120
|
+
type: :development
|
121
|
+
version_requirements: *id006
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
name: webmock
|
124
|
+
prerelease: false
|
125
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ~>
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
132
|
+
- 1
|
133
|
+
- 5
|
134
|
+
- 0
|
135
|
+
version: 1.5.0
|
136
|
+
type: :development
|
137
|
+
version_requirements: *id007
|
138
|
+
description: Pi Command Line Tool
|
139
|
+
email: bstpaas@gmail.com
|
140
|
+
executables:
|
141
|
+
- pi
|
142
|
+
extensions: []
|
143
|
+
|
144
|
+
extra_rdoc_files:
|
145
|
+
- README
|
146
|
+
files:
|
147
|
+
- README
|
148
|
+
- Rakefile
|
149
|
+
- lib/cli/config.rb
|
150
|
+
- lib/cli/version.rb
|
151
|
+
- lib/cli/errors.rb
|
152
|
+
- lib/cli/core_ext.rb
|
153
|
+
- lib/cli/commands/misc.rb
|
154
|
+
- lib/cli/commands/base.rb
|
155
|
+
- lib/cli/commands/user.rb
|
156
|
+
- lib/cli/commands/projects.rb
|
157
|
+
- lib/cli/runner.rb
|
158
|
+
- lib/cli/usage.rb
|
159
|
+
- lib/pi.rb
|
160
|
+
- lib/pi/const.rb
|
161
|
+
- lib/pi/client.rb
|
162
|
+
- lib/cli.rb
|
163
|
+
- bin/pi
|
164
|
+
homepage: http://www.samsungcloud.org/
|
165
|
+
licenses: []
|
166
|
+
|
167
|
+
post_install_message:
|
168
|
+
rdoc_options: []
|
169
|
+
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
hash: 3
|
178
|
+
segments:
|
179
|
+
- 0
|
180
|
+
version: "0"
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
none: false
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
hash: 3
|
187
|
+
segments:
|
188
|
+
- 0
|
189
|
+
version: "0"
|
190
|
+
requirements: []
|
191
|
+
|
192
|
+
rubyforge_project:
|
193
|
+
rubygems_version: 1.8.15
|
194
|
+
signing_key:
|
195
|
+
specification_version: 3
|
196
|
+
summary: Commandline tool that provides access to Samsung Cloud Platform.
|
197
|
+
test_files: []
|
198
|
+
|