kommando 0.0.22 → 0.1.0
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/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +14 -2
- data/CHANGELOG.md +11 -0
- data/README.md +9 -0
- data/bin/autotest +6 -0
- data/bin/e2e +1 -1
- data/bin/matrix +35 -0
- data/bin/release +2 -1
- data/demos/ping_monitor.rb +19 -0
- data/docker-compose.yml +27 -0
- data/docker/Dockerfile.alpine +14 -0
- data/docker/Dockerfile.alpine-2.1 +14 -0
- data/docker/Dockerfile.alpine-2.2 +14 -0
- data/docker/Dockerfile.alpine-2.3 +14 -0
- data/docker/Dockerfile.debian +13 -0
- data/docker/entrypoint.sh +6 -0
- data/examples/every.rb +23 -0
- data/examples/every_ping.rb +15 -0
- data/examples/k_visibility.rb +15 -0
- data/examples/kill.rb +1 -1
- data/examples/live_output.rb +1 -1
- data/examples/nano.rb +1 -1
- data/examples/nano_match.rb +1 -1
- data/examples/out_once.rb +21 -0
- data/examples/out_once_chaining.rb +29 -0
- data/examples/stdout_to_file.rb +2 -2
- data/examples/timeout.rb +2 -2
- data/examples/when_chaining.rb +15 -0
- data/kommando.gemspec +4 -1
- data/lib/kommando.rb +20 -44
- data/lib/kommando/matchers.rb +6 -0
- data/lib/kommando/matchers/base.rb +31 -0
- data/lib/kommando/matchers/every.rb +16 -0
- data/lib/kommando/matchers/once.rb +5 -0
- data/lib/kommando/stdin.rb +22 -0
- data/lib/kommando/stdout.rb +61 -0
- data/lib/kommando/version.rb +1 -1
- metadata +39 -4
- data/lib/kommando/buffer.rb +0 -36
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 06f39743982905083dccf326b8edd83f882cefa4
|
|
4
|
+
data.tar.gz: f7eb8a290c764606b716c2b15a451179502eb716
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c913d9b57655dfd1768c682cba99f0f0109c8cad22d2eff6a024c68c1b85e75672fab5449295f4ce9cfee0917994507f76bf338ecfdcbc21e79cd3aa3b523814
|
|
7
|
+
data.tar.gz: 2fead68560757c6bad67aa22d663fa59cce61587bab9b52ed7e01f7ea6b71d379c468e230f0549bbe5e7c2963ab5eeac1cf1668aa492c6648e74b2811ccd859f
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.4.1
|
data/.travis.yml
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
dist: trusty
|
|
1
2
|
language: ruby
|
|
2
3
|
rvm:
|
|
3
|
-
- 2.
|
|
4
|
-
|
|
4
|
+
- 2.4
|
|
5
|
+
- 2.3
|
|
6
|
+
- 2.2
|
|
7
|
+
- 2.1
|
|
8
|
+
before_install:
|
|
9
|
+
- sudo apt-get update -qq
|
|
10
|
+
- sudo apt-get install -yqq nano
|
|
11
|
+
- gem install bundler
|
|
12
|
+
install:
|
|
13
|
+
- bundle
|
|
14
|
+
script:
|
|
15
|
+
- rake
|
|
16
|
+
- bin/e2e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
- DOCS: `demos/ping_monitor.rb`
|
|
5
|
+
- FEAT: `k.out.once` can chain `k.out.every` (`k.out.once(/smth/).every(/aftersmth/)`
|
|
6
|
+
- FEAT: `k.out.every` can chain `k.out.once` (`k.out.every(/smth/).once(/aftersmth/)`
|
|
7
|
+
- FEAT: MatchData will be passed as the first argument of the proc on `k.once` and `k.every`
|
|
8
|
+
- FEAT: `k.out.every` matching with chaining
|
|
9
|
+
- FEAT: `k.out.once` matching with chaining (will deprecate `k.on`)
|
|
10
|
+
- FEAT: Ruby 2.1 compatibility
|
|
11
|
+
- FEAT: `k.when` returns `k` so when's can be defined as a chain
|
|
12
|
+
- FIX: Ruby 2.4 Fixnum deprecation warning
|
|
13
|
+
|
|
3
14
|
## 0.0.22
|
|
4
15
|
- FEAT: Global whens with `Kommando.when :timeout block` and clearing with `Kommando.when = nil`
|
|
5
16
|
- FEAT: Context available with `k.when :timeout do |kontextual_k|` and `Kommando.when :timeout |kontextual_k|`
|
data/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Kommando
|
|
2
|
+
[](https://travis-ci.org/matti/kommando)
|
|
2
3
|
|
|
3
4
|
Command runner with expect-like features. Great for integration testing.
|
|
4
5
|
|
|
@@ -115,6 +116,14 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
115
116
|
|
|
116
117
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bin/release`, which will run all tests, create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
117
118
|
|
|
119
|
+
### Notes
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
RSPEC_PROFILE=each rake spec
|
|
123
|
+
RSPEC_PROFILE=all rake spec
|
|
124
|
+
# --> profiles directory
|
|
125
|
+
```
|
|
126
|
+
|
|
118
127
|
## Contributing
|
|
119
128
|
|
|
120
129
|
Bug reports and pull requests are welcome on GitHub at https://github.com/matti/kommando.
|
data/bin/autotest
ADDED
data/bin/e2e
CHANGED
|
@@ -6,7 +6,7 @@ require 'tempfile'
|
|
|
6
6
|
find_examples = Kommando.new "find examples -type f -name *"
|
|
7
7
|
find_examples.run
|
|
8
8
|
|
|
9
|
-
e2e_output = Tempfile.new
|
|
9
|
+
e2e_output = Tempfile.new "test"
|
|
10
10
|
|
|
11
11
|
for example in find_examples.out.split("\r\n") do
|
|
12
12
|
print "Running #{example} ".ljust(74, ".")
|
data/bin/matrix
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "./lib/kommando"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
docker_compose=YAML.load(File.read("docker-compose.yml"))
|
|
7
|
+
services = docker_compose["services"].keys
|
|
8
|
+
|
|
9
|
+
Kommando.run("docker-compose build", {
|
|
10
|
+
output: true
|
|
11
|
+
}).when(:failed) {
|
|
12
|
+
raise "build failed"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
ks = []
|
|
16
|
+
for service in services
|
|
17
|
+
k = Kommando.new "docker-compose up #{service}"
|
|
18
|
+
k.run_async
|
|
19
|
+
ks << k
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
loop do
|
|
23
|
+
for k in ks do
|
|
24
|
+
cmd=k.instance_variable_get(:@cmd)
|
|
25
|
+
puts "#{cmd} (#{(k.code ? "STOP" : "RUNNING")})"
|
|
26
|
+
|
|
27
|
+
if k.code
|
|
28
|
+
puts k.out
|
|
29
|
+
exit 1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
print "-"*20; puts " #{DateTime.now.to_s}"
|
|
34
|
+
sleep 2
|
|
35
|
+
end
|
data/bin/release
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
k = Kommando.new "ping -i 0.2 127.0.0.1"
|
|
4
|
+
|
|
5
|
+
k.out.every /time=(\d+\.\d+)\s/ do |m|
|
|
6
|
+
time = m[1].to_f
|
|
7
|
+
print "#{time} ".ljust(6)
|
|
8
|
+
puts "x" * (time*300.to_i)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
k.out.once(/^PING.+\n$/).every(/^(.+)\r\n/) do |m|
|
|
12
|
+
unless m[1].start_with? "64 bytes from"
|
|
13
|
+
puts "ERR: unexpected reply: #{m[1]}"
|
|
14
|
+
exit 1
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
k.run
|
data/docker-compose.yml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
version: '2.1'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
alpine:
|
|
5
|
+
build:
|
|
6
|
+
context: .
|
|
7
|
+
dockerfile: docker/Dockerfile.alpine
|
|
8
|
+
|
|
9
|
+
debian:
|
|
10
|
+
build:
|
|
11
|
+
context: .
|
|
12
|
+
dockerfile: docker/Dockerfile.debian
|
|
13
|
+
|
|
14
|
+
alpine-2.1:
|
|
15
|
+
build:
|
|
16
|
+
context: .
|
|
17
|
+
dockerfile: docker/Dockerfile.alpine-2.1
|
|
18
|
+
|
|
19
|
+
alpine-2.2:
|
|
20
|
+
build:
|
|
21
|
+
context: .
|
|
22
|
+
dockerfile: docker/Dockerfile.alpine-2.2
|
|
23
|
+
|
|
24
|
+
alpine-2.3:
|
|
25
|
+
build:
|
|
26
|
+
context: .
|
|
27
|
+
dockerfile: docker/Dockerfile.alpine-2.3
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM ruby:2.4.1-alpine
|
|
2
|
+
|
|
3
|
+
RUN apk add --no-cache \
|
|
4
|
+
git build-base \
|
|
5
|
+
nano bash
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY Gemfile Gemfile.lock kommando.gemspec ./
|
|
10
|
+
COPY lib/kommando/version.rb ./lib/kommando/
|
|
11
|
+
RUN bundle install
|
|
12
|
+
|
|
13
|
+
COPY . .
|
|
14
|
+
ENTRYPOINT docker/entrypoint.sh
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM ruby:2.1-alpine
|
|
2
|
+
|
|
3
|
+
RUN apk add --no-cache \
|
|
4
|
+
git build-base \
|
|
5
|
+
nano bash
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY Gemfile Gemfile.lock kommando.gemspec ./
|
|
10
|
+
COPY lib/kommando/version.rb ./lib/kommando/
|
|
11
|
+
RUN bundle install
|
|
12
|
+
|
|
13
|
+
COPY . .
|
|
14
|
+
ENTRYPOINT docker/entrypoint.sh
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM ruby:2.2-alpine
|
|
2
|
+
|
|
3
|
+
RUN apk add --no-cache \
|
|
4
|
+
git build-base \
|
|
5
|
+
nano bash
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY Gemfile Gemfile.lock kommando.gemspec ./
|
|
10
|
+
COPY lib/kommando/version.rb ./lib/kommando/
|
|
11
|
+
RUN bundle install
|
|
12
|
+
|
|
13
|
+
COPY . .
|
|
14
|
+
ENTRYPOINT docker/entrypoint.sh
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM ruby:2.3-alpine
|
|
2
|
+
|
|
3
|
+
RUN apk add --no-cache \
|
|
4
|
+
git build-base \
|
|
5
|
+
nano bash
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
COPY Gemfile Gemfile.lock kommando.gemspec ./
|
|
10
|
+
COPY lib/kommando/version.rb ./lib/kommando/
|
|
11
|
+
RUN bundle install
|
|
12
|
+
|
|
13
|
+
COPY . .
|
|
14
|
+
ENTRYPOINT docker/entrypoint.sh
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
FROM ruby:2.4.1
|
|
2
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
3
|
+
|
|
4
|
+
RUN apt-get update && apt-get install -y nano
|
|
5
|
+
|
|
6
|
+
WORKDIR /app
|
|
7
|
+
|
|
8
|
+
COPY Gemfile Gemfile.lock kommando.gemspec ./
|
|
9
|
+
COPY lib/kommando/version.rb ./lib/kommando/
|
|
10
|
+
RUN bundle install
|
|
11
|
+
|
|
12
|
+
COPY . .
|
|
13
|
+
ENTRYPOINT docker/entrypoint.sh
|
data/examples/every.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
calls = []
|
|
4
|
+
calls_chained = []
|
|
5
|
+
|
|
6
|
+
k = Kommando.new("$ echo hello hello hello hell", {
|
|
7
|
+
output: false
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
k.out.every("hello") do
|
|
11
|
+
calls << :got_hello
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
k.out.every("hello") do
|
|
15
|
+
calls_chained << :got_hello
|
|
16
|
+
end.every("hell") do
|
|
17
|
+
calls_chained << :got_hell
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
k.run
|
|
21
|
+
|
|
22
|
+
raise "err" unless calls == [:got_hello, :got_hello, :got_hello]
|
|
23
|
+
raise "err chained" unless calls_chained == [:got_hello, :got_hell, :got_hello, :got_hell, :got_hello, :got_hell]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
calls = []
|
|
4
|
+
|
|
5
|
+
k = Kommando.new("ping -c 2 -i 0.2 127.0.0.1", {
|
|
6
|
+
output: false
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
k.out.every(/from (\d+\.\d+\.\d+\.\d+):/) do |m|
|
|
10
|
+
calls << m[1]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
k.run
|
|
14
|
+
|
|
15
|
+
raise "err" unless calls == ["127.0.0.1", "127.0.0.1"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
k_in_when, k_in_out_on = nil, nil
|
|
4
|
+
|
|
5
|
+
k = Kommando.new "$ echo something"
|
|
6
|
+
k.when(:exit) do #NOTE: no |k| needed (naturally)
|
|
7
|
+
k_in_when = true if k
|
|
8
|
+
end
|
|
9
|
+
k.out.on("something") do
|
|
10
|
+
k_in_out_on = true if k
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
k.run
|
|
14
|
+
|
|
15
|
+
raise "err" unless k_in_when && k_in_out_on
|
data/examples/kill.rb
CHANGED
data/examples/live_output.rb
CHANGED
data/examples/nano.rb
CHANGED
data/examples/nano_match.rb
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
calls = []
|
|
4
|
+
calls_matchdata = []
|
|
5
|
+
|
|
6
|
+
k = Kommando.new("ping -c 3 -i 0.2 127.0.0.1", {
|
|
7
|
+
output: false
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
k.out.once("bytes") do
|
|
11
|
+
calls << :first
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
k.out.once(/from (\d+)\./) do |m|
|
|
15
|
+
calls_matchdata << m[1]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
k.run
|
|
19
|
+
|
|
20
|
+
raise "err" unless calls == [:first]
|
|
21
|
+
raise "err matchdata" unless calls_matchdata == ["127"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
calls_bytes = []
|
|
4
|
+
calls_icmp = []
|
|
5
|
+
calls_ttl_then_time = []
|
|
6
|
+
|
|
7
|
+
k = Kommando.new("ping -c 3 -i 0.2 127.0.0.1", {
|
|
8
|
+
output: true
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
k.out.on("bytes") do
|
|
12
|
+
calls_bytes << :only_bytes
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
k.out.once("icmp_seq") do
|
|
16
|
+
calls_icmp << :first_icmp
|
|
17
|
+
end.once("icmp_seq") do
|
|
18
|
+
calls_icmp << :second_icmp
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
k.out.once("ttl").once("time") do
|
|
22
|
+
calls_ttl_then_time << :only_ttl_then_time
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
k.run
|
|
26
|
+
|
|
27
|
+
raise "err icmp" unless calls_icmp == [:first_icmp, :second_icmp]
|
|
28
|
+
raise "err bytes" unless calls_bytes == [:only_bytes]
|
|
29
|
+
raise "err ttl_then_time" unless calls_ttl_then_time == [:only_ttl_then_time]
|
data/examples/stdout_to_file.rb
CHANGED
data/examples/timeout.rb
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "./lib/kommando"
|
|
2
|
+
|
|
3
|
+
calls = []
|
|
4
|
+
k = Kommando.new("$ exit 0")
|
|
5
|
+
k.when(:success) do
|
|
6
|
+
calls << :success
|
|
7
|
+
end.when(:failed) do
|
|
8
|
+
calls << :failed # should never happen
|
|
9
|
+
end.when(:exit) do
|
|
10
|
+
calls << :exit
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
k.run
|
|
14
|
+
|
|
15
|
+
raise "err" unless calls == [:exit, :success]
|
data/kommando.gemspec
CHANGED
|
@@ -14,7 +14,9 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.homepage = "http://github.com/matti/kommando"
|
|
15
15
|
spec.license = "MIT"
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
if Dir.exist? ".git"
|
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
19
|
+
end
|
|
18
20
|
spec.bindir = "exe"
|
|
19
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
20
22
|
spec.require_paths = ["lib"]
|
|
@@ -27,4 +29,5 @@ Gem::Specification.new do |spec|
|
|
|
27
29
|
spec.add_development_dependency "byebug"
|
|
28
30
|
spec.add_development_dependency "stackprof"
|
|
29
31
|
spec.add_development_dependency "trapper"
|
|
32
|
+
spec.add_development_dependency "rspec-prof"
|
|
30
33
|
end
|
data/lib/kommando.rb
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
require "pty"
|
|
2
2
|
require "timeout"
|
|
3
3
|
|
|
4
|
+
class Kommando
|
|
5
|
+
end
|
|
6
|
+
|
|
4
7
|
require_relative "kommando/error"
|
|
5
8
|
require_relative "kommando/version"
|
|
6
|
-
require_relative "kommando/buffer"
|
|
7
9
|
require_relative "kommando/when"
|
|
10
|
+
require_relative "kommando/stdout"
|
|
11
|
+
require_relative "kommando/stdin"
|
|
12
|
+
require_relative "kommando/matchers"
|
|
8
13
|
|
|
9
14
|
class Kommando
|
|
10
15
|
class << self
|
|
@@ -38,7 +43,6 @@ class Kommando
|
|
|
38
43
|
@@timeout=value
|
|
39
44
|
end
|
|
40
45
|
|
|
41
|
-
|
|
42
46
|
def when(event_name, &block)
|
|
43
47
|
@@whens ||= Kommando::When.new
|
|
44
48
|
@@whens.register event_name, block
|
|
@@ -53,8 +57,9 @@ class Kommando
|
|
|
53
57
|
Thread.abort_on_exception=true
|
|
54
58
|
|
|
55
59
|
@cmd = cmd
|
|
56
|
-
@
|
|
57
|
-
@
|
|
60
|
+
@shell = @cmd.start_with? "$"
|
|
61
|
+
@stdout = Kommando::Stdout.new @shell
|
|
62
|
+
@stdin = Kommando::Stdin.new
|
|
58
63
|
|
|
59
64
|
@output_stdout = opts[:output] == true
|
|
60
65
|
@output_file = if opts[:output].class == String
|
|
@@ -63,7 +68,7 @@ class Kommando
|
|
|
63
68
|
|
|
64
69
|
@timeout = if opts[:timeout].class == Float
|
|
65
70
|
opts[:timeout]
|
|
66
|
-
elsif opts[:timeout].class == Fixnum
|
|
71
|
+
elsif opts[:timeout].class.to_s == "Integer" || opts[:timeout].class.to_s == "Fixnum"
|
|
67
72
|
opts[:timeout].to_f
|
|
68
73
|
else
|
|
69
74
|
@timeout = @@timeout
|
|
@@ -94,11 +99,6 @@ class Kommando
|
|
|
94
99
|
@thread = nil
|
|
95
100
|
@pid = nil
|
|
96
101
|
|
|
97
|
-
@shell = false
|
|
98
|
-
|
|
99
|
-
@matchers = {}
|
|
100
|
-
@matcher_buffer = ""
|
|
101
|
-
|
|
102
102
|
@whens = {}
|
|
103
103
|
@when = When.new(self)
|
|
104
104
|
|
|
@@ -138,8 +138,7 @@ class Kommando
|
|
|
138
138
|
return false if @executed
|
|
139
139
|
@executed = true
|
|
140
140
|
|
|
141
|
-
command, *args = if @
|
|
142
|
-
@shell = true
|
|
141
|
+
command, *args = if @shell
|
|
143
142
|
trash, line = @cmd.split "$", 2
|
|
144
143
|
line.lstrip!
|
|
145
144
|
["bash", "-c", line]
|
|
@@ -270,16 +269,16 @@ class Kommando
|
|
|
270
269
|
137
|
|
271
270
|
else
|
|
272
271
|
begin
|
|
273
|
-
|
|
274
|
-
Process.wait @pid if @pid
|
|
275
|
-
end
|
|
272
|
+
Process.wait @pid if @pid
|
|
276
273
|
rescue Errno::ECHILD => ex
|
|
277
274
|
# safe to supress, I guess
|
|
278
|
-
rescue Timeout::Error => ex
|
|
279
|
-
# seems to be okay...
|
|
280
275
|
end
|
|
281
276
|
|
|
282
|
-
|
|
277
|
+
if $?
|
|
278
|
+
$?.exitstatus
|
|
279
|
+
else
|
|
280
|
+
137 # sometimes with ruby2.1 ? (maybefix now?)
|
|
281
|
+
end
|
|
283
282
|
end
|
|
284
283
|
|
|
285
284
|
@when.fire :error if @rescue_happened
|
|
@@ -298,19 +297,7 @@ class Kommando
|
|
|
298
297
|
end
|
|
299
298
|
|
|
300
299
|
def out
|
|
301
|
-
|
|
302
|
-
@stdout.to_s.strip
|
|
303
|
-
else
|
|
304
|
-
@stdout.to_s
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
kommando = self
|
|
308
|
-
string.define_singleton_method(:on) do |matcher, &block|
|
|
309
|
-
matchers = kommando.instance_variable_get(:@matchers)
|
|
310
|
-
matchers[matcher] = block
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
string
|
|
300
|
+
@stdout.to_s
|
|
314
301
|
end
|
|
315
302
|
|
|
316
303
|
def code
|
|
@@ -333,6 +320,7 @@ class Kommando
|
|
|
333
320
|
|
|
334
321
|
def when(event, &block)
|
|
335
322
|
@when.register event, block
|
|
323
|
+
self
|
|
336
324
|
end
|
|
337
325
|
|
|
338
326
|
private
|
|
@@ -375,21 +363,9 @@ class Kommando
|
|
|
375
363
|
break if flushing == true && c == nil
|
|
376
364
|
next unless c
|
|
377
365
|
|
|
378
|
-
@stdout
|
|
366
|
+
@stdout << c
|
|
379
367
|
print c if @output_stdout
|
|
380
368
|
stdout_file.write c if @output_file
|
|
381
|
-
|
|
382
|
-
if c
|
|
383
|
-
@matcher_buffer << c
|
|
384
|
-
|
|
385
|
-
matchers_copy = @matchers.clone # blocks can insert to @matchers while iteration is undergoing
|
|
386
|
-
matchers_copy.each_pair do |matcher,block|
|
|
387
|
-
if @matcher_buffer.match matcher
|
|
388
|
-
block.call
|
|
389
|
-
@matchers.delete matcher # do not match again TODO: is this safe?
|
|
390
|
-
end
|
|
391
|
-
end
|
|
392
|
-
end
|
|
393
369
|
end
|
|
394
370
|
end
|
|
395
371
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class Kommando::Matchers::Base
|
|
2
|
+
attr_reader :nested_matchers
|
|
3
|
+
|
|
4
|
+
def initialize(regexp, block)
|
|
5
|
+
@regexp = regexp
|
|
6
|
+
@block = block
|
|
7
|
+
|
|
8
|
+
@nested_matchers = []
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def match(string)
|
|
12
|
+
raise "#match not implemented"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call(match_data=nil)
|
|
16
|
+
return unless @block
|
|
17
|
+
@block.call match_data
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def once(regexp, &block)
|
|
21
|
+
m = Kommando::Matchers::Once.new regexp, block
|
|
22
|
+
@nested_matchers << m
|
|
23
|
+
m
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def every(regexp, &block)
|
|
27
|
+
m = Kommando::Matchers::Every.new regexp, block
|
|
28
|
+
@nested_matchers << m
|
|
29
|
+
m
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Kommando::Matchers::Every < Kommando::Matchers::Base
|
|
2
|
+
def initialize(regexp, block)
|
|
3
|
+
super regexp, block
|
|
4
|
+
@cursor = 0
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def match(string)
|
|
8
|
+
match_data = string[@cursor..-1].match(@regexp)
|
|
9
|
+
@cursor = string.length if match_data
|
|
10
|
+
match_data
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def skip_by(string)
|
|
14
|
+
@cursor = string.length
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class Kommando; class Stdin
|
|
2
|
+
def initialize
|
|
3
|
+
@buffer = []
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def getc
|
|
7
|
+
@buffer.shift
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def <<(string)
|
|
11
|
+
@buffer << string
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def write(string)
|
|
15
|
+
self << string
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def writeln(string)
|
|
19
|
+
self << string << "\r"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
class Kommando; class Stdout
|
|
2
|
+
def initialize(shell)
|
|
3
|
+
@buffer = []
|
|
4
|
+
@matchers = []
|
|
5
|
+
@matcher_buffer = ""
|
|
6
|
+
|
|
7
|
+
@shell = shell
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def <<(c)
|
|
11
|
+
@buffer << c
|
|
12
|
+
@matcher_buffer << c
|
|
13
|
+
|
|
14
|
+
matchers_copy = @matchers.clone # blocks can insert to @matchers while iteration is undergoing
|
|
15
|
+
matchers_copy.each do |matcher|
|
|
16
|
+
if (match_data = matcher.match @matcher_buffer)
|
|
17
|
+
matcher.call match_data
|
|
18
|
+
unless matcher.class == Kommando::Matchers::Every
|
|
19
|
+
@matchers.delete matcher #TODO: is this safe?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
matcher.nested_matchers.each do |nested_matcher|
|
|
23
|
+
if nested_matcher.class == Kommando::Matchers::Every
|
|
24
|
+
nested_matcher.skip_by(@matcher_buffer)
|
|
25
|
+
end
|
|
26
|
+
@matchers = @matchers + [nested_matcher] #TODO: is this safe?
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_s
|
|
33
|
+
string = @buffer.join ""
|
|
34
|
+
|
|
35
|
+
#TODO: this behaviour maybe makes no sense?
|
|
36
|
+
string.strip! if @shell
|
|
37
|
+
|
|
38
|
+
matchers = @matchers
|
|
39
|
+
#TODO: deprecate .on
|
|
40
|
+
string.define_singleton_method(:on) do |regexp, &block|
|
|
41
|
+
m = Kommando::Matchers::Once.new regexp, block
|
|
42
|
+
matchers << m
|
|
43
|
+
m
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
string.define_singleton_method(:once) do |regexp, &block|
|
|
47
|
+
m = Kommando::Matchers::Once.new regexp, block
|
|
48
|
+
matchers << m
|
|
49
|
+
m
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
string.define_singleton_method(:every) do |regexp, &block|
|
|
53
|
+
m = Kommando::Matchers::Every.new regexp, block
|
|
54
|
+
matchers << m
|
|
55
|
+
m
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
string
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end; end
|
data/lib/kommando/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kommando
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matti Paksula
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2017-04-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -122,6 +122,20 @@ dependencies:
|
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: rspec-prof
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
125
139
|
description: Great for integration testing.
|
|
126
140
|
email:
|
|
127
141
|
- matti.paksula@iki.fi
|
|
@@ -139,23 +153,38 @@ files:
|
|
|
139
153
|
- LICENSE.txt
|
|
140
154
|
- README.md
|
|
141
155
|
- Rakefile
|
|
156
|
+
- bin/autotest
|
|
142
157
|
- bin/console
|
|
143
158
|
- bin/e2e
|
|
144
159
|
- bin/loop
|
|
160
|
+
- bin/matrix
|
|
145
161
|
- bin/reinstall
|
|
146
162
|
- bin/release
|
|
147
163
|
- bin/setup
|
|
148
164
|
- bin/stress
|
|
149
165
|
- bin/version
|
|
166
|
+
- demos/ping_monitor.rb
|
|
167
|
+
- docker-compose.yml
|
|
168
|
+
- docker/Dockerfile.alpine
|
|
169
|
+
- docker/Dockerfile.alpine-2.1
|
|
170
|
+
- docker/Dockerfile.alpine-2.2
|
|
171
|
+
- docker/Dockerfile.alpine-2.3
|
|
172
|
+
- docker/Dockerfile.debian
|
|
173
|
+
- docker/entrypoint.sh
|
|
150
174
|
- examples/async.rb
|
|
151
175
|
- examples/env.rb
|
|
176
|
+
- examples/every.rb
|
|
177
|
+
- examples/every_ping.rb
|
|
152
178
|
- examples/exit.rb
|
|
153
179
|
- examples/in.rb
|
|
154
180
|
- examples/in_shell.rb
|
|
181
|
+
- examples/k_visibility.rb
|
|
155
182
|
- examples/kill.rb
|
|
156
183
|
- examples/live_output.rb
|
|
157
184
|
- examples/nano.rb
|
|
158
185
|
- examples/nano_match.rb
|
|
186
|
+
- examples/out_once.rb
|
|
187
|
+
- examples/out_once_chaining.rb
|
|
159
188
|
- examples/passwd.rb
|
|
160
189
|
- examples/ping.rb
|
|
161
190
|
- examples/shell.rb
|
|
@@ -168,10 +197,16 @@ files:
|
|
|
168
197
|
- examples/uptime.rb
|
|
169
198
|
- examples/wait.rb
|
|
170
199
|
- examples/when.rb
|
|
200
|
+
- examples/when_chaining.rb
|
|
171
201
|
- kommando.gemspec
|
|
172
202
|
- lib/kommando.rb
|
|
173
|
-
- lib/kommando/buffer.rb
|
|
174
203
|
- lib/kommando/error.rb
|
|
204
|
+
- lib/kommando/matchers.rb
|
|
205
|
+
- lib/kommando/matchers/base.rb
|
|
206
|
+
- lib/kommando/matchers/every.rb
|
|
207
|
+
- lib/kommando/matchers/once.rb
|
|
208
|
+
- lib/kommando/stdin.rb
|
|
209
|
+
- lib/kommando/stdout.rb
|
|
175
210
|
- lib/kommando/version.rb
|
|
176
211
|
- lib/kommando/when.rb
|
|
177
212
|
- tests/forever_true.rb
|
|
@@ -197,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
197
232
|
version: '0'
|
|
198
233
|
requirements: []
|
|
199
234
|
rubyforge_project:
|
|
200
|
-
rubygems_version: 2.
|
|
235
|
+
rubygems_version: 2.6.11
|
|
201
236
|
signing_key:
|
|
202
237
|
specification_version: 4
|
|
203
238
|
summary: Command runner with expect-like features
|
data/lib/kommando/buffer.rb
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
class Kommando::Buffer
|
|
2
|
-
|
|
3
|
-
def initialize
|
|
4
|
-
@buffer = []
|
|
5
|
-
|
|
6
|
-
@matchers = {}
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def append(string)
|
|
10
|
-
@buffer << string
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def to_s
|
|
14
|
-
@buffer.join ""
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def <<(string)
|
|
18
|
-
@buffer << string
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def write(string)
|
|
22
|
-
self << string
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def writeln(string)
|
|
26
|
-
self.write "#{string}\r"
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def getc
|
|
30
|
-
@buffer.shift
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def on(matcher, &block)
|
|
34
|
-
@matchers[matcher] = block
|
|
35
|
-
end
|
|
36
|
-
end
|