loom-core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +99 -0
- data/Guardfile +54 -0
- data/Rakefile +6 -0
- data/bin/loom +185 -0
- data/lib/env/development.rb +1 -0
- data/lib/loom.rb +44 -0
- data/lib/loom/all.rb +20 -0
- data/lib/loom/config.rb +106 -0
- data/lib/loom/core_ext.rb +37 -0
- data/lib/loom/dsl.rb +60 -0
- data/lib/loom/facts.rb +13 -0
- data/lib/loom/facts/all.rb +2 -0
- data/lib/loom/facts/fact_file_provider.rb +86 -0
- data/lib/loom/facts/fact_set.rb +138 -0
- data/lib/loom/host_spec.rb +32 -0
- data/lib/loom/inventory.rb +124 -0
- data/lib/loom/logger.rb +141 -0
- data/lib/loom/method_signature.rb +174 -0
- data/lib/loom/mods.rb +4 -0
- data/lib/loom/mods/action_proxy.rb +105 -0
- data/lib/loom/mods/all.rb +3 -0
- data/lib/loom/mods/mod_loader.rb +80 -0
- data/lib/loom/mods/module.rb +113 -0
- data/lib/loom/pattern.rb +15 -0
- data/lib/loom/pattern/all.rb +7 -0
- data/lib/loom/pattern/definition_context.rb +74 -0
- data/lib/loom/pattern/dsl.rb +176 -0
- data/lib/loom/pattern/hook.rb +28 -0
- data/lib/loom/pattern/loader.rb +48 -0
- data/lib/loom/pattern/reference.rb +71 -0
- data/lib/loom/pattern/reference_set.rb +169 -0
- data/lib/loom/pattern/result_reporter.rb +77 -0
- data/lib/loom/runner.rb +209 -0
- data/lib/loom/shell.rb +12 -0
- data/lib/loom/shell/all.rb +10 -0
- data/lib/loom/shell/api.rb +48 -0
- data/lib/loom/shell/cmd_result.rb +33 -0
- data/lib/loom/shell/cmd_wrapper.rb +164 -0
- data/lib/loom/shell/core.rb +226 -0
- data/lib/loom/shell/harness_blob.rb +26 -0
- data/lib/loom/shell/harness_command_builder.rb +50 -0
- data/lib/loom/shell/session.rb +25 -0
- data/lib/loom/trap.rb +44 -0
- data/lib/loom/version.rb +3 -0
- data/lib/loomext/all.rb +4 -0
- data/lib/loomext/corefacts.rb +6 -0
- data/lib/loomext/corefacts/all.rb +8 -0
- data/lib/loomext/corefacts/facter_provider.rb +24 -0
- data/lib/loomext/coremods.rb +5 -0
- data/lib/loomext/coremods/all.rb +13 -0
- data/lib/loomext/coremods/exec.rb +50 -0
- data/lib/loomext/coremods/files.rb +104 -0
- data/lib/loomext/coremods/net.rb +33 -0
- data/lib/loomext/coremods/package/adapter.rb +100 -0
- data/lib/loomext/coremods/package/package.rb +62 -0
- data/lib/loomext/coremods/user.rb +82 -0
- data/lib/loomext/coremods/vm.rb +0 -0
- data/lib/loomext/coremods/vm/all.rb +6 -0
- data/lib/loomext/coremods/vm/vbox.rb +84 -0
- data/loom.gemspec +39 -0
- data/loom/inventory.yml +13 -0
- data/scripts/harness.sh +242 -0
- data/spec/loom/host_spec_spec.rb +101 -0
- data/spec/loom/inventory_spec.rb +154 -0
- data/spec/loom/method_signature_spec.rb +275 -0
- data/spec/loom/pattern/dsl_spec.rb +207 -0
- data/spec/loom/shell/cmd_wrapper_spec.rb +239 -0
- data/spec/loom/shell/harness_blob_spec.rb +42 -0
- data/spec/loom/shell/harness_command_builder_spec.rb +36 -0
- data/spec/runloom.sh +35 -0
- data/spec/scripts/harness_spec.rb +385 -0
- data/spec/spec_helper.rb +94 -0
- data/spec/test.loom +370 -0
- data/spec/test_loom_spec.rb +57 -0
- metadata +287 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
require "loom/facts"
|
2
|
+
require "loom/pattern"
|
3
|
+
require "loom/shell"
|
4
|
+
|
5
|
+
describe Loom::Pattern::DSL do
|
6
|
+
|
7
|
+
# Fake API for tests. This object should raise an error on any command
|
8
|
+
# execution.
|
9
|
+
let(:fake_shell) { Loom::Shell::FakeApi.new }
|
10
|
+
let(:a_fact_set) do
|
11
|
+
Loom::Facts::FactSet.new('fake.host', :fact_one => 1, :fact_two => :two)
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
# bit buckets the logs
|
16
|
+
@logger_io = StringIO.new
|
17
|
+
Loom.configure do |config|
|
18
|
+
config.log_device = @logger_io
|
19
|
+
end
|
20
|
+
|
21
|
+
@reference_set = Loom::Pattern::ReferenceSet::Builder
|
22
|
+
.create(loom_file, ':loom_file')
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:pattern_under_test) { @reference_set['pattern_under_test'] }
|
26
|
+
let(:inner_pattern) { @reference_set['inner:an_inner_pattern'] }
|
27
|
+
|
28
|
+
context "pattern basics" do
|
29
|
+
|
30
|
+
let(:loom_file) do
|
31
|
+
<<EOS
|
32
|
+
desc "a description of pattern_under_test"
|
33
|
+
pattern :pattern_under_test do |loom, facts|
|
34
|
+
loom.do_outer_thing
|
35
|
+
end
|
36
|
+
|
37
|
+
module Inner
|
38
|
+
include Loom::Pattern
|
39
|
+
|
40
|
+
desc "an inner pattern"
|
41
|
+
pattern :an_inner_pattern do |loom, facts|
|
42
|
+
loom.do_inner_thing
|
43
|
+
end
|
44
|
+
end
|
45
|
+
EOS
|
46
|
+
end
|
47
|
+
|
48
|
+
it "defines a Pattern::Reference" do
|
49
|
+
expect(pattern_under_test).to be_a Loom::Pattern::Reference
|
50
|
+
end
|
51
|
+
|
52
|
+
it "defines a reference with a desc" do
|
53
|
+
expect(pattern_under_test.desc).to(
|
54
|
+
eql "a description of pattern_under_test")
|
55
|
+
end
|
56
|
+
|
57
|
+
it "defines an inner reference with a desc" do
|
58
|
+
expect(inner_pattern.desc).to eql "an inner pattern"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "is runnable" do
|
62
|
+
pattern_under_test.call fake_shell, a_fact_set
|
63
|
+
expect(fake_shell.cmd_executions.first).to be :do_outer_thing
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "#let" do
|
68
|
+
|
69
|
+
let(:loom_file) do
|
70
|
+
<<EOS
|
71
|
+
let(:let_var_1) { "let var 1"}
|
72
|
+
let(:let_var_2) { "let var 2"}
|
73
|
+
|
74
|
+
desc "a description of pattern_under_test"
|
75
|
+
pattern :pattern_under_test do |loom, facts|
|
76
|
+
loom.do_outer_thing(let_var_1, let_var_2)
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "a pattern that will raise an erorr"
|
80
|
+
pattern :bogus_pattern do |loom, facts|
|
81
|
+
loom.do_outer_thing(let_var_3)
|
82
|
+
end
|
83
|
+
|
84
|
+
module Inner
|
85
|
+
include Loom::Pattern
|
86
|
+
|
87
|
+
let(:let_var_2) { "override let var 2"}
|
88
|
+
let(:let_var_3) { "let var 3"}
|
89
|
+
|
90
|
+
desc "an inner pattern"
|
91
|
+
pattern :an_inner_pattern do |loom, facts|
|
92
|
+
loom.do_inner_thing(let_var_1, let_var_2, let_var_3)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
EOS
|
96
|
+
end
|
97
|
+
|
98
|
+
it "defines :let declartions at the top level" do
|
99
|
+
pattern_under_test.call fake_shell, a_fact_set
|
100
|
+
expect(fake_shell.cmd_execution_args.first).to(
|
101
|
+
eql ["let var 1", "let var 2"])
|
102
|
+
end
|
103
|
+
|
104
|
+
it "defines :let declartions at inner scopes, innacessible to outer" do
|
105
|
+
expect do
|
106
|
+
@reference_set['bogus_pattern'].call fake_shell, a_fact_set
|
107
|
+
end.to raise_error /^undefined local variable/
|
108
|
+
end
|
109
|
+
|
110
|
+
it "defines :let declarations at inner scopes, overriding outer scope" do
|
111
|
+
inner_pattern.call fake_shell, a_fact_set
|
112
|
+
expect(fake_shell.cmd_execution_args.first).to(
|
113
|
+
eql ["let var 1", "override let var 2", "let var 3"])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "#with_facts" do
|
118
|
+
|
119
|
+
let(:loom_file) do
|
120
|
+
<<EOS
|
121
|
+
with_facts :outer_fact => :outer
|
122
|
+
|
123
|
+
desc "a description of pattern_under_test"
|
124
|
+
pattern :pattern_under_test do |loom, facts|
|
125
|
+
loom.do_outer_thing facts[:outer_fact]
|
126
|
+
end
|
127
|
+
|
128
|
+
module Inner
|
129
|
+
include Loom::Pattern
|
130
|
+
|
131
|
+
with_facts :inner_fact => :inner
|
132
|
+
|
133
|
+
desc "an inner pattern"
|
134
|
+
pattern :an_inner_pattern do |loom, facts|
|
135
|
+
loom.do_inner_thing(facts[:outer_fact], facts[:inner_fact])
|
136
|
+
end
|
137
|
+
end
|
138
|
+
EOS
|
139
|
+
end
|
140
|
+
|
141
|
+
it "defines fact sets at the top level" do
|
142
|
+
pattern_under_test.call fake_shell, a_fact_set
|
143
|
+
expect(fake_shell.cmd_execution_args.first).to(
|
144
|
+
eql [:outer])
|
145
|
+
end
|
146
|
+
|
147
|
+
it "provides fact sets that get merged into inner modules" do
|
148
|
+
inner_pattern.call fake_shell, a_fact_set
|
149
|
+
expect(fake_shell.cmd_execution_args.first).to(
|
150
|
+
eql [:outer, :inner])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "hooks" do
|
155
|
+
|
156
|
+
let(:loom_file) do
|
157
|
+
<<EOS
|
158
|
+
|
159
|
+
let(:hook_order) { [] }
|
160
|
+
|
161
|
+
before do hook_order.push("outer before hook") end
|
162
|
+
after do hook_order.push("outer after hook") end
|
163
|
+
|
164
|
+
desc "a description of pattern_under_test"
|
165
|
+
pattern :pattern_under_test do |loom, facts|
|
166
|
+
hook_order.push "execute the pattern"
|
167
|
+
loom.do_outer_thing(hook_order)
|
168
|
+
end
|
169
|
+
|
170
|
+
module Inner
|
171
|
+
include Loom::Pattern
|
172
|
+
|
173
|
+
before do hook_order.push("inner before hook") end
|
174
|
+
after do hook_order.push("inner after hook") end
|
175
|
+
|
176
|
+
desc "an inner pattern"
|
177
|
+
pattern :an_inner_pattern do |loom, facts|
|
178
|
+
hook_order.push "execute inner pattern"
|
179
|
+
loom.do_inner_thing(hook_order)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
EOS
|
183
|
+
end
|
184
|
+
|
185
|
+
it "executes outer before hooks first and after hooks last" do
|
186
|
+
pattern_under_test.call fake_shell, a_fact_set
|
187
|
+
expect(fake_shell.cmd_execution_args.first).to eql [[
|
188
|
+
"outer before hook",
|
189
|
+
"execute the pattern",
|
190
|
+
"outer after hook"
|
191
|
+
]]
|
192
|
+
end
|
193
|
+
|
194
|
+
it "executes nested hooks in wrapped order" do
|
195
|
+
inner_pattern.call fake_shell, a_fact_set
|
196
|
+
expect(fake_shell.cmd_execution_args.first).to eql [[
|
197
|
+
"outer before hook",
|
198
|
+
"inner before hook",
|
199
|
+
"execute inner pattern",
|
200
|
+
"inner after hook",
|
201
|
+
"outer after hook"
|
202
|
+
]]
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
require "loom/shell"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
describe Loom::Shell::CmdWrapper do
|
5
|
+
|
6
|
+
def unescape_cmd(cmd)
|
7
|
+
YAML.load(%Q(---\n"#{cmd.to_s}"\n))
|
8
|
+
end
|
9
|
+
|
10
|
+
context "examples" do
|
11
|
+
it "escapes spaces" do
|
12
|
+
cmd = Loom::Shell::CmdWrapper.new :printf, "print out this string"
|
13
|
+
expect(%x{#{cmd}}).to eql "print out this string"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "skips escaping symbols and frozen string" do
|
17
|
+
cmd = Loom::Shell::CmdWrapper.new :"/bin/echo", :"\"yy\"", "\"xx\""
|
18
|
+
expect(%x{#{cmd}}.strip).to eql "yy \"xx\""
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context ".new" do
|
23
|
+
it "does not escape whitespace between joined commands parts" do
|
24
|
+
cmd = Loom::Shell::CmdWrapper.new :echo, "-n", "\"all the rest\""
|
25
|
+
expect(cmd.escape_cmd).to eql "echo -n \\\"all\\ the\\ rest\\\""
|
26
|
+
end
|
27
|
+
|
28
|
+
it "flattens cmd input" do
|
29
|
+
cmd = Loom::Shell::CmdWrapper.new :somecmd, ["-f", "file.txt"], [:a, [:b]]
|
30
|
+
expect(cmd.to_s).to eql "somecmd -f file.txt a b"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context ".escape" do
|
35
|
+
it "escapes CmdWrappers" do
|
36
|
+
cmd = Loom::Shell::CmdWrapper.new '"hi"'
|
37
|
+
expect(Loom::Shell::CmdWrapper.escape cmd).to eql cmd.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
it "escapes recursively" do
|
41
|
+
content = 'I said "row row row your boat"'
|
42
|
+
cmd_inner = 'echo "%s"' % Loom::Shell::CmdWrapper.escape(content)
|
43
|
+
cmd_outer = '"%s"' % Loom::Shell::CmdWrapper.escape(cmd_inner)
|
44
|
+
|
45
|
+
expected = '"echo\ \"I\\\\\ said\\\\\ ' +
|
46
|
+
'\\\\\"row\\\\\ row\\\\\ row\\\\\ your\\\\\ boat\\\\\"\""'
|
47
|
+
|
48
|
+
printf_expected = 'echo\\ "I\ said\ "row\ row\ row\ your\ boat""'
|
49
|
+
|
50
|
+
expect(cmd_outer).to eql expected
|
51
|
+
expect(%x{printf #{cmd_outer}}.strip).to eql printf_expected
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "#escape" do
|
56
|
+
it "escapes strings with quotes" do
|
57
|
+
cmd = Loom::Shell::CmdWrapper.new '"hi"'
|
58
|
+
|
59
|
+
expected = '\"hi\"'
|
60
|
+
expect(cmd.escape_cmd).to eql expected
|
61
|
+
expect(%x{printf #{expected}}.strip).to eql unescape_cmd(cmd)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "ignores strings without quotes" do
|
65
|
+
cmd = Loom::Shell::CmdWrapper.new 'hi'
|
66
|
+
|
67
|
+
expected = 'hi'
|
68
|
+
expect(cmd.escape_cmd).to eql expected
|
69
|
+
expect(%x{printf #{expected}}.strip).to eql unescape_cmd(cmd)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "escapes nested quotes" do
|
73
|
+
cmd = Loom::Shell::CmdWrapper.new 'echo "hi"'
|
74
|
+
|
75
|
+
expected = 'echo\\ \"hi\"'
|
76
|
+
expect(cmd.escape_cmd).to eql expected
|
77
|
+
expect(%x{printf #{expected}}.strip).to eql unescape_cmd(cmd)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "respects frozen? string" do
|
81
|
+
cmd = Loom::Shell::CmdWrapper.new :echo, "\"^FROZEN^\"".freeze, :"^", "^"
|
82
|
+
|
83
|
+
expected = 'echo "^FROZEN^" ^ \^'
|
84
|
+
expect(cmd.escape_cmd).to eql expected
|
85
|
+
end
|
86
|
+
|
87
|
+
it "respects wrapped frozen? strings" do
|
88
|
+
cmd_inner = Loom::Shell::CmdWrapper.new :echo, "\"^#FROZEN^\"".freeze
|
89
|
+
cmd = Loom::Shell::CmdWrapper.wrap_cmd :sudo, cmd_inner
|
90
|
+
|
91
|
+
expected = 'sudo echo "^#FROZEN^"'
|
92
|
+
expect(cmd.escape_cmd).to eql expected
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# I don't want to think about this shit anymore. Don't touch this unless its
|
97
|
+
# broken.
|
98
|
+
context "#wrap" do
|
99
|
+
it "preserves escaped CmdWrappers: depth 2" do
|
100
|
+
cmd_which = Loom::Shell::CmdWrapper.new :which, :ls
|
101
|
+
cmd_sh = Loom::Shell::CmdWrapper.new :"/bin/sh", "-c", should_quote: true
|
102
|
+
|
103
|
+
composed_cmd = cmd_sh.wrap(cmd_sh.wrap(cmd_which)).to_s
|
104
|
+
|
105
|
+
expected = "/bin/sh -c \"/bin/sh -c \\\"which ls\\\"\""
|
106
|
+
|
107
|
+
expect(composed_cmd).to eql expected
|
108
|
+
# Matches /bin/ls$ for portability, on fedora it's /usr/bin/ls
|
109
|
+
expect(%x{#{composed_cmd}}.strip).to match /\/bin\/ls$/
|
110
|
+
end
|
111
|
+
|
112
|
+
it "preserves escaped CmdWrappers: depth N" do
|
113
|
+
cmd_which = Loom::Shell::CmdWrapper.new :which, :ls
|
114
|
+
cmd_sh = Loom::Shell::CmdWrapper.new :"/bin/sh", "-c", should_quote: true
|
115
|
+
|
116
|
+
composed_cmd = cmd_sh.wrap(cmd_sh.wrap(cmd_sh.wrap(cmd_which))).to_s
|
117
|
+
|
118
|
+
expected =
|
119
|
+
"/bin/sh -c \"/bin/sh -c \\\"/bin/sh -c \\\\\\\"which ls\\\\\\\"\\\"\""
|
120
|
+
|
121
|
+
expect(composed_cmd).to eql expected
|
122
|
+
# Matches /bin/ls$ for portability, on fedora it's /usr/bin/ls
|
123
|
+
expect(%x{#{composed_cmd}}.strip).to match /\/bin\/ls$/
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context Loom::Shell::CmdRedirect do
|
128
|
+
|
129
|
+
let(:cmd_parts) { [:"/bin/ls"] }
|
130
|
+
|
131
|
+
it "redirects stdout to file" do
|
132
|
+
redirect = Loom::Shell::CmdRedirect.new "/my/file"
|
133
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
134
|
+
|
135
|
+
expect(cmd.to_s).to eql "/bin/ls >/my/file"
|
136
|
+
end
|
137
|
+
|
138
|
+
it "redirects stderr to file" do
|
139
|
+
redirect = Loom::Shell::CmdRedirect.new "/my/file", fd: 2
|
140
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
141
|
+
|
142
|
+
expect(cmd.to_s).to eql "/bin/ls 2>/my/file"
|
143
|
+
end
|
144
|
+
|
145
|
+
it "appends stdout to file" do
|
146
|
+
mode = Loom::Shell::CmdRedirect::Mode::APPEND
|
147
|
+
|
148
|
+
redirect = Loom::Shell::CmdRedirect.new "/my/file", mode: mode
|
149
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
150
|
+
|
151
|
+
expect(cmd.to_s).to eql "/bin/ls >>/my/file"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "appends stderr to file" do
|
155
|
+
mode = Loom::Shell::CmdRedirect::Mode::APPEND
|
156
|
+
|
157
|
+
redirect = Loom::Shell::CmdRedirect.new "/my/file", fd: 2, mode: mode
|
158
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
159
|
+
|
160
|
+
expect(cmd.to_s).to eql "/bin/ls 2>>/my/file"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "redirects stderr to stdout" do
|
164
|
+
redirect = Loom::Shell::CmdRedirect.new 1, fd: 2
|
165
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
166
|
+
|
167
|
+
expect(cmd.to_s).to eql "/bin/ls 2>1"
|
168
|
+
end
|
169
|
+
|
170
|
+
it "redirects both stderr and stdout to file" do
|
171
|
+
mode = Loom::Shell::CmdRedirect::Mode::OUTPUT_12
|
172
|
+
|
173
|
+
redirect = Loom::Shell::CmdRedirect.new "/my/file", mode: mode
|
174
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
175
|
+
|
176
|
+
expect(cmd.to_s).to eql "/bin/ls &>/my/file"
|
177
|
+
end
|
178
|
+
|
179
|
+
context "helper factories" do
|
180
|
+
|
181
|
+
it "appends to stdout" do
|
182
|
+
redirect = Loom::Shell::CmdRedirect.append_stdout "/my/file"
|
183
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirect
|
184
|
+
|
185
|
+
expect(cmd.to_s).to eql "/bin/ls >>/my/file"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "multiple redirects" do
|
190
|
+
it "redirects both stderr and stdout to file" do
|
191
|
+
|
192
|
+
redirects = [
|
193
|
+
Loom::Shell::CmdRedirect.new("/my/file"),
|
194
|
+
Loom::Shell::CmdRedirect.new(1, fd: 2)
|
195
|
+
]
|
196
|
+
cmd = Loom::Shell::CmdWrapper.new *cmd_parts, redirect: redirects
|
197
|
+
|
198
|
+
expect(cmd.to_s).to eql "/bin/ls >/my/file 2>1"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "wrapped redirects" do
|
203
|
+
it "does not escape redirects" do
|
204
|
+
skip "fails - this is why I started implementing the harness see " +
|
205
|
+
"`git show 1196d2ec2` for info"
|
206
|
+
r = Loom::Shell::CmdRedirect.append_stdout "/my/file"
|
207
|
+
|
208
|
+
cmd_inner = Loom::Shell::CmdWrapper.new :echo, :hello, redirect: r
|
209
|
+
cmd = Loom::Shell::CmdWrapper.wrap_cmd :sudo, "-u", :root, cmd_inner
|
210
|
+
|
211
|
+
expect(cmd.to_s).to eql "sudo -u root echo hello >>/my/file"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context Loom::Shell::CmdPipeline do
|
217
|
+
|
218
|
+
let(:cmds) do
|
219
|
+
[
|
220
|
+
Loom::Shell::CmdWrapper.new(:find, ".", "-name", "*foo", "-print0"),
|
221
|
+
Loom::Shell::CmdWrapper.new(:xargs, "-0", "-I-", "ls", "-")
|
222
|
+
]
|
223
|
+
end
|
224
|
+
|
225
|
+
it "pipes commands together" do
|
226
|
+
pipeline = Loom::Shell::CmdPipeline.new cmds
|
227
|
+
|
228
|
+
expected = "find . -name \\*foo -print0 | xargs -0 -I- ls -"
|
229
|
+
expect(pipeline.to_s).to eql expected
|
230
|
+
end
|
231
|
+
|
232
|
+
it "accepts commands as pre-escaped strings" do
|
233
|
+
pipeline = Loom::Shell::CmdPipeline.new ["I'm already escaped", "me too!"]
|
234
|
+
|
235
|
+
expected = "I'm already escaped | me too!"
|
236
|
+
expect(pipeline.to_s).to eql expected
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
describe Loom::Shell::HarnessBlob do
|
2
|
+
|
3
|
+
HARNESS = "./scripts/harness.sh"
|
4
|
+
|
5
|
+
# Set debug_script to true in a context to see STDERR debugging.
|
6
|
+
let(:debug_script) { false }
|
7
|
+
|
8
|
+
let(:cmd) { 'echo hi there | (echo "from subshell"; cat);' }
|
9
|
+
let(:encoded_script) do
|
10
|
+
run_harnes_script "--print_base64", :stdin => cmd
|
11
|
+
end
|
12
|
+
let(:golden_checksum) do
|
13
|
+
run_harnes_script "--print_checksum", encoded_script
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def run_harnes_script(cmd, *args, stdin: nil)
|
18
|
+
cmd = %Q{./scripts/harness.sh 2>/dev/null #{cmd}}
|
19
|
+
|
20
|
+
heredoc = nil
|
21
|
+
if stdin
|
22
|
+
heredoc = "<<'EOS'\n#{stdin}\nEOS"
|
23
|
+
cmd << " - #{args.join " "} #{heredoc}"
|
24
|
+
else
|
25
|
+
cmd << " #{args.join " "}"
|
26
|
+
end
|
27
|
+
|
28
|
+
%x{#{cmd}}
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "scripts/harness.sh parity" do
|
32
|
+
|
33
|
+
subject { Loom::Shell::HarnessBlob.new cmd }
|
34
|
+
|
35
|
+
it "computes a valid script checksum" do
|
36
|
+
run_harnes_script "--check", golden_checksum, {
|
37
|
+
:stdin => subject.encoded_script
|
38
|
+
}
|
39
|
+
expect($?.exitstatus).to eq 0
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|