smart_proxy_remote_execution_ssh 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/smart_proxy_remote_execution_ssh/actions/pull_script.rb +48 -16
- data/lib/smart_proxy_remote_execution_ssh/api.rb +8 -0
- data/lib/smart_proxy_remote_execution_ssh/multiplexed_ssh_connection.rb +2 -0
- data/lib/smart_proxy_remote_execution_ssh/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: debc9989aade4d23bda1b90e9fa8e85c99948f5b9ca37d6cecca7573bb994e5e
|
4
|
+
data.tar.gz: 38a2731c7f28643daaa33ddd29f93172b7467877f36b12c750b82f86e921c04d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3f5776ce0f6ad361f2c344d0ff5d5cef9b6b032e23dc42ae0e877298abd9e95c0156c77334b106036f376e62c60c01ab13344d6bda53baa52c93c7caba79b71
|
7
|
+
data.tar.gz: d1de077038e5fce86df1871e4702e2abb4c7de4937f66aa8730803bb4542aa8f26c1c848d24bb74db1ce5594514d3a552b92b7ad315d346ead5e7586cb20da20
|
@@ -4,9 +4,20 @@ require 'time'
|
|
4
4
|
|
5
5
|
module Proxy::RemoteExecution::Ssh::Actions
|
6
6
|
class PullScript < Proxy::Dynflow::Action::Runner
|
7
|
+
include ::Dynflow::Action::Timeouts
|
8
|
+
|
7
9
|
JobDelivered = Class.new
|
8
10
|
PickupTimeout = Class.new
|
9
11
|
|
12
|
+
# The proxy has the job stored in its job storage
|
13
|
+
READY_FOR_PICKUP = 'ready_for_pickup'
|
14
|
+
# The host was notified over MQTT at least once
|
15
|
+
NOTIFIED = 'notified'
|
16
|
+
# The host has picked up the job
|
17
|
+
DELIVERED = 'delivered'
|
18
|
+
# We received at least one output from the host
|
19
|
+
RUNNING = 'running'
|
20
|
+
|
10
21
|
execution_plan_hooks.use :cleanup, :on => :stopped
|
11
22
|
|
12
23
|
def plan(action_input, mqtt: false)
|
@@ -16,14 +27,22 @@ module Proxy::RemoteExecution::Ssh::Actions
|
|
16
27
|
|
17
28
|
def run(event = nil)
|
18
29
|
if event == JobDelivered
|
19
|
-
output[:state] =
|
30
|
+
output[:state] = DELIVERED
|
20
31
|
suspend
|
21
32
|
elsif event == PickupTimeout
|
22
33
|
process_pickup_timeout
|
34
|
+
elsif event == ::Dynflow::Action::Timeouts::Timeout
|
35
|
+
process_timeout
|
36
|
+
elsif event.nil?
|
37
|
+
if (timeout = input['execution_timeout_interval'])
|
38
|
+
schedule_timeout(timeout, optional: true)
|
39
|
+
end
|
40
|
+
super
|
23
41
|
else
|
24
42
|
super
|
25
43
|
end
|
26
44
|
rescue => e
|
45
|
+
cleanup
|
27
46
|
action_logger.error(e)
|
28
47
|
process_update(Proxy::Dynflow::Runner::Update.encode_exception('Proxy error', e))
|
29
48
|
end
|
@@ -36,7 +55,7 @@ module Proxy::RemoteExecution::Ssh::Actions
|
|
36
55
|
plan_event(PickupTimeout, input[:time_to_pickup], optional: true) if input[:time_to_pickup]
|
37
56
|
|
38
57
|
input[:job_uuid] = job_storage.store_job(host_name, execution_plan_id, run_step_id, input[:script].tr("\r", ''), effective_user: input[:effective_user])
|
39
|
-
output[:state] =
|
58
|
+
output[:state] = READY_FOR_PICKUP
|
40
59
|
output[:result] = []
|
41
60
|
|
42
61
|
mqtt_start(otp_password) if input[:with_mqtt]
|
@@ -50,7 +69,7 @@ module Proxy::RemoteExecution::Ssh::Actions
|
|
50
69
|
end
|
51
70
|
|
52
71
|
def process_external_event(event)
|
53
|
-
output[:state] =
|
72
|
+
output[:state] = RUNNING
|
54
73
|
data = event.data
|
55
74
|
case data['version']
|
56
75
|
when nil
|
@@ -89,19 +108,34 @@ module Proxy::RemoteExecution::Ssh::Actions
|
|
89
108
|
process_update(Proxy::Dynflow::Runner::Update.new(continuous_output, exit_code))
|
90
109
|
end
|
91
110
|
|
92
|
-
def
|
111
|
+
def process_timeout
|
112
|
+
kill_run "Execution timeout exceeded"
|
113
|
+
end
|
114
|
+
|
115
|
+
def kill_run(fail_msg = 'The job was cancelled by the user')
|
116
|
+
continuous_output = Proxy::Dynflow::ContinuousOutput.new
|
117
|
+
exit_code = nil
|
118
|
+
|
93
119
|
case output[:state]
|
94
|
-
when
|
120
|
+
when READY_FOR_PICKUP, NOTIFIED
|
95
121
|
# If the job is not running yet on the client, wipe it from storage
|
96
122
|
cleanup
|
97
|
-
|
98
|
-
when
|
123
|
+
exit_code = 'EXCEPTION'
|
124
|
+
when DELIVERED, RUNNING
|
99
125
|
# Client was notified or is already running, dealing with this situation
|
100
126
|
# is only supported if mqtt is available
|
101
127
|
# Otherwise we have to wait it out
|
102
|
-
|
128
|
+
if input[:with_mqtt]
|
129
|
+
mqtt_cancel
|
130
|
+
fail_msg += ', notifying the host over MQTT'
|
131
|
+
else
|
132
|
+
fail_msg += ', however the job was triggered without MQTT and cannot be stopped'
|
133
|
+
end
|
103
134
|
end
|
104
|
-
|
135
|
+
continuous_output.add_output(fail_msg + "\n")
|
136
|
+
process_update(Proxy::Dynflow::Runner::Update.new(continuous_output, exit_code))
|
137
|
+
|
138
|
+
suspend unless exit_code
|
105
139
|
end
|
106
140
|
|
107
141
|
def mqtt_start(otp_password)
|
@@ -118,12 +152,12 @@ module Proxy::RemoteExecution::Ssh::Actions
|
|
118
152
|
},
|
119
153
|
)
|
120
154
|
Proxy::RemoteExecution::Ssh::MQTT::Dispatcher.instance.new(input[:job_uuid], mqtt_topic, payload)
|
121
|
-
output[:state] =
|
155
|
+
output[:state] = NOTIFIED
|
122
156
|
end
|
123
157
|
|
124
158
|
def mqtt_cancel
|
125
|
-
cleanup
|
126
159
|
payload = mqtt_payload_base.merge(
|
160
|
+
content: "#{input[:proxy_url]}/ssh/jobs/#{input[:job_uuid]}/cancel",
|
127
161
|
metadata: {
|
128
162
|
'event': 'cancel',
|
129
163
|
'job_uuid': input[:job_uuid]
|
@@ -163,11 +197,9 @@ module Proxy::RemoteExecution::Ssh::Actions
|
|
163
197
|
end
|
164
198
|
|
165
199
|
def process_pickup_timeout
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
suspend
|
170
|
-
end
|
200
|
+
suspend unless [READY_FOR_PICKUP, NOTIFIED].include? output[:state]
|
201
|
+
|
202
|
+
kill_run 'The job was not picked up in time'
|
171
203
|
end
|
172
204
|
end
|
173
205
|
end
|
@@ -71,6 +71,14 @@ module Proxy::RemoteExecution
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
get "/jobs/:job_uuid/cancel" do |job_uuid|
|
75
|
+
do_authorize_with_ssl_client
|
76
|
+
|
77
|
+
with_authorized_job(job_uuid) do |job_record|
|
78
|
+
{}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
74
82
|
private
|
75
83
|
|
76
84
|
def notify_job(job_record, event)
|
@@ -154,6 +154,8 @@ module Proxy::RemoteExecution::Ssh::Runners
|
|
154
154
|
ssh_options << "-o ControlPath=#{socket_file}"
|
155
155
|
ssh_options << "-o ControlPersist=yes"
|
156
156
|
ssh_options << "-o ProxyCommand=none"
|
157
|
+
ssh_options << "-o ServerAliveInterval=15"
|
158
|
+
ssh_options << "-o ServerAliveCountMax=3" # This is the default, but let's be explicit
|
157
159
|
@establish_ssh_options = ssh_options
|
158
160
|
end
|
159
161
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_remote_execution_ssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Nečas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|