opswalrus 1.0.77 → 1.0.78

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c19f0877541baca3fa57340c300382e8819e56d9bfc2225ca1f4a888c0df9fb6
4
- data.tar.gz: 279d36f24ff0861115ca06e4201d907c84082b764f308faceee9c9c4420a2ef2
3
+ metadata.gz: 13215ff324f0411cb258d2bb9228d4e6ab5a99bdab79d81fa13206063f3ab66c
4
+ data.tar.gz: 1ff2f044c230528bd3fa94ee3070380f6b5943bf1d8495bc608460f52128abbc
5
5
  SHA512:
6
- metadata.gz: 54b958066621d691e460702e41388b76c34c3a9cc379f1fe431e52f70509c581a81f8d1a9d7c11ea15f5d5406c5862659534b5c7b18aa086494e0ac3a2b5c564
7
- data.tar.gz: 0771e13131d4db57fdc9f730ed80a286aaaf80409b35cdbdfe2091c0e80b35d321ccba1fbad6c89a6ce28438207330bbd944833618aef762ab42fb6ab7b98641
6
+ metadata.gz: afcaa074c96bf612c7c51c75199ff18d0de8988bbb7037068736533f272f83b39fa18501278586037abfd6c64a49ff41f6c1d344028bc373b4381ab6239f1255
7
+ data.tar.gz: 2d87b71f172c144010f29e625a82d7c10628c11684cc75c9686accc8392b24ff8e4c81f05df8d2ce3ed02497171faacbb59c0821a588563902d5623d4d58ae69
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in opswalrus.gemspec
6
6
  gemspec
7
7
 
8
+ # gem "kleene", path: '../../kleene-rb'
8
9
  gem "rake", "~> 13.0"
9
10
  gem "rspec", "~> 3.0"
10
11
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- opswalrus (1.0.77)
4
+ opswalrus (1.0.78)
5
5
  activesupport (~> 7.0)
6
6
  bcrypt_pbkdf (~> 1.1)
7
7
  binding_of_caller (~> 1.0)
@@ -9,6 +9,7 @@ PATH
9
9
  ed25519 (~> 1.3)
10
10
  git (~> 1.18)
11
11
  gli (~> 2.21)
12
+ kleene
12
13
  pastel (~> 0.8)
13
14
  rubyzip (~> 2.3)
14
15
  semantic_logger (~> 4.13)
@@ -32,9 +33,9 @@ GEM
32
33
  public_suffix (>= 2.0.2, < 6.0)
33
34
  ast (2.4.2)
34
35
  backport (1.2.0)
35
- base64 (0.1.1)
36
+ base64 (0.2.0)
36
37
  bcrypt_pbkdf (1.1.0)
37
- benchmark (0.2.1)
38
+ benchmark (0.3.0)
38
39
  bigdecimal (3.1.4)
39
40
  binding_of_caller (1.0.0)
40
41
  debug_inspector (>= 0.0.1)
@@ -43,7 +44,7 @@ GEM
43
44
  connection_pool (2.4.1)
44
45
  debug_inspector (1.1.0)
45
46
  diff-lcs (1.5.0)
46
- drb (2.1.1)
47
+ drb (2.2.0)
47
48
  ruby2_keywords
48
49
  e2mmap (0.1.0)
49
50
  ed25519 (1.3.0)
@@ -55,13 +56,16 @@ GEM
55
56
  concurrent-ruby (~> 1.0)
56
57
  jaro_winkler (1.5.6)
57
58
  json (2.6.3)
59
+ kleene (0.8.0)
60
+ activesupport (~> 7.1)
61
+ regexp_parser (~> 2.8)
58
62
  kramdown (2.4.0)
59
63
  rexml
60
64
  kramdown-parser-gfm (1.1.0)
61
65
  kramdown (~> 2.0)
62
66
  language_server-protocol (3.17.0.3)
63
67
  minitest (5.20.0)
64
- mutex_m (0.1.2)
68
+ mutex_m (0.2.0)
65
69
  net-scp (4.0.0)
66
70
  net-ssh (>= 2.6.5, < 8.0.0)
67
71
  net-ssh (7.2.0)
@@ -74,7 +78,7 @@ GEM
74
78
  pastel (0.8.0)
75
79
  tty-color (~> 0.5)
76
80
  public_suffix (5.0.3)
77
- racc (1.7.2)
81
+ racc (1.7.3)
78
82
  rainbow (3.1.1)
79
83
  rake (13.1.0)
80
84
  rbs (2.8.4)
data/cli2.rb ADDED
@@ -0,0 +1,88 @@
1
+ require 'tty-option'
2
+
3
+ class Command
4
+ include TTY::Option
5
+
6
+ usage do
7
+ program "dock"
8
+
9
+ command "run"
10
+
11
+ desc "Run a command in a new container"
12
+
13
+ example "Set working directory (-w)",
14
+ " $ dock run -w /path/to/dir/ ubuntu pwd"
15
+
16
+ example <<~EOS
17
+ Mount volume
18
+ $ dock run -v `pwd`:`pwd` -w `pwd` ubuntu pwd
19
+ EOS
20
+ end
21
+
22
+ argument :image do
23
+ required
24
+ desc "The name of the image to use"
25
+ end
26
+
27
+ argument :command do
28
+ optional
29
+ desc "The command to run inside the image"
30
+ end
31
+
32
+ keyword :restart do
33
+ default "no"
34
+ permit %w[no on-failure always unless-stopped]
35
+ desc "Restart policy to apply when a container exits"
36
+ end
37
+
38
+ option :verbose do
39
+ arity "+"
40
+ short "-v"
41
+ desc "Verbose mode"
42
+ end
43
+
44
+ flag :detach do
45
+ short "-d"
46
+ long "--detach"
47
+ desc "Run container in background and print container ID"
48
+ end
49
+
50
+ flag :help do
51
+ short "-h"
52
+ long "--help"
53
+ desc "Print usage"
54
+ end
55
+
56
+ option :name do
57
+ required
58
+ long "--name string"
59
+ desc "Assign a name to the container"
60
+ end
61
+
62
+ option :port do
63
+ arity one_or_more
64
+ short "-p"
65
+ long "--publish list"
66
+ convert :list
67
+ desc "Publish a container's port(s) to the host"
68
+ end
69
+
70
+ def run
71
+ puts params[:verbose].inspect
72
+ if params[:help]
73
+ print help
74
+ elsif params.errors.any?
75
+ puts params.errors.summary
76
+ else
77
+ pp params.to_h
78
+ end
79
+ end
80
+ end
81
+
82
+ def main
83
+ cmd = Command.new
84
+ cmd.parse
85
+ puts cmd.run
86
+ end
87
+
88
+ main
@@ -255,7 +255,7 @@ module OpsWalrus
255
255
  if App.instance.info? # this is true if log_level is trace, debug, info
256
256
  io.print Style.blue(host)
257
257
  io.print " (#{Style.blue(self.alias)})" if self.alias
258
- io.print " | #{Style.magenta(description)}" if description
258
+ io.print " | #{Style.green(description)}" if description
259
259
  io.puts
260
260
  io.print Style.yellow(cmd_id)
261
261
  io.print Style.green.bold(" > ")
@@ -263,7 +263,7 @@ module OpsWalrus
263
263
  elsif App.instance.warn? && description
264
264
  io.print Style.blue(host)
265
265
  io.print " (#{Style.blue(self.alias)})" if self.alias
266
- io.print " | #{Style.magenta(description)}" if description
266
+ io.print " | #{Style.green(description)}" if description
267
267
  io.puts
268
268
  end
269
269
  io.string
@@ -1,3 +1,4 @@
1
+ require 'kleene'
1
2
  require 'sshkit'
2
3
 
3
4
  module OpsWalrus
@@ -8,8 +9,9 @@ module OpsWalrus
8
9
 
9
10
  attr_accessor :input_mappings # Hash[ String | Regex => (String | Proc) ]
10
11
 
11
- def initialize(mapping)
12
- @input_mappings = mapping
12
+ def initialize(mappings, lookback_window_chars = 200)
13
+ @input_mappings = mappings
14
+ @online_matcher = Kleene::NaiveOnlineRegex.new(mappings.keys, lookback_window_chars)
13
15
  end
14
16
 
15
17
  # sudo_password : String | Nil
@@ -40,8 +42,8 @@ module OpsWalrus
40
42
  # when the given block returns, then the temporary mapping is removed from the interaction handler
41
43
  #
42
44
  # mapping : Hash[ String | Regex => (String | Proc) ] | Nil
43
- def with_mapping(mapping = nil, sudo_password: nil, ops_sudo_password: nil, inherit_existing_mappings: true)
44
- new_mapping = inherit_existing_mappings ? @input_mappings : {}
45
+ def with_mapping(mapping = nil, sudo_password: nil, ops_sudo_password: nil, inherit_existing_mappings: true, lookback_window_chars: 200)
46
+ new_mapping = inherit_existing_mappings ? @input_mappings.clone : {}
45
47
 
46
48
  if mapping
47
49
  raise ArgumentError.new("mapping must be a Hash") unless mapping.is_a?(Hash)
@@ -58,19 +60,26 @@ module OpsWalrus
58
60
  end
59
61
  new_mapping.merge!(password_mappings) if password_mappings
60
62
 
63
+ # trace(Style.green("mapping: #{mapping}"))
64
+ # trace(Style.green("new_mapping: #{new_mapping}"))
65
+ # trace(Style.green("new_mapping.empty?: #{new_mapping.empty?}"))
66
+ # trace(Style.green("new_mapping == @input_mappings: #{new_mapping == @input_mappings}"))
61
67
  if new_mapping.empty? || new_mapping == @input_mappings
68
+ trace(Style.red("with_mapping -> reset"))
69
+ @online_matcher.reset
62
70
  yield self
63
71
  else
64
- yield ScopedMappingInteractionHandler.new(new_mapping)
72
+ trace(Style.red("with_mapping -> new mapping"))
73
+ yield ScopedMappingInteractionHandler.new(new_mapping, lookback_window_chars)
65
74
  end
66
75
  end
67
76
 
68
77
  # adds the specified input mapping to the interaction handler
69
78
  #
70
79
  # mapping : Hash[ String | Regex => (String | Proc) ]
71
- def add_mapping(mapping)
72
- @input_mappings.merge!(mapping)
73
- end
80
+ # def add_mapping(mapping)
81
+ # @input_mappings.merge!(mapping)
82
+ # end
74
83
 
75
84
  # cmd, :stdout, data, stdin
76
85
  # the return value from on_data is returned to Command#call_interaction_handler which is then returned verbatim
@@ -84,17 +93,33 @@ module OpsWalrus
84
93
  # This method returns the data that is emitted to the response channel as a result of having processed the output
85
94
  # from a command that the interaction handler was expecting.
86
95
  def on_data(_command, stream_name, data, response_channel)
87
- response_data = @input_mappings.find_map do |pattern, mapped_output_value|
88
- pattern = pattern.is_a?(String) ? Regexp.new(Regexp.escape(pattern)) : pattern
89
- if pattern_match = data.match(pattern) # pattern_match : MatchData | Nil
90
- case mapped_output_value
91
- when Proc, Method
92
- mapped_output_value.call(pattern_match)
93
- when String
94
- mapped_output_value
95
- end
96
+ # trace(Style.yellow("regexen=#{@online_matcher.instance_exec { @regexen } }"))
97
+ # trace(Style.yellow("data=`#{data}`"))
98
+ # trace(Style.yellow("buffer=#{@online_matcher.instance_exec { @buffer } }"))
99
+ new_matches = @online_matcher.ingest(data)
100
+ # trace(Style.yellow("new_matches=`#{new_matches}`"))
101
+ response_data = new_matches.find_map do |online_match|
102
+ mapped_output_value = @input_mappings[online_match.regex]
103
+ case mapped_output_value
104
+ when Proc, Method
105
+ mapped_output_value.call(online_match.match)
106
+ when String
107
+ mapped_output_value
96
108
  end
97
109
  end
110
+ # trace(Style.yellow("response_data=`#{response_data.inspect}`"))
111
+
112
+ # response_data = @input_mappings.find_map do |pattern, mapped_output_value|
113
+ # pattern = pattern.is_a?(String) ? Regexp.new(Regexp.escape(pattern)) : pattern
114
+ # if pattern_match = data.match(pattern) # pattern_match : MatchData | Nil
115
+ # case mapped_output_value
116
+ # when Proc, Method
117
+ # mapped_output_value.call(pattern_match)
118
+ # when String
119
+ # mapped_output_value
120
+ # end
121
+ # end
122
+ # end
98
123
 
99
124
  if response_data.nil?
100
125
  trace(Style.red("No interaction handler mapping for #{stream_name}: `#{data}` so no response was sent"))
@@ -294,7 +294,7 @@ module OpsWalrus
294
294
  if App.instance.dry_run?
295
295
  ["", "", 0]
296
296
  else
297
- sshkit_cmd = @runtime_env.handle_input(input, inherit_existing_mappings: true) do |interaction_handler|
297
+ sshkit_cmd = @runtime_env.handle_input(input, inherit_existing_mappings: true, lookback_window_chars: 200) do |interaction_handler|
298
298
  # puts "self=#{self.class.superclass}"
299
299
  # self is an instance of one of the dynamically defined subclasses of OpsFileScript
300
300
  App.instance.debug("OpsFileScriptDSL#shell! cmd=#{cmd} with input mappings #{interaction_handler.input_mappings.inspect} given input: #{input.inspect})")
@@ -311,14 +311,14 @@ module OpsWalrus
311
311
  output_block = StringIO.open do |io|
312
312
  if App.instance.info? # this is true if log_level is trace, debug, info
313
313
  io.print Style.blue(hostname)
314
- io.print " | #{Style.magenta(description)}" if description
314
+ io.print " | #{Style.green(description)}" if description
315
315
  io.puts
316
316
  io.print Style.yellow(cmd_id)
317
317
  io.print Style.green.bold(" > ")
318
318
  io.puts Style.yellow(cmd)
319
319
  elsif App.instance.warn? && description
320
320
  io.print Style.blue(hostname)
321
- io.print " | #{Style.magenta(description)}" if description
321
+ io.print " | #{Style.green(description)}" if description
322
322
  io.puts
323
323
  end
324
324
  io.string
@@ -267,12 +267,13 @@ module OpsWalrus
267
267
 
268
268
  # input_mapping : Hash[ String | Regex => String ]
269
269
  # sudo_password : String
270
- def handle_input(input_mapping, sudo_password: nil, ops_sudo_password: nil, inherit_existing_mappings: true, &block)
270
+ def handle_input(input_mapping, sudo_password: nil, ops_sudo_password: nil, inherit_existing_mappings: true, lookback_window_chars: 200, &block)
271
271
  @interaction_handler.with_mapping(
272
272
  input_mapping,
273
273
  sudo_password: sudo_password,
274
274
  ops_sudo_password: ops_sudo_password,
275
275
  inherit_existing_mappings: inherit_existing_mappings,
276
+ lookback_window_chars: lookback_window_chars,
276
277
  &block
277
278
  )
278
279
  end
@@ -1,3 +1,3 @@
1
1
  module OpsWalrus
2
- VERSION = "1.0.77"
2
+ VERSION = "1.0.78"
3
3
  end
data/opswalrus.gemspec CHANGED
@@ -44,6 +44,7 @@ Gem::Specification.new do |spec|
44
44
 
45
45
  spec.add_dependency "bcrypt_pbkdf", "~> 1.1"
46
46
  spec.add_dependency "ed25519", "~> 1.3"
47
+ spec.add_dependency "kleene", ">= 0"
47
48
  spec.add_dependency "sshkit", "~> 1.21" # sshkit uses net-ssh, which depends on bcrypt_pbkdf and ed25519 to dynamically add support for ed25519 if those two gems are present
48
49
 
49
50
  # For more information and examples about making a new gem, check out our
data/test.ops ADDED
@@ -0,0 +1,10 @@
1
+ params:
2
+ version: string
3
+
4
+ imports:
5
+ core: "https://github.com/opswalrus/core.git"
6
+
7
+ ...
8
+
9
+ totp = rand(10000)
10
+ sh("Push gem", input: {/You have enabled multi-factor authentication. Please enter OTP code./ => "#{totp}\n"}) { 'ruby test.rb' }
data/test.rb CHANGED
@@ -1,88 +1,3 @@
1
- require 'tty-option'
2
-
3
- class Command
4
- include TTY::Option
5
-
6
- usage do
7
- program "dock"
8
-
9
- command "run"
10
-
11
- desc "Run a command in a new container"
12
-
13
- example "Set working directory (-w)",
14
- " $ dock run -w /path/to/dir/ ubuntu pwd"
15
-
16
- example <<~EOS
17
- Mount volume
18
- $ dock run -v `pwd`:`pwd` -w `pwd` ubuntu pwd
19
- EOS
20
- end
21
-
22
- argument :image do
23
- required
24
- desc "The name of the image to use"
25
- end
26
-
27
- argument :command do
28
- optional
29
- desc "The command to run inside the image"
30
- end
31
-
32
- keyword :restart do
33
- default "no"
34
- permit %w[no on-failure always unless-stopped]
35
- desc "Restart policy to apply when a container exits"
36
- end
37
-
38
- option :verbose do
39
- arity "+"
40
- short "-v"
41
- desc "Verbose mode"
42
- end
43
-
44
- flag :detach do
45
- short "-d"
46
- long "--detach"
47
- desc "Run container in background and print container ID"
48
- end
49
-
50
- flag :help do
51
- short "-h"
52
- long "--help"
53
- desc "Print usage"
54
- end
55
-
56
- option :name do
57
- required
58
- long "--name string"
59
- desc "Assign a name to the container"
60
- end
61
-
62
- option :port do
63
- arity one_or_more
64
- short "-p"
65
- long "--publish list"
66
- convert :list
67
- desc "Publish a container's port(s) to the host"
68
- end
69
-
70
- def run
71
- puts params[:verbose].inspect
72
- if params[:help]
73
- print help
74
- elsif params.errors.any?
75
- puts params.errors.summary
76
- else
77
- pp params.to_h
78
- end
79
- end
80
- end
81
-
82
- def main
83
- cmd = Command.new
84
- cmd.parse
85
- puts cmd.run
86
- end
87
-
88
- main
1
+ puts "You have enabled multi-factor authentication. Please enter OTP code."
2
+ input = gets
3
+ puts "You typed: #{input}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opswalrus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.77
4
+ version: 1.0.78
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Ellis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-02 00:00:00.000000000 Z
11
+ date: 2023-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '1.3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: kleene
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: sshkit
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -196,6 +210,7 @@ files:
196
210
  - README.md
197
211
  - Rakefile
198
212
  - build.ops
213
+ - cli2.rb
199
214
  - exe/ops
200
215
  - lib/opswalrus.rb
201
216
  - lib/opswalrus/_bootstrap.ops
@@ -229,6 +244,7 @@ files:
229
244
  - lib/opswalrus/zip.rb
230
245
  - opswalrus.gemspec
231
246
  - sig/opswalrus.rbs
247
+ - test.ops
232
248
  - test.rb
233
249
  - vms/arch/Vagrantfile
234
250
  - vms/debian/Vagrantfile