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
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'terminal-table/import'
|
4
|
+
require 'highline/import'
|
5
|
+
|
6
|
+
module PI::Cli
|
7
|
+
|
8
|
+
module Command
|
9
|
+
|
10
|
+
class Base
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
@options = options.dup
|
14
|
+
|
15
|
+
# Fix for system ruby and Highline (stdin) on MacOSX
|
16
|
+
if RUBY_PLATFORM =~ /darwin/ && RUBY_VERSION == '1.8.7' && RUBY_PATCHLEVEL <= 174
|
17
|
+
HighLine.track_eof = false
|
18
|
+
end
|
19
|
+
|
20
|
+
# Suppress colorize on Windows systems for now.
|
21
|
+
if !!RUBY_PLATFORM['mingw'] || !!RUBY_PLATFORM['mswin32'] || !!RUBY_PLATFORM['cygwin']
|
22
|
+
PI::Cli::Config.colorize = false
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def client
|
28
|
+
return @client if @client
|
29
|
+
@client = PI::Client.new(target_url, auth_token)
|
30
|
+
@client.trace = PI::Cli::Config.trace if PI::Cli::Config.trace
|
31
|
+
@client.proxy_for @options[:proxy] if @options[:proxy]
|
32
|
+
@client
|
33
|
+
end
|
34
|
+
|
35
|
+
def target_url
|
36
|
+
@target_url = PI::Cli::Config.target_url
|
37
|
+
end
|
38
|
+
|
39
|
+
def auth_token
|
40
|
+
return @auth_token if @auth_token
|
41
|
+
@auth_token = PI::Cli::Config.auth_token
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module PI::Cli::Command
|
2
|
+
|
3
|
+
class Misc < Base
|
4
|
+
def version
|
5
|
+
say "pi #{PI::Cli::VERSION}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def set_target(target_url)
|
9
|
+
target_url = "http://#{target_url}" unless /^https?/ =~ target_url
|
10
|
+
target_url = target_url.gsub(/\/+$/, '')
|
11
|
+
client = PI::Client.new(target_url)
|
12
|
+
PI::Cli::Config.store_target(target_url)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,294 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'set'
|
6
|
+
|
7
|
+
module PI::Cli::Command
|
8
|
+
|
9
|
+
class Projects < Base
|
10
|
+
|
11
|
+
YES_SET = Set.new(["y", "Y", "yes", "YES"])
|
12
|
+
|
13
|
+
def projects
|
14
|
+
projects = client.projects
|
15
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
16
|
+
display "\n"
|
17
|
+
return display JSON.pretty_generate(projects) if @options[:json]
|
18
|
+
return display "No Projects" if projects.nil? || projects.empty?
|
19
|
+
projects_table = table do |t|
|
20
|
+
t.headings = 'Name', 'Runtime', 'Framework', 'GitUrl', 'Description'
|
21
|
+
projects.each do |project|
|
22
|
+
t << [project[:name], project[:runtime] ,project[:framework], project[:gitUrl],project[:description]]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
display projects_table
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_project(projectname=nil)
|
29
|
+
unless projectname
|
30
|
+
loop{
|
31
|
+
projectname = ask("Project Name: ")
|
32
|
+
err "Project Name required." if projectname.nil? || projectname.empty?
|
33
|
+
if project_exists?(projectname)
|
34
|
+
display "Project '#{projectname}' already exists."
|
35
|
+
projectname =nil
|
36
|
+
next
|
37
|
+
else
|
38
|
+
break
|
39
|
+
end
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
runtime = nil
|
44
|
+
runtimes = client.runtimes
|
45
|
+
choose do |menu|
|
46
|
+
display "=============Runtime============"
|
47
|
+
menu.prompt = "Select Runtime: "
|
48
|
+
menu.select_by = :index_or_name
|
49
|
+
runtimes.each do |rt|
|
50
|
+
menu.choice(rt) { runtime = rt }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
display "Selected Runtime: ",false
|
54
|
+
display "#{runtime}".green
|
55
|
+
|
56
|
+
framework = nil
|
57
|
+
frameworks = client.frameworks(runtime)
|
58
|
+
err "No Frameworks" if frameworks.nil? || frameworks.empty?
|
59
|
+
choose do |menu|
|
60
|
+
display "=============Frameworks============"
|
61
|
+
menu.prompt = "Select Framework: "
|
62
|
+
menu.select_by = :index_or_name
|
63
|
+
frameworks.each do |fk|
|
64
|
+
menu.choice(fk) { framework = fk }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
display "Selected Framework: ",false
|
68
|
+
display "#{framework}".green
|
69
|
+
|
70
|
+
description = ask("Please enter in the description: ")
|
71
|
+
manifest = {
|
72
|
+
:name => "#{projectname}",
|
73
|
+
:runtime => "#{runtime}",
|
74
|
+
:framework => "#{framework}",
|
75
|
+
:description => "#{description}"
|
76
|
+
}
|
77
|
+
|
78
|
+
display "Creating project #{projectname}: ",false
|
79
|
+
client.create_project(projectname, manifest)
|
80
|
+
display "OK".green
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete_project(projectname=nil)
|
84
|
+
unless projectname
|
85
|
+
projects = client.projects
|
86
|
+
err "No Projects" if projects.nil? || projects.empty?
|
87
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
88
|
+
choose do |menu|
|
89
|
+
display "=============Project Name======="
|
90
|
+
menu.prompt = "Select Project: "
|
91
|
+
menu.select_by = :index_or_name
|
92
|
+
projects.each do |project|
|
93
|
+
menu.choice(project[:name]) { projectname = project[:name] }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
display "Selected Project: ",false
|
97
|
+
display "#{projectname}".green
|
98
|
+
end
|
99
|
+
display "Deleting project [#{projectname}]: ", false
|
100
|
+
client.delete_project(projectname)
|
101
|
+
display 'OK'.green
|
102
|
+
end
|
103
|
+
|
104
|
+
def upload(projectname=nil)
|
105
|
+
file = nil
|
106
|
+
unless projectname
|
107
|
+
projects = client.projects
|
108
|
+
err "No Projects" if projects.nil? || projects.empty?
|
109
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
110
|
+
choose do |menu|
|
111
|
+
display "=============Project Name======="
|
112
|
+
menu.prompt = "Select Project: "
|
113
|
+
menu.select_by = :index_or_name
|
114
|
+
projects.each do |project|
|
115
|
+
menu.choice(project[:name]) { projectname = project[:name] }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
display "Selected Project: ",false
|
119
|
+
display "#{projectname}".green
|
120
|
+
end
|
121
|
+
description = ask("Please enter in the description: ")
|
122
|
+
version = ask("Please enter the version: ")
|
123
|
+
|
124
|
+
path = nil
|
125
|
+
loop{
|
126
|
+
path = ask("Please enter the path of upload war file: ") do |p|
|
127
|
+
p.validate = /\.(war)$/
|
128
|
+
p.responses[:not_valid] = "Please enter the path of upload war file:"
|
129
|
+
end
|
130
|
+
if not File.exists? path
|
131
|
+
display "Deployment path does not exist!"
|
132
|
+
path =nil
|
133
|
+
next
|
134
|
+
else
|
135
|
+
break
|
136
|
+
end
|
137
|
+
}
|
138
|
+
|
139
|
+
upload_file = File.new(path, 'rb')
|
140
|
+
manifest = {
|
141
|
+
:projectName => "#{projectname}",
|
142
|
+
:fileWAR => upload_file,
|
143
|
+
:versionName => "#{version.downcase}",
|
144
|
+
:description => "#{description}"
|
145
|
+
}
|
146
|
+
display "Uploading ",false
|
147
|
+
client.upload(manifest)
|
148
|
+
display 'OK'.green
|
149
|
+
end
|
150
|
+
|
151
|
+
def project_events(projectname=nil)
|
152
|
+
unless projectname
|
153
|
+
projects = client.projects
|
154
|
+
err "No Projects" if projects.nil? || projects.empty?
|
155
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
156
|
+
choose do |menu|
|
157
|
+
display "=============Project Name======="
|
158
|
+
menu.prompt = "Select Project: "
|
159
|
+
menu.select_by = :index_or_name
|
160
|
+
projects.each do |project|
|
161
|
+
menu.choice(project[:name]) { projectname = project[:name] }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
display "Selected Project: ",false
|
165
|
+
display "#{projectname}".green
|
166
|
+
end
|
167
|
+
events = client.project_events(projectname)
|
168
|
+
return display JSON.pretty_generate(events || []) if @options[:json]
|
169
|
+
return display "No Events." if events.empty?
|
170
|
+
events_table = table do |t|
|
171
|
+
t.headings = 'Target', 'AppName','EventTime', 'EventInfo','EventDetail'
|
172
|
+
events.each do |event|
|
173
|
+
t << [event[:targetName], event[:applicationName], event[:createdAt], event[:eventType], event[:eventDetail]]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
display events_table
|
177
|
+
end
|
178
|
+
|
179
|
+
def project_tags(projectname=nil)
|
180
|
+
unless projectname
|
181
|
+
projects = client.projects
|
182
|
+
err "No Projects" if projects.nil? || projects.empty?
|
183
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
184
|
+
choose do |menu|
|
185
|
+
display "=============Project Name======="
|
186
|
+
menu.prompt = "Select Project: "
|
187
|
+
menu.select_by = :index_or_name
|
188
|
+
projects.each do |project|
|
189
|
+
menu.choice(project[:name]) { projectname = project[:name] }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
display "Selected Project: ",false
|
193
|
+
display "#{projectname}".green
|
194
|
+
end
|
195
|
+
tags ||= client.project_tags(projectname)
|
196
|
+
return display JSON.pretty_generate(tags || []) if @options[:json]
|
197
|
+
return display "No Tags." if tags.size == 0
|
198
|
+
tags_table = table do |t|
|
199
|
+
t.headings = ['Tag']
|
200
|
+
tags.each { |f| t << [f]}
|
201
|
+
end
|
202
|
+
display "\n"
|
203
|
+
display tags_table
|
204
|
+
end
|
205
|
+
|
206
|
+
def project_commits(projectname=nil)
|
207
|
+
unless projectname
|
208
|
+
projects = client.projects
|
209
|
+
err "No Projects" if projects.nil? || projects.empty?
|
210
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
211
|
+
choose do |menu|
|
212
|
+
display "=============Project Name======="
|
213
|
+
menu.prompt = "Select Project: "
|
214
|
+
menu.select_by = :index_or_name
|
215
|
+
projects.each do |project|
|
216
|
+
menu.choice(project[:name]) { projectname = project[:name] }
|
217
|
+
end
|
218
|
+
end
|
219
|
+
display "Selected Project: ",false
|
220
|
+
display "#{projectname}".green
|
221
|
+
end
|
222
|
+
|
223
|
+
tag =nil
|
224
|
+
tags = client.project_tags(projectname)
|
225
|
+
return display JSON.pretty_generate(tags || []) if @options[:json]
|
226
|
+
display "\n"
|
227
|
+
return display "No Commits" if tags.nil? || tags.empty?
|
228
|
+
choose do |menu|
|
229
|
+
display "=============Tag======="
|
230
|
+
menu.prompt = "Select Tag: "
|
231
|
+
menu.select_by = :index_or_name
|
232
|
+
tags.each do |t|
|
233
|
+
menu.choice(t) { tag = t}
|
234
|
+
end
|
235
|
+
end
|
236
|
+
display "Selected Tag: ",false
|
237
|
+
display "#{tag}".green
|
238
|
+
|
239
|
+
commits = client.project_commits(projectname,tag)
|
240
|
+
commits.sort! {|a, b| a[:date] <=> b[:date] }
|
241
|
+
return display JSON.pretty_generate(commits || []) if @options[:json]
|
242
|
+
return display "No Commits" if commits.nil? || commits.empty?
|
243
|
+
commits_table = table do |t|
|
244
|
+
t.headings = 'CommitId', 'Date', 'Comment'
|
245
|
+
commits.each do |commit|
|
246
|
+
t << [commit[:commit], commit[:date], commit[:comment]]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
display commits_table
|
250
|
+
end
|
251
|
+
|
252
|
+
def project_apps(projectname=nil)
|
253
|
+
unless projectname
|
254
|
+
projects = client.projects
|
255
|
+
err "No Projects" if projects.nil? || projects.empty?
|
256
|
+
projects.sort! {|a, b| a[:name] <=> b[:name] }
|
257
|
+
choose do |menu|
|
258
|
+
display "=============Project Name======="
|
259
|
+
menu.prompt = "Select Project: "
|
260
|
+
menu.select_by = :index_or_name
|
261
|
+
projects.each do |project|
|
262
|
+
menu.choice(project[:name]) { projectname = project[:name] }
|
263
|
+
end
|
264
|
+
end
|
265
|
+
display "Selected Project: ",false
|
266
|
+
display "#{projectname}".green
|
267
|
+
end
|
268
|
+
|
269
|
+
apps = client.project_apps(projectname)
|
270
|
+
apps.sort! {|a, b| a[:appname] <=> b[:appname] }
|
271
|
+
return display JSON.pretty_generate(apps || []) if @options[:json]
|
272
|
+
return display "No applications" if apps.nil? || apps.empty?
|
273
|
+
|
274
|
+
apps_table = table do |t|
|
275
|
+
t.headings = 'Target', 'AppName', 'URL', 'Tag', 'Status', 'Instances'
|
276
|
+
apps.each do |app|
|
277
|
+
t << [app[:targetName], app[:appName], app[:url], app[:tag], app[:status], app[:instances]]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
display apps_table
|
281
|
+
end
|
282
|
+
|
283
|
+
private
|
284
|
+
|
285
|
+
def project_exists?(projectname)
|
286
|
+
projects = client.projects
|
287
|
+
projects.each do |project|
|
288
|
+
return true if project[:name] == projectname
|
289
|
+
end
|
290
|
+
return false
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module PI::Cli::Command
|
4
|
+
|
5
|
+
class User < Base
|
6
|
+
|
7
|
+
YES_SET = Set.new(["y", "Y", "yes", "YES"])
|
8
|
+
|
9
|
+
def login(url=nil)
|
10
|
+
unless url
|
11
|
+
url = ask("URL: '#{target_url}'? ")
|
12
|
+
if YES_SET.member?(url)
|
13
|
+
url = "#{target_url}"
|
14
|
+
else if url.empty?
|
15
|
+
url =target_url
|
16
|
+
else
|
17
|
+
url = ask("URL: ")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
url = "#{target_url}" if url.nil? || url.empty?
|
22
|
+
eval("PI::Cli::Command::Misc").new().send("set_target", url)
|
23
|
+
tries ||= 0
|
24
|
+
user = ask("User: ")
|
25
|
+
password = ask("Password: ") {|q| q.echo = '*'}
|
26
|
+
err "Need a valid user" unless user
|
27
|
+
err "Need a password" unless password
|
28
|
+
login_and_save_token(user, password)
|
29
|
+
say "Successfully logged into [#{target_url}]".green
|
30
|
+
rescue PI::Client::TargetError
|
31
|
+
display "Problem with login, invalid account or password.".red
|
32
|
+
retry if (tries += 1) < 3 && !@options[:passwd]
|
33
|
+
exit 1
|
34
|
+
rescue => e
|
35
|
+
display "Problem with login, #{e}, try again or register for an account.".red
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
def logout
|
40
|
+
PI::Cli::Config.remove_token_file
|
41
|
+
say "Successfully logged out of [#{target_url}]".green
|
42
|
+
end
|
43
|
+
|
44
|
+
def info
|
45
|
+
info = client.info
|
46
|
+
return display JSON.pretty_generate(info) if @options[:json]
|
47
|
+
display "\nName: #{info[:name]}"
|
48
|
+
display "Description: #{info[:description]}"
|
49
|
+
display "Build: #{info[:build]}"
|
50
|
+
display "Version: #{info[:version]}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def user
|
54
|
+
user = client.user_info
|
55
|
+
github_info = client.github_info
|
56
|
+
github_info[:name] = "null" if github_info[:name].empty? || github_info[:name].nil?
|
57
|
+
github_info[:email] = "null" if github_info[:email].empty? || github_info[:email].nil?
|
58
|
+
user_merge =user.merge(github_info)
|
59
|
+
return display JSON.pretty_generate(user_merge) if @options[:json]
|
60
|
+
return display 'No user info' if user.empty?
|
61
|
+
display "\nUserName: #{user[:userName]}"
|
62
|
+
display "DomainName: #{user[:domainName]}"
|
63
|
+
display "RoleName: #{user[:roleName]}"
|
64
|
+
display "State: #{user[:state]}"
|
65
|
+
display "Github Account Name: #{github_info[:name]}"
|
66
|
+
display "Github Account Email: #{github_info[:email]}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def targets
|
70
|
+
targets = client.targets
|
71
|
+
return display JSON.pretty_generate(targets) if @options[:json]
|
72
|
+
return display 'No Targets' if targets.empty?
|
73
|
+
targets_table = table do |t|
|
74
|
+
t.headings = 'Name', 'URL'
|
75
|
+
targets.each do |target|
|
76
|
+
t << [target[:name], target[:targetUrl]]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
display "\n"
|
80
|
+
display targets_table
|
81
|
+
end
|
82
|
+
|
83
|
+
def password(newpassword=nil)
|
84
|
+
unless newpassword
|
85
|
+
loop{
|
86
|
+
newpassword = ask("New Password: ") {|q| q.echo = '*'}
|
87
|
+
newpassword2 = ask("Verify Password: ") {|q| q.echo = '*'}
|
88
|
+
if newpassword != newpassword2
|
89
|
+
display "Passwords did not match, try again"
|
90
|
+
newpassword =nil
|
91
|
+
next
|
92
|
+
else
|
93
|
+
break
|
94
|
+
end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
client.password(newpassword)
|
98
|
+
display "ok".green
|
99
|
+
end
|
100
|
+
|
101
|
+
def github
|
102
|
+
name = @options[:name]
|
103
|
+
name = ask("Please input your name: ") unless name
|
104
|
+
email = ask("Please input your email: ")
|
105
|
+
password = ask("Please input your password: ") {|q| q.echo = '*'}
|
106
|
+
manifest = {
|
107
|
+
:name => "#{name}",
|
108
|
+
:password => "#{password}",
|
109
|
+
:email => "#{email}",
|
110
|
+
:passwordBase64 => "#{password}"
|
111
|
+
}
|
112
|
+
github = client.github(manifest)
|
113
|
+
display "ok".green
|
114
|
+
end
|
115
|
+
|
116
|
+
def runtimes
|
117
|
+
runtimes_info = client.runtimes
|
118
|
+
return display JSON.pretty_generate(runtimes_info) if @options[:json]
|
119
|
+
return display "No Runtimes" if runtimes_info.empty?
|
120
|
+
rtable = table do |t|
|
121
|
+
t.headings = ['Name']
|
122
|
+
runtimes_info.each { |rt| t << [rt] }
|
123
|
+
end
|
124
|
+
display "\n"
|
125
|
+
display rtable
|
126
|
+
end
|
127
|
+
|
128
|
+
def frameworks
|
129
|
+
runtimes = client.runtimes
|
130
|
+
java_runtime = runtimes[0].downcase
|
131
|
+
ruby_runtime = runtimes[1].downcase
|
132
|
+
java_frameworks = client.frameworks(java_runtime)
|
133
|
+
ruby_frameworks = client.frameworks(ruby_runtime)
|
134
|
+
frameworks = java_frameworks << ruby_frameworks[0] << ruby_frameworks[1]
|
135
|
+
return display JSON.pretty_generate(frameworks) if @options[:json]
|
136
|
+
return display "No Frameworks" if frameworks.empty?
|
137
|
+
rtable = table do |t|
|
138
|
+
t.headings = ['Name']
|
139
|
+
frameworks.each { |f| t << [f]}
|
140
|
+
end
|
141
|
+
display "\n"
|
142
|
+
display rtable
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def login_and_save_token(user, password)
|
148
|
+
token = client.login(user, password)
|
149
|
+
PI::Cli::Config.store_token(token)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|