pytty 0.4.0 → 0.4.1
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 +4 -4
- data/Gemfile.lock +1 -1
- data/build/linux.sh +1 -1
- data/lib/pytty/client/api/attach.rb +11 -7
- data/lib/pytty/client/api/yield.rb +1 -1
- data/lib/pytty/client/cli.rb +7 -5
- data/lib/pytty/client/cli/ps_command.rb +1 -1
- data/lib/pytty/client/cli/root_command.rb +0 -2
- data/lib/pytty/client/cli/run_command.rb +6 -2
- data/lib/pytty/client/cli/yield_command.rb +9 -4
- data/lib/pytty/client/process_yield.rb +5 -2
- data/lib/pytty/daemon.rb +0 -3
- data/lib/pytty/daemon/api/router.rb +6 -5
- data/lib/pytty/daemon/api/server.rb +1 -1
- data/lib/pytty/daemon/cli/serve_command.rb +18 -2
- data/lib/pytty/daemon/components/handler.rb +8 -5
- data/lib/pytty/daemon/process_yield.rb +19 -11
- data/lib/pytty/version.rb +1 -1
- metadata +1 -2
- data/lib/pytty/client/cli/kill_command.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdb07fa81c4837ef64e8bffa9abaed4abdb6b99caeff476a7d4b11b2b36be8f1
|
4
|
+
data.tar.gz: 979f05736d9f1ab607edf33371c6a3f1ffadcdd60ca05c8d6d57af2a401e1808
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 691018ead4ca0970d5ba99006e2931aa7da6b6d116adf6e2d041282c22d24f67985a0eb581659d82bb991c8f64e22b31f9bee6733b02de4fb54ca70187f0f791
|
7
|
+
data.tar.gz: 5c9c8a5cbea5e16a36332b3aab35f02472322b474d075bf923dd671c6d56f49a78677c6d77370f77eb80388ae1cfa0ffb8148232178433b201cd4e3da010e625
|
data/Gemfile.lock
CHANGED
data/build/linux.sh
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "io/console"
|
2
|
+
|
1
3
|
module Pytty
|
2
4
|
module Client
|
3
5
|
module Api
|
@@ -8,17 +10,19 @@ module Pytty
|
|
8
10
|
headers = [['accept', 'application/json']]
|
9
11
|
body = {}.to_json
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
# stdin_body = {
|
14
|
+
# c: '\f'
|
15
|
+
# }.to_json
|
16
|
+
# response = internet.post("#{Pytty::Client.host_url}/v1/stdin/#{id}", headers, [stdin_body])
|
17
|
+
|
18
|
+
if interactive
|
19
|
+
$stdin.raw!
|
20
|
+
$stdin.echo = false
|
21
|
+
end
|
13
22
|
async_stdin = Async::IO::Stream.new(
|
14
23
|
Async::IO::Generic.new($stdin)
|
15
24
|
)
|
16
25
|
|
17
|
-
stdin_body = {
|
18
|
-
c: "\f"
|
19
|
-
}.to_json
|
20
|
-
response = internet.post("#{Pytty::Client.host_url}/v1/stdin/#{id}", headers, [stdin_body])
|
21
|
-
|
22
26
|
detach_sequence_started = false
|
23
27
|
while c = async_stdin.read(1) do
|
24
28
|
detach = false
|
data/lib/pytty/client/cli.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
require "clamp"
|
2
2
|
|
3
3
|
require_relative "../common/cli/version_command"
|
4
|
-
|
5
|
-
require_relative "cli/stream_command"
|
6
|
-
require_relative "cli/yield_command"
|
4
|
+
|
7
5
|
require_relative "cli/ps_command"
|
8
|
-
|
9
|
-
require_relative "cli/
|
6
|
+
|
7
|
+
require_relative "cli/yield_command"
|
10
8
|
require_relative "cli/spawn_command"
|
9
|
+
|
10
|
+
require_relative "cli/rm_command"
|
11
11
|
require_relative "cli/signal_command"
|
12
12
|
require_relative "cli/attach_command"
|
13
13
|
require_relative "cli/stdout_command"
|
14
14
|
|
15
|
+
require_relative "cli/run_command"
|
16
|
+
|
15
17
|
require_relative "cli/root_command"
|
@@ -13,10 +13,8 @@ module Pytty
|
|
13
13
|
|
14
14
|
subcommand ["version"], "Show version information", Pytty::Common::Cli::VersionCommand
|
15
15
|
subcommand ["run"], "run", RunCommand
|
16
|
-
subcommand ["stream"], "stream", StreamCommand
|
17
16
|
subcommand ["yield"], "yield", YieldCommand
|
18
17
|
subcommand ["ps"], "ps", PsCommand
|
19
|
-
subcommand ["kill"], "kill", KillCommand
|
20
18
|
subcommand ["rm"], "rm", RmCommand
|
21
19
|
subcommand ["spawn"], "spawn", SpawnCommand
|
22
20
|
subcommand ["signal"], "signal", SignalCommand
|
@@ -16,8 +16,12 @@ module Pytty
|
|
16
16
|
|
17
17
|
def execute
|
18
18
|
Async.run do |task|
|
19
|
-
|
20
|
-
|
19
|
+
response, body = Pytty::Client::Api::Yield.run id: name, cmd: cmd_list, env: {}
|
20
|
+
unless response.status == 200
|
21
|
+
puts body
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
process_yield = Pytty::Client::ProcessYield.from_json body
|
21
25
|
unless detach?
|
22
26
|
task.async do
|
23
27
|
process_yield.attach interactive: interactive?
|
@@ -12,12 +12,17 @@ module Pytty
|
|
12
12
|
option ["--name"], "NAME", "name"
|
13
13
|
|
14
14
|
def execute
|
15
|
-
|
16
|
-
|
17
|
-
::Pytty::Client::ProcessYield.from_json json
|
15
|
+
response, json = Async.run do
|
16
|
+
Pytty::Client::Api::Yield.run cmd: cmd_list, id: name, env: {}
|
18
17
|
end.wait
|
19
18
|
|
20
|
-
|
19
|
+
if response.status == 200
|
20
|
+
process_yield = ::Pytty::Client::ProcessYield.from_json json
|
21
|
+
puts process_yield.id
|
22
|
+
else
|
23
|
+
puts json
|
24
|
+
end
|
25
|
+
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module Pytty
|
2
2
|
module Client
|
3
3
|
class ProcessYield
|
4
|
-
def initialize(id:, cmd:, env:, pid:)
|
4
|
+
def initialize(id:, cmd:, env:, pid:, status:)
|
5
5
|
@cmd = cmd
|
6
6
|
@env = env
|
7
7
|
@pid = pid
|
8
8
|
@id = id
|
9
|
+
@status = status
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_reader :id
|
@@ -15,7 +16,8 @@ module Pytty
|
|
15
16
|
id: json.fetch("id"),
|
16
17
|
cmd: json.fetch("cmd"),
|
17
18
|
env: json.fetch("env"),
|
18
|
-
pid: json.fetch("pid")
|
19
|
+
pid: json.fetch("pid"),
|
20
|
+
status: json.fetch("status")
|
19
21
|
})
|
20
22
|
end
|
21
23
|
def running?
|
@@ -25,6 +27,7 @@ module Pytty
|
|
25
27
|
fields = []
|
26
28
|
fields << @id
|
27
29
|
fields << running?
|
30
|
+
fields << @status
|
28
31
|
fields << @cmd.join(" ")
|
29
32
|
fields.join("\t")
|
30
33
|
end
|
data/lib/pytty/daemon.rb
CHANGED
@@ -21,11 +21,8 @@ module Pytty
|
|
21
21
|
objs.each do |k,obj|
|
22
22
|
process_yield = ProcessYield.new obj["cmd"], id: obj["id"], env: obj["env"]
|
23
23
|
@@yields[obj["id"]] = process_yield
|
24
|
-
print "spawning #{process_yield.cmd} ... "
|
25
24
|
process_yield.spawn if obj["running"]
|
26
|
-
puts "done"
|
27
25
|
end
|
28
|
-
|
29
26
|
end
|
30
27
|
|
31
28
|
def self.pytty_path
|
@@ -29,24 +29,25 @@ module Pytty
|
|
29
29
|
rescue Exception => ex
|
30
30
|
p ex
|
31
31
|
ensure
|
32
|
-
puts "closing body"
|
33
32
|
body.close
|
34
33
|
end
|
35
34
|
|
36
35
|
[200, {'content-type' => 'text/html; charset=utf-8'}, body]
|
37
36
|
when "attach"
|
38
37
|
process_yield = Pytty::Daemon.yields[params["id"]]
|
38
|
+
return [404, {'content-type' => 'text/html; charset=utf-8'}, ["does not exist"]] unless process_yield
|
39
|
+
|
40
|
+
puts "got attach: #{req.object_id}"
|
39
41
|
body = Async::HTTP::Body::Writable.new
|
40
42
|
|
41
43
|
Async::Task.current.async do |task|
|
42
44
|
notification = process_yield.add_stdout body
|
43
|
-
p ["blocking", notification]
|
44
45
|
notification.wait
|
45
|
-
p "got notification"
|
46
46
|
rescue Exception => ex
|
47
|
-
|
47
|
+
puts "----"
|
48
|
+
p ["attach", ex]
|
48
49
|
ensure
|
49
|
-
puts "closing
|
50
|
+
puts "closing attach: #{req.object_id}"
|
50
51
|
body.close
|
51
52
|
end
|
52
53
|
|
@@ -25,9 +25,25 @@ module Pytty
|
|
25
25
|
"1234"
|
26
26
|
end
|
27
27
|
|
28
|
-
Async::Reactor.run do
|
28
|
+
Async::Reactor.run do |task|
|
29
29
|
Pytty::Daemon.load
|
30
|
-
|
30
|
+
server_task = task.async do
|
31
|
+
Pytty::Daemon::Api::Server.run url: url_parts.join("")
|
32
|
+
end
|
33
|
+
|
34
|
+
shutdown = lambda do |signo|
|
35
|
+
puts "\r"
|
36
|
+
puts "Got: #{Signal.signame(signo)}"
|
37
|
+
server_task.stop
|
38
|
+
Pytty::Daemon.yields.each do |id,process_yield|
|
39
|
+
process_yield.signal "kill"
|
40
|
+
puts id
|
41
|
+
end
|
42
|
+
puts "bye."
|
43
|
+
end
|
44
|
+
|
45
|
+
Signal.trap "INT", shutdown
|
46
|
+
Signal.trap "TERM", shutdown
|
31
47
|
end
|
32
48
|
end
|
33
49
|
end
|
@@ -17,11 +17,14 @@ module Pytty
|
|
17
17
|
env = params.dig "env"
|
18
18
|
id = params.dig "id"
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
if Pytty::Daemon.yields[id]
|
21
|
+
[500, "already exists"]
|
22
|
+
else
|
23
|
+
process_yield = Pytty::Daemon::ProcessYield.new cmd, id: id, env: env
|
24
|
+
Pytty::Daemon.yields[process_yield.id] = process_yield
|
25
|
+
Pytty::Daemon.dump
|
26
|
+
[200, process_yield]
|
27
|
+
end
|
25
28
|
else
|
26
29
|
raise "unknown: #{component}"
|
27
30
|
end
|
@@ -44,6 +44,7 @@ module Pytty
|
|
44
44
|
|
45
45
|
def spawn
|
46
46
|
return false if running?
|
47
|
+
@status = nil
|
47
48
|
|
48
49
|
executable, args = @cmd
|
49
50
|
# @env.merge!({
|
@@ -59,8 +60,6 @@ module Pytty
|
|
59
60
|
File.open stdout_path, "r"
|
60
61
|
)
|
61
62
|
Async::Task.current.async do |task|
|
62
|
-
p ["spawn", executable, args, @env]
|
63
|
-
|
64
63
|
real_stdout, real_stdin, pid = PTY.spawn @env, executable, *args
|
65
64
|
@pid = pid
|
66
65
|
async_stdout = Async::IO::Generic.new real_stdout
|
@@ -70,6 +69,7 @@ module Pytty
|
|
70
69
|
while c = @stdin.dequeue do
|
71
70
|
async_stdin.write c
|
72
71
|
end
|
72
|
+
rescue Async::Stop => ex
|
73
73
|
rescue Exception => ex
|
74
74
|
puts "async_stdin.write: #{ex.inspect}"
|
75
75
|
end
|
@@ -78,40 +78,48 @@ module Pytty
|
|
78
78
|
while c = async_stdout.read(1)
|
79
79
|
stdout_appender.write c
|
80
80
|
stdout_appender.flush
|
81
|
+
|
81
82
|
@stdouts.each do |notification, stdout|
|
82
83
|
begin
|
83
84
|
stdout.write c
|
84
|
-
rescue Errno::EPIPE => ex
|
85
|
+
rescue Errno::EPIPE, Errno::EPROTOTYPE => ex
|
85
86
|
notification.signal
|
86
87
|
@stdouts.delete notification
|
87
88
|
end
|
88
89
|
end
|
89
90
|
end
|
91
|
+
rescue Async::Stop
|
92
|
+
signal "kill"
|
93
|
+
rescue Exception => ex
|
94
|
+
p ["async_stdout.read", ex]
|
90
95
|
ensure
|
91
96
|
task_stdin_writer.stop
|
92
97
|
Process.wait(@pid)
|
93
|
-
@status = $?.exitstatus
|
98
|
+
@status = if $?.exitstatus
|
99
|
+
$?.exitstatus
|
100
|
+
else
|
101
|
+
Signal.signame $?.termsig
|
102
|
+
end
|
103
|
+
puts "exited #{@id} with status: #{@status}"
|
104
|
+
|
94
105
|
@pid = nil
|
95
106
|
stdout_appender.close
|
96
107
|
|
97
108
|
@stdouts.each do |notification, stdout|
|
98
|
-
p ["notifying: #{notification}"]
|
99
109
|
notification.signal
|
100
110
|
@stdouts.delete notification
|
101
111
|
end
|
102
|
-
|
112
|
+
Pytty::Daemon.dump
|
103
113
|
end
|
104
114
|
end.wait
|
105
115
|
|
106
|
-
puts "spawned"
|
107
|
-
p ["@stdouts", @stdouts]
|
116
|
+
puts "spawned #{id}"
|
108
117
|
return true
|
109
118
|
end
|
110
119
|
|
111
120
|
def signal(sig)
|
112
|
-
|
113
|
-
|
114
|
-
Process.kill(sig_upcased, @pid)
|
121
|
+
return unless @pid
|
122
|
+
Process.kill(sig.upcase, @pid)
|
115
123
|
end
|
116
124
|
end
|
117
125
|
end
|
data/lib/pytty/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pytty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matti Paksula
|
@@ -197,7 +197,6 @@ files:
|
|
197
197
|
- lib/pytty/client/api/yield.rb
|
198
198
|
- lib/pytty/client/cli.rb
|
199
199
|
- lib/pytty/client/cli/attach_command.rb
|
200
|
-
- lib/pytty/client/cli/kill_command.rb
|
201
200
|
- lib/pytty/client/cli/ps_command.rb
|
202
201
|
- lib/pytty/client/cli/rm_command.rb
|
203
202
|
- lib/pytty/client/cli/root_command.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'async'
|
3
|
-
require 'async/http'
|
4
|
-
require 'async/http/internet'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
module Pytty
|
8
|
-
module Client
|
9
|
-
module Cli
|
10
|
-
class KillCommand < Clamp::Command
|
11
|
-
parameter "ID ...", "id"
|
12
|
-
|
13
|
-
def execute
|
14
|
-
Async.run do
|
15
|
-
internet = Async::HTTP::Internet.new
|
16
|
-
headers = [['accept', 'application/json']]
|
17
|
-
body = {
|
18
|
-
signal: "KILL"
|
19
|
-
}.to_json
|
20
|
-
|
21
|
-
for id in id_list do
|
22
|
-
response = internet.post("#{Pytty::Client.host_url}/v1/signal/#{id}", headers, [body])
|
23
|
-
puts response.read
|
24
|
-
end
|
25
|
-
ensure
|
26
|
-
internet.close
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|