org-converge 0.0.13 → 0.0.14
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 +1 -0
- data/TODO +21 -10
- data/bin/org-converge +1 -1
- data/lib/org-converge/command.rb +30 -7
- data/lib/org-converge/engine.rb +61 -21
- data/lib/org-converge/version.rb +1 -1
- data/spec/converge_examples/block_modifiers/run.org +2 -1
- data/spec/converge_examples/chdir/local-run.org +42 -0
- data/spec/converge_examples/idempotency/conditions.org +158 -0
- data/spec/converge_spec.rb +29 -0
- data/vagrant.org +104 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8f7e90bad105cff350dbb911fe70a553646caa6
|
4
|
+
data.tar.gz: da367c09faae2f51ad7b0efd34c57f5a27ab8057
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b099f71b36b2504a9ae922ea1956d2a23eb224478c332fc230a747079105db9214b604d397ab43f0fa8dfd8d29b2349384a00ca4dfcf7f9e2fd72809e0885b8
|
7
|
+
data.tar.gz: 8768bddc3b3273d54164c7325e2f1f5e22b1364ed91ceaecf31f6edd1ee426274500ebd45eec6ed8329e1a048a4041de85f9614a9e443086d5fe83a52f5ef466
|
data/Gemfile
CHANGED
data/TODO
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#+TODO: TODO | DONE CANCELED
|
3
3
|
#+startup: showeverything
|
4
4
|
|
5
|
-
* [0/
|
5
|
+
* [0/16] 0.1.0 version
|
6
6
|
|
7
7
|
- [ ] Macros can be loaded and applied to the configuration
|
8
8
|
- [ ] Actually support converging and idempotency (~--runmode=idempotent~)
|
@@ -13,25 +13,36 @@
|
|
13
13
|
- [ ] Heuristics for determining which binary to use for running the script
|
14
14
|
- [ ] Display how the run would look like without making changes
|
15
15
|
: org-converge setupfile.org --dry-run
|
16
|
-
- [ ] Use
|
17
|
-
- [ ] Can use ~:dir~ for running a process relative to that directory
|
16
|
+
- [ ] Use =:eval= for evaling blocks (off by default)
|
18
17
|
- [ ] Bugfix for when results blocks have only inline examples or images
|
19
18
|
- [ ] Bugfix for when the result from a ~org-spec~ run has non-zero exit status
|
20
19
|
- [ ] Bugfixes for spec run
|
21
|
-
|
22
|
-
* [0/5] 0.0.14
|
23
|
-
|
24
20
|
- [ ] Distributed run helpers for the header arguments
|
25
|
-
|
21
|
+
Like remote =:dir= for example.
|
22
|
+
- [ ] =:onerror=
|
23
|
+
aborteverything, restart, runhandler
|
24
|
+
- [ ] =:asserts=
|
26
25
|
- [ ] =:waits:=
|
27
26
|
Wait for other processes to start before starting.
|
28
27
|
The process does not start until the alive signal to the following
|
29
28
|
list of processes succeeds.
|
30
29
|
- [ ] =:awaits:=
|
31
30
|
Wait for other processes to finish before starting.
|
32
|
-
- [ ] =:
|
33
|
-
|
34
|
-
- [ ] =:
|
31
|
+
- [ ] =:file=
|
32
|
+
For storing the output from the evaluation (already done in spec mode)a
|
33
|
+
- [ ] Can use =:dir= for running a process remotely via ssh
|
34
|
+
This needs the credentials to be readily available
|
35
|
+
|
36
|
+
* [2/2] 0.0.14
|
37
|
+
|
38
|
+
All of the following makes it required to
|
39
|
+
track the result from the runs.
|
40
|
+
|
41
|
+
- [X] Can use =:dir= for running a process relative to that directory
|
42
|
+
- [X] =:if= and =:unless= checks
|
43
|
+
First step at achieving idempotency.
|
44
|
+
This tracks the result from another block.
|
45
|
+
In case the block results in exit 0, then true. Otherwise false.
|
35
46
|
|
36
47
|
* [2/2] 0.0.13
|
37
48
|
|
data/bin/org-converge
CHANGED
data/lib/org-converge/command.rb
CHANGED
@@ -4,6 +4,7 @@ module OrgConverge
|
|
4
4
|
attr_reader :logger
|
5
5
|
attr_reader :ob
|
6
6
|
attr_reader :engine
|
7
|
+
attr_reader :runmode
|
7
8
|
|
8
9
|
def initialize(options)
|
9
10
|
@options = options
|
@@ -27,6 +28,9 @@ module OrgConverge
|
|
27
28
|
logger.formatter = proc do |severity, datetime, progname, msg|
|
28
29
|
"[#{datetime.strftime('%Y-%m-%dT%H:%M:%S %z')}] #{msg}\n"
|
29
30
|
end
|
31
|
+
|
32
|
+
# Keep track of the exit status from the process for idempotency checks
|
33
|
+
@procs_exit_status = Hash.new { |h,k| h[k] = { } }
|
30
34
|
end
|
31
35
|
|
32
36
|
def execute!
|
@@ -48,7 +52,7 @@ module OrgConverge
|
|
48
52
|
|
49
53
|
def converge!
|
50
54
|
tangle!
|
51
|
-
runmode = @options['--runmode'] || ob.in_buffer_settings['RUNMODE']
|
55
|
+
@runmode = @options['--runmode'] || ob.in_buffer_settings['RUNMODE']
|
52
56
|
case
|
53
57
|
when @options['--name']
|
54
58
|
if runmode == 'sequentially'
|
@@ -65,7 +69,7 @@ module OrgConverge
|
|
65
69
|
case runmode
|
66
70
|
when 'parallel'
|
67
71
|
run_blocks_in_parallel!
|
68
|
-
when 'sequential'
|
72
|
+
when 'sequential', 'idempotent'
|
69
73
|
run_blocks_sequentially!
|
70
74
|
when 'chained', 'chain', 'tasks'
|
71
75
|
run_blocks_chain!
|
@@ -131,7 +135,6 @@ module OrgConverge
|
|
131
135
|
end
|
132
136
|
|
133
137
|
def run_blocks_sequentially!
|
134
|
-
@engine = OrgConverge::Engine.new(:logger => @logger, :babel => @babel)
|
135
138
|
babel.tangle_runnable_blocks!(@run_dir)
|
136
139
|
|
137
140
|
runlist_stack = []
|
@@ -141,17 +144,17 @@ module OrgConverge
|
|
141
144
|
|
142
145
|
while not runlist_stack.empty?
|
143
146
|
key, script = runlist_stack.shift
|
144
|
-
|
145
147
|
# Decision: Only run blocks which have a name
|
146
148
|
next unless script[:header][:name]
|
147
|
-
|
148
149
|
display_name = script[:header][:name]
|
149
|
-
with_running_engine
|
150
|
+
exit_status_list = with_running_engine(:runmode => @runmode) \
|
151
|
+
do |engine|
|
150
152
|
file = File.expand_path("#{@run_dir}/#{key}")
|
151
153
|
bin = determine_lang_bin(script)
|
152
154
|
cmd = "#{bin} #{file}"
|
153
155
|
run_procs(script, cmd, engine)
|
154
156
|
end
|
157
|
+
@procs_exit_status.merge!(exit_status_list)
|
155
158
|
end
|
156
159
|
logger.info "Run has completed successfully.".fg 'green'
|
157
160
|
end
|
@@ -209,7 +212,7 @@ module OrgConverge
|
|
209
212
|
file = File.expand_path("#{@run_dir}/#{key}")
|
210
213
|
bin = determine_lang_bin(script)
|
211
214
|
cmd = "#{bin} #{file}"
|
212
|
-
|
215
|
+
run_procs(script, cmd, engine)
|
213
216
|
end
|
214
217
|
end
|
215
218
|
logger.info "Run has completed successfully.".fg 'green'
|
@@ -344,6 +347,26 @@ module OrgConverge
|
|
344
347
|
def run_procs(script, cmd, engine=nil)
|
345
348
|
engine ||= @engine
|
346
349
|
display_name = script[:header][:name]
|
350
|
+
|
351
|
+
if @runmode == 'idempotent'
|
352
|
+
case
|
353
|
+
when script[:header][:if]
|
354
|
+
block_name = script[:header][:if]
|
355
|
+
exit_status = @procs_exit_status[block_name]
|
356
|
+
unless exit_status == 0
|
357
|
+
logger.info "#{display_name.fg 'green'} -- Skipped since :if clause matches check from '#{block_name.fg 'yellow'}'"
|
358
|
+
return
|
359
|
+
end
|
360
|
+
when script[:header][:unless]
|
361
|
+
block_name = script[:header][:unless]
|
362
|
+
exit_status = @procs_exit_status[block_name]
|
363
|
+
if exit_status == 0
|
364
|
+
logger.info "#{display_name.fg 'green'} -- Skipped since :unless clause matches check from '#{block_name.fg 'yellow'}'"
|
365
|
+
return
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
347
370
|
if script[:header][:procs]
|
348
371
|
procs = script[:header][:procs].to_i
|
349
372
|
1.upto(procs) do |i|
|
data/lib/org-converge/engine.rb
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
require 'foreman/engine'
|
6
6
|
require 'foreman/process'
|
7
7
|
require 'tco'
|
8
|
+
require 'fileutils'
|
8
9
|
|
9
10
|
module OrgConverge
|
10
11
|
class Engine < Foreman::Engine
|
@@ -23,6 +24,10 @@ module OrgConverge
|
|
23
24
|
# Code blocks whose start invocation is manipulated run inside a thread
|
24
25
|
@threads = []
|
25
26
|
@running_threads = { }
|
27
|
+
|
28
|
+
# Returns a list in the end with the exit status code from the code blocks
|
29
|
+
# that were run in parallel
|
30
|
+
@procs_exit_status = { }
|
26
31
|
end
|
27
32
|
|
28
33
|
# We allow other processes to exit with 0 status
|
@@ -33,7 +38,7 @@ module OrgConverge
|
|
33
38
|
watch_for_output
|
34
39
|
sleep 0.1
|
35
40
|
begin
|
36
|
-
status = watch_for_termination do
|
41
|
+
status = watch_for_termination do
|
37
42
|
@threads.each do |t|
|
38
43
|
unless t.alive?
|
39
44
|
t.exit
|
@@ -42,6 +47,8 @@ module OrgConverge
|
|
42
47
|
end
|
43
48
|
end
|
44
49
|
end while (@running.count > 0 or @running_threads.count > 0)
|
50
|
+
|
51
|
+
@procs_exit_status
|
45
52
|
end
|
46
53
|
|
47
54
|
# Overriden: we do not consider process formations
|
@@ -78,6 +85,7 @@ module OrgConverge
|
|
78
85
|
def register(name, command, options={})
|
79
86
|
options[:env] ||= env
|
80
87
|
options[:cwd] ||= File.dirname(command.split(" ").first)
|
88
|
+
|
81
89
|
process = OrgConverge::CodeBlockProcess.new(command, options)
|
82
90
|
@names[process] = name
|
83
91
|
@processes << process
|
@@ -125,6 +133,20 @@ module OrgConverge
|
|
125
133
|
rescue Errno::ECHILD
|
126
134
|
end
|
127
135
|
|
136
|
+
def termination_message_for(status)
|
137
|
+
n = name_for(status.pid).split('.').first
|
138
|
+
|
139
|
+
if status.exited?
|
140
|
+
@procs_exit_status[n] = status.exitstatus
|
141
|
+
"exited with code #{status.exitstatus}"
|
142
|
+
elsif status.signaled?
|
143
|
+
# TODO: How to handle exit by signals? Non-zero exit status so idempotency check fails?
|
144
|
+
"terminated by SIG#{Signal.list.invert[status.termsig]}"
|
145
|
+
else
|
146
|
+
"died a mysterious death"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
128
150
|
def name_for(pid)
|
129
151
|
process = nil
|
130
152
|
index = nil
|
@@ -144,46 +166,64 @@ module OrgConverge
|
|
144
166
|
# Need to expose the options to make the process be aware
|
145
167
|
# of the possible running mode (specially spec mode)
|
146
168
|
# and where to put the results output
|
147
|
-
require 'timeout'
|
148
169
|
class CodeBlockProcess < Foreman::Process
|
149
170
|
attr_reader :options
|
150
171
|
|
151
172
|
def run(options={})
|
152
173
|
env = @options[:env].merge(options[:env] || {})
|
153
174
|
output = options[:output] || $stdout
|
154
|
-
runner = "#{Foreman.runner}".shellescape
|
175
|
+
runner = "#{Foreman.runner}".shellescape
|
155
176
|
|
156
177
|
# whitelist the modifiers which manipulate how to the block is started
|
157
178
|
block_modifiers = { }
|
158
179
|
if options[:header]
|
159
180
|
block_modifiers[:waitfor] = options[:header][:waitsfor] || options[:header][:waitfor] || options[:header][:sleep]
|
160
181
|
block_modifiers[:timeout] = options[:header][:timeoutin] || options[:header][:timeout] || options[:header][:timeoutafter]
|
182
|
+
if options[:header][:dir]
|
183
|
+
block_modifiers[:cwd] = File.expand_path(File.join(self.options[:cwd], options[:header][:dir]))
|
184
|
+
end
|
161
185
|
end
|
162
186
|
|
163
187
|
pid = nil
|
164
188
|
thread = nil
|
165
|
-
process = nil
|
166
189
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
-
else
|
179
|
-
if Foreman.windows?
|
180
|
-
Dir.chdir(cwd) do
|
181
|
-
pid = Process.spawn env, expanded_command(env), :out => output, :err => output
|
182
|
-
end
|
190
|
+
process = proc do
|
191
|
+
wrapped_command = ''
|
192
|
+
if block_modifiers[:cwd]
|
193
|
+
@options[:cwd] = block_modifiers[:cwd]
|
194
|
+
# Need to adjust the path by having the run file at the same place
|
195
|
+
bin, original_script = command.split(' ')
|
196
|
+
new_script = File.join(block_modifiers[:cwd], ".#{options[:header][:name]}")
|
197
|
+
FileUtils.cp(original_script, new_script)
|
198
|
+
cmd = [bin, new_script].join(' ')
|
199
|
+
wrapped_command = "exec #{runner} -d '#{cwd}' -p -- #{cmd}"
|
183
200
|
else
|
184
201
|
wrapped_command = "exec #{runner} -d '#{cwd}' -p -- #{command}"
|
185
|
-
pid = Process.spawn env, wrapped_command, :out => output, :err => output
|
186
202
|
end
|
203
|
+
opts = { :out => output, :err => output }
|
204
|
+
pid = Process.spawn env, wrapped_command, opts
|
205
|
+
end
|
206
|
+
|
207
|
+
# In case we modify the run block, we run it in a Thread
|
208
|
+
# otherwise we continue treating it as a forked process.
|
209
|
+
if block_modifiers and (block_modifiers[:waitfor] || block_modifiers[:timeout] || block_modifiers[:dir])
|
210
|
+
waitfor = block_modifiers[:waitfor].to_i
|
211
|
+
timeout = block_modifiers[:timeout].to_i
|
212
|
+
|
213
|
+
thread = Thread.new do
|
214
|
+
sleep waitfor if waitfor > 0
|
215
|
+
pid = process.call
|
216
|
+
if timeout > 0
|
217
|
+
sleep timeout
|
218
|
+
# FIXME: Kill children properly
|
219
|
+
o = `ps -ef | awk '$3 == #{pid} { print $2 }'`
|
220
|
+
o.each_line { |cpid| Process.kill(:TERM, cpid.to_i) }
|
221
|
+
Process.kill(:TERM, pid)
|
222
|
+
Thread.current.kill
|
223
|
+
end
|
224
|
+
end
|
225
|
+
else
|
226
|
+
pid = process.call
|
187
227
|
end
|
188
228
|
|
189
229
|
# In case of thread, pid will be nil
|
data/lib/org-converge/version.rb
CHANGED
@@ -7,6 +7,7 @@ We have the following process, but it will take 5 seconds to start...
|
|
7
7
|
echo "Wait..."
|
8
8
|
for i in `seq 1 4`;
|
9
9
|
do
|
10
|
+
echo $i
|
10
11
|
echo $i >> out.log
|
11
12
|
sleep 1
|
12
13
|
done
|
@@ -21,7 +22,7 @@ echo "whoosh" > out.log
|
|
21
22
|
#+end_src
|
22
23
|
|
23
24
|
#+name: timeout-in-3-seconds
|
24
|
-
#+begin_src sh :timeout
|
25
|
+
#+begin_src sh :timeout 5
|
25
26
|
while true; do
|
26
27
|
echo "Eventually will timeout..."
|
27
28
|
sleep 1
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#+TITLE: Changing directories locally
|
2
|
+
#+runmode: sequential
|
3
|
+
|
4
|
+
Like in the original Org babel from Emacs, it should be possible
|
5
|
+
to run the block with a different root. This avoids having to implement
|
6
|
+
changing dir within the language as well.
|
7
|
+
|
8
|
+
#+begin_src python :tangle subdir/greetings/greetings.py :mkdirp true
|
9
|
+
def hello():
|
10
|
+
f = open('out.log', 'w')
|
11
|
+
f.write("Hi\n")
|
12
|
+
print "Finished writing."
|
13
|
+
#+end_src
|
14
|
+
|
15
|
+
#+begin_src python :tangle subdir/greetings/__init__.py :mkdirp true
|
16
|
+
# greetings module
|
17
|
+
#+end_src
|
18
|
+
|
19
|
+
#+name: load-and-greet-test
|
20
|
+
#+begin_src python :results output code :dir subdir
|
21
|
+
from greetings import greetings
|
22
|
+
|
23
|
+
print dir(greetings)
|
24
|
+
|
25
|
+
for i in range(0, 10):
|
26
|
+
greetings.hello()
|
27
|
+
#+end_src
|
28
|
+
|
29
|
+
#+name: path-test
|
30
|
+
#+begin_src python :results output code :dir subdir
|
31
|
+
import os
|
32
|
+
|
33
|
+
print os.getcwd()
|
34
|
+
print os.path.realpath(__file__)
|
35
|
+
print os.path.dirname(os.path.realpath(__file__))
|
36
|
+
#+end_src
|
37
|
+
|
38
|
+
#+name: bash-cwd-text
|
39
|
+
#+begin_src sh :results output :dir subdir
|
40
|
+
echo "within subdir" > out.log
|
41
|
+
cat out.log
|
42
|
+
#+end_src
|
@@ -0,0 +1,158 @@
|
|
1
|
+
#+TITLE: Idempotency examples
|
2
|
+
#+runmode: sequential
|
3
|
+
|
4
|
+
First steps towards achieving idempotency.
|
5
|
+
All of these are identified when tangling and during execution.
|
6
|
+
|
7
|
+
- Example resources
|
8
|
+
+ command
|
9
|
+
exit status 1 means that the block should be run
|
10
|
+
exit status 0 means that it should not be run
|
11
|
+
+ directory
|
12
|
+
Can be covered by :mkdirp
|
13
|
+
+ package
|
14
|
+
If package is in the dpkg -l output, don't install
|
15
|
+
+ template
|
16
|
+
Makes sense only when tangling.
|
17
|
+
If there was a diff in the template, then apply and notify another block
|
18
|
+
+ file
|
19
|
+
if it exists then run
|
20
|
+
else do not run it
|
21
|
+
|
22
|
+
*** DONE When =:if <block>= is used, it will execute the block unless conditional block returns 0
|
23
|
+
|
24
|
+
The most general case is when we link 2 different code blocks
|
25
|
+
so that one can define whether the second one should be executed.
|
26
|
+
|
27
|
+
In order to achieve this, the blocks need to be defined sequentially
|
28
|
+
this way it will be checked whether sinatra is installed or not first,
|
29
|
+
and use the exit status when considering to start the application.
|
30
|
+
|
31
|
+
*NOTE*: Because of this constraint, parallel runs cannot run in converge mode.
|
32
|
+
Only sequential runs supported.
|
33
|
+
|
34
|
+
#+name: install-package
|
35
|
+
#+begin_src sh
|
36
|
+
echo "brew install something..."
|
37
|
+
echo "package is installed" > installed
|
38
|
+
#+end_src
|
39
|
+
|
40
|
+
#+name: package-already-installed
|
41
|
+
#+begin_src sh
|
42
|
+
if [ -e installed ]; then
|
43
|
+
echo "Already installed"
|
44
|
+
exit 0
|
45
|
+
else
|
46
|
+
echo "Needs install"
|
47
|
+
exit 1
|
48
|
+
fi
|
49
|
+
#+end_src
|
50
|
+
|
51
|
+
#+name: install-package-once-again
|
52
|
+
#+begin_src sh :unless package-already-installed
|
53
|
+
echo "Installing the package once again..."
|
54
|
+
echo "not run" >> installed
|
55
|
+
#+end_src
|
56
|
+
|
57
|
+
#+name: do-everything-even-if-package-installed
|
58
|
+
#+begin_src sh :if package-already-installed
|
59
|
+
echo "Doing this even if installed already..."
|
60
|
+
echo "eof" >> installed
|
61
|
+
#+end_src
|
62
|
+
|
63
|
+
*** COMMENT When it has a results block, then it will be executed unless it matches the spec
|
64
|
+
|
65
|
+
Here they would be run sequentially, but it would be better if the =:assert= block
|
66
|
+
can be lazily invoked when deploy-app is about to run, not during the preparation step
|
67
|
+
which happens sequentially.
|
68
|
+
|
69
|
+
#+name: ruby-version-installed
|
70
|
+
#+begin_src sh :results output code :exports none
|
71
|
+
ruby --version | awk '{ print $2 }'
|
72
|
+
#+end_src
|
73
|
+
|
74
|
+
#+RESULTS: ruby-version-installed
|
75
|
+
#+BEGIN_SRC sh
|
76
|
+
1.8.7
|
77
|
+
#+END_SRC
|
78
|
+
|
79
|
+
#+name: deploy-app
|
80
|
+
#+begin_src sh :assert ruby-version-installed
|
81
|
+
echo "Can deploy app because correct Ruby is installed"
|
82
|
+
#+end_src
|
83
|
+
|
84
|
+
*** COMMENT When =:if file-exists :at <path>= is used, it will execute the block unless the file exists
|
85
|
+
|
86
|
+
#+name: execute-if-file-exists
|
87
|
+
#+begin_src sh :if file-exists :at /var/run/ntpd.pid
|
88
|
+
echo "Starting process because ntpd file exists exists.."
|
89
|
+
#+end_src
|
90
|
+
|
91
|
+
These =file-exists= kind of checks can be pluggable.
|
92
|
+
|
93
|
+
*** COMMENT Ideas
|
94
|
+
**** TODO How to support gated checks in parallel runs?
|
95
|
+
|
96
|
+
Let's say that we have a run which makes a healthcheck in the end.
|
97
|
+
In this case, it would mean that a healthcheck would be run
|
98
|
+
once run-web-app is alive.
|
99
|
+
|
100
|
+
Run a healthcheck for the application in the end
|
101
|
+
to confirm that it boot up correctly:
|
102
|
+
|
103
|
+
#+begin_src ruby :tangle sinatra/app.rb :mkdirp true
|
104
|
+
require 'sinatra'
|
105
|
+
|
106
|
+
get '/' do
|
107
|
+
"OK\n"
|
108
|
+
end
|
109
|
+
#+end_src
|
110
|
+
|
111
|
+
***** Check if Sinatra is installed at least
|
112
|
+
:PROPERTIES:
|
113
|
+
:SRC_ORDER: sequential
|
114
|
+
:END:
|
115
|
+
|
116
|
+
One idea is to accumulate them in case they are under
|
117
|
+
the same headline, meaning that runlists can be grouped.
|
118
|
+
|
119
|
+
#+name: sinatra-is-installed
|
120
|
+
#+begin_src sh
|
121
|
+
echo "Checking if sinatra is installed"
|
122
|
+
gem list | grep sinatra
|
123
|
+
#+end_src
|
124
|
+
|
125
|
+
...then run it as follows:
|
126
|
+
|
127
|
+
#+name: install-sinatra
|
128
|
+
#+begin_src sh :unless sinatra-is-installed
|
129
|
+
gem install sinatra
|
130
|
+
#+end_src
|
131
|
+
|
132
|
+
A block which is not executed due to an idempotency check
|
133
|
+
is equivalent to another one that ended with exit status 0.
|
134
|
+
|
135
|
+
#+name: server-start
|
136
|
+
#+begin_src sh :timeout 5 :if install-sinatra
|
137
|
+
ruby sinatra/app.rb
|
138
|
+
#+end_src
|
139
|
+
|
140
|
+
***** Run a healthcheck for the sinatra application
|
141
|
+
:PROPERTIES:
|
142
|
+
:SRC_ORDER: sequential
|
143
|
+
:END:
|
144
|
+
|
145
|
+
#+name: healthcheck-sinatra-app
|
146
|
+
#+begin_src sh :sleep 3 :timeout 10 :awaits server-start
|
147
|
+
while true; do
|
148
|
+
curl 127.0.0.1:4567 2> /dev/null
|
149
|
+
if [ $? != 0 ]; then
|
150
|
+
echo "NOT OK"
|
151
|
+
fi
|
152
|
+
sleep 1
|
153
|
+
done
|
154
|
+
#+end_src
|
155
|
+
|
156
|
+
#+begin_src sh
|
157
|
+
echo "Run"
|
158
|
+
#+end_src
|
data/spec/converge_spec.rb
CHANGED
@@ -159,4 +159,33 @@ describe OrgConverge::Command do
|
|
159
159
|
result = File.open("#{example_dir}/out.log").read
|
160
160
|
result.should == "whoosh\n1\n2\n3\n4\n"
|
161
161
|
end
|
162
|
+
|
163
|
+
it "should be able to chdir the process directory" do
|
164
|
+
example_dir = File.join(EXAMPLES_DIR, 'chdir')
|
165
|
+
setup_file = File.join(example_dir, 'local-run.org')
|
166
|
+
|
167
|
+
o = OrgConverge::Command.new({
|
168
|
+
'<org_file>' => setup_file,
|
169
|
+
'--root-dir' => example_dir
|
170
|
+
})
|
171
|
+
success = o.execute!
|
172
|
+
success.should == true
|
173
|
+
result = File.open("#{example_dir}/subdir/out.log").read
|
174
|
+
result.should == "within subdir\n"
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should support idempotency checks via :if and :unless conditional clauses" do
|
178
|
+
example_dir = File.join(EXAMPLES_DIR, 'idempotency')
|
179
|
+
setup_file = File.join(example_dir, 'conditions.org')
|
180
|
+
|
181
|
+
o = OrgConverge::Command.new({
|
182
|
+
'<org_file>' => setup_file,
|
183
|
+
'--root-dir' => example_dir,
|
184
|
+
'--runmode' => 'idempotent'
|
185
|
+
})
|
186
|
+
success = o.execute!
|
187
|
+
success.should == true
|
188
|
+
result = File.open("#{example_dir}/installed").read
|
189
|
+
result.should == "package is installed\neof\n"
|
190
|
+
end
|
162
191
|
end
|
data/vagrant.org
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
#+TITLE: Vagrant environment setup
|
2
|
+
#+startup: showeverything
|
3
|
+
|
4
|
+
**** Importing the Vagrant keys first
|
5
|
+
|
6
|
+
#+begin_src text :tangle vagrant/.git/info/sparse-checkout :mkdirp true
|
7
|
+
keys
|
8
|
+
#+end_src
|
9
|
+
|
10
|
+
#+name: import-vagrant-keys-done
|
11
|
+
#+begin_src sh :results output
|
12
|
+
[ -e vagrant/keys/vagrant ] && echo "Already cloned"
|
13
|
+
#+end_src
|
14
|
+
|
15
|
+
#+name: import-vagrant-keys
|
16
|
+
#+begin_src sh :unless import-vagrant-keys-done
|
17
|
+
cd vagrant
|
18
|
+
git init
|
19
|
+
git remote add origin https://github.com/mitchellh/vagrant.git
|
20
|
+
git config core.sparsecheckout true
|
21
|
+
git pull origin master
|
22
|
+
git checkout master
|
23
|
+
chmod 0600 keys/vagrant
|
24
|
+
#+end_src
|
25
|
+
|
26
|
+
**** Vagrantfile for Ubuntu 14.04
|
27
|
+
|
28
|
+
#+begin_src ruby :tangle Vagrantfile
|
29
|
+
# -*- mode: ruby -*-
|
30
|
+
# vi: set ft=ruby :
|
31
|
+
|
32
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
33
|
+
VAGRANTFILE_API_VERSION = "2"
|
34
|
+
|
35
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
36
|
+
config.vm.box = "ubuntu-14.04-amd64-vbox.box"
|
37
|
+
config.vm.box_url = "https://oss-binaries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-amd64-vbox.box"
|
38
|
+
|
39
|
+
# config.vm.network :forwarded_port, guest: 80, host: 8080
|
40
|
+
# config.vm.network :private_network, ip: "192.168.33.10"
|
41
|
+
# config.vm.network :public_network
|
42
|
+
# config.ssh.forward_agent = true
|
43
|
+
|
44
|
+
config.vm.provider :virtualbox do |vb|
|
45
|
+
vb.gui = true
|
46
|
+
vb.customize ["modifyvm", :id, "--memory", "1024"]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
#+end_src
|
50
|
+
|
51
|
+
***** Import
|
52
|
+
|
53
|
+
#+name: vagrant-running
|
54
|
+
#+begin_src sh
|
55
|
+
vagrant status
|
56
|
+
#+end_src
|
57
|
+
|
58
|
+
#+name: start_vagrant
|
59
|
+
#+begin_src sh :unless vagrant-running
|
60
|
+
vagrant up
|
61
|
+
#+end_src
|
62
|
+
|
63
|
+
***** Configure
|
64
|
+
|
65
|
+
Install Emacs, Org mode and Org Converge in the VM.
|
66
|
+
|
67
|
+
#+name: running-in-ubuntu
|
68
|
+
#+begin_src sh :results output
|
69
|
+
platform=`uname -a | awk '{print $2}'`
|
70
|
+
if [ $platform == "ubuntu-14" ]; then
|
71
|
+
echo "OK"
|
72
|
+
exit 0
|
73
|
+
else
|
74
|
+
echo "Only works in Ubuntu"
|
75
|
+
exit 1
|
76
|
+
fi
|
77
|
+
#+end_src
|
78
|
+
|
79
|
+
#+name: apt-get-install
|
80
|
+
#+begin_src sh :dir vagrant@localhost:2222/ :if running-in-ubuntu
|
81
|
+
sudo apt-get update
|
82
|
+
sudo apt-get install build-essentials emacs24-nox org-mode -y
|
83
|
+
#+end_src
|
84
|
+
|
85
|
+
**** Vagrantfile :: Docker provider
|
86
|
+
|
87
|
+
#+begin_src ruby :tangle docker/Vagrantfile :mkdirp true
|
88
|
+
Vagrant.configure("2") do |config|
|
89
|
+
config.vm.provider "docker" do |d|
|
90
|
+
d.build_dir = "."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
#+end_src
|
94
|
+
|
95
|
+
#+begin_src conf :tangle docker/Dockerfile
|
96
|
+
FROM ubuntu
|
97
|
+
RUN apt-get -y update
|
98
|
+
RUN apt-get -y install emacs24-nox org-mode
|
99
|
+
#+end_src
|
100
|
+
|
101
|
+
#+name: vagrant-docker-provider
|
102
|
+
#+begin_src sh :dir docker
|
103
|
+
vagrant up --provider=docker
|
104
|
+
#+end_src
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: org-converge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Waldemar Quevedo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docopt
|
@@ -131,9 +131,11 @@ files:
|
|
131
131
|
- spec/converge_examples/basic_tangle/conf.yml.expected
|
132
132
|
- spec/converge_examples/basic_tangle/setup.org
|
133
133
|
- spec/converge_examples/block_modifiers/run.org
|
134
|
+
- spec/converge_examples/chdir/local-run.org
|
134
135
|
- spec/converge_examples/commented_block/run.org
|
135
136
|
- spec/converge_examples/expected_results/spec.org
|
136
137
|
- spec/converge_examples/expected_results/spec2.org
|
138
|
+
- spec/converge_examples/idempotency/conditions.org
|
137
139
|
- spec/converge_examples/linked_tasks/tasks.org
|
138
140
|
- spec/converge_examples/multi_proc/run.org
|
139
141
|
- spec/converge_examples/runlist_example/setup.org
|
@@ -141,6 +143,7 @@ files:
|
|
141
143
|
- spec/converge_examples/specified_block/run.org
|
142
144
|
- spec/converge_spec.rb
|
143
145
|
- spec/spec_helper.rb
|
146
|
+
- vagrant.org
|
144
147
|
homepage: https://github.com/wallyqs/org-converge
|
145
148
|
licenses: []
|
146
149
|
metadata: {}
|
@@ -170,9 +173,11 @@ test_files:
|
|
170
173
|
- spec/converge_examples/basic_tangle/conf.yml.expected
|
171
174
|
- spec/converge_examples/basic_tangle/setup.org
|
172
175
|
- spec/converge_examples/block_modifiers/run.org
|
176
|
+
- spec/converge_examples/chdir/local-run.org
|
173
177
|
- spec/converge_examples/commented_block/run.org
|
174
178
|
- spec/converge_examples/expected_results/spec.org
|
175
179
|
- spec/converge_examples/expected_results/spec2.org
|
180
|
+
- spec/converge_examples/idempotency/conditions.org
|
176
181
|
- spec/converge_examples/linked_tasks/tasks.org
|
177
182
|
- spec/converge_examples/multi_proc/run.org
|
178
183
|
- spec/converge_examples/runlist_example/setup.org
|