org-converge 0.0.1 → 0.0.2
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.
- data/.travis.yml +5 -0
- data/README.md +130 -0
- data/Rakefile +2 -0
- data/TODO +52 -20
- data/lib/org-converge.rb +10 -3
- data/lib/org-converge/babel.rb +22 -1
- data/lib/org-converge/babel_output_buffer.rb +18 -7
- data/lib/org-converge/command.rb +29 -10
- data/lib/org-converge/engine.rb +87 -0
- data/lib/org-converge/version.rb +1 -1
- data/org-converge.gemspec +1 -0
- data/spec/converge_examples/basic_run_example/setup.org +31 -0
- metadata +23 -6
data/.travis.yml
ADDED
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
Org Converge
|
2
|
+
------------
|
3
|
+
[](https://travis-ci.org/wallyqs/org-converge)
|
4
|
+
|
5
|
+
# Description
|
6
|
+
|
7
|
+
A tool which uses Org mode syntax to describe, configure and
|
8
|
+
setup something, borrowing some ideas of what is possible to
|
9
|
+
do with tools like `chef-solo`, `puppet`, `ansible`, etc...
|
10
|
+
|
11
|
+
Can also be used for tangling code blocks like Org Babel does.
|
12
|
+
|
13
|
+
# Installing
|
14
|
+
|
15
|
+
$ gem install org-converge
|
16
|
+
|
17
|
+
# Motivation
|
18
|
+
|
19
|
+
The Org babel syntax has proven to be flexible enough to produce
|
20
|
+
*reproducible research* papers. Then, I believe that configuring and setting up
|
21
|
+
a server for example is something that could be also be done using
|
22
|
+
the same syntax, given that *converging* the configuration is something
|
23
|
+
that one ought to be able to reproduce.
|
24
|
+
|
25
|
+
# Example usage
|
26
|
+
|
27
|
+
$ org-converge spec/converge_examples/basic_tangle/setup.org --showfiles
|
28
|
+
|
29
|
+
---------- conf.yml --------------
|
30
|
+
bind: 0.0.0.0
|
31
|
+
port: 2442
|
32
|
+
|
33
|
+
mysql:
|
34
|
+
db: users
|
35
|
+
host: somewhere-example.local
|
36
|
+
password: 111111111
|
37
|
+
|
38
|
+
$ org-converge spec/converge_examples/basic_tangle/setup.org --tangle
|
39
|
+
|
40
|
+
I, [2014-03-24T00:21:08.073506 #660] INFO -- : Tangling 1 files...
|
41
|
+
I, [2014-03-24T00:21:08.073668 #660] INFO -- : BEGIN(conf.yml): Tangling 7 lines at 'conf.yml'
|
42
|
+
I, [2014-03-24T00:21:08.075562 #660] INFO -- : END(conf.yml): done.
|
43
|
+
I, [2014-03-24T00:21:08.075638 #660] INFO -- : Tangling succeeded!
|
44
|
+
|
45
|
+
# How it works
|
46
|
+
|
47
|
+
Org Converge uses an liberally extended version of Org Babel
|
48
|
+
features in order to give support for converging the configuration
|
49
|
+
of a server.
|
50
|
+
|
51
|
+
For example, using Org Babel and macros we can easily spread config
|
52
|
+
files on a server by writing the following on a `server.org` file.
|
53
|
+
|
54
|
+
```org
|
55
|
+
#+MACRO: multitenancy_enabled true
|
56
|
+
#+MACRO: status_port true
|
57
|
+
|
58
|
+
#+begin_src yaml :tangle /etc/component.yml
|
59
|
+
multitenant: false
|
60
|
+
status_port: 10004
|
61
|
+
#+end_src
|
62
|
+
```
|
63
|
+
|
64
|
+
And then configure it by running it as follows, (considering we have
|
65
|
+
the correct permissions):
|
66
|
+
|
67
|
+
```sh
|
68
|
+
$ org-converge server.org
|
69
|
+
```
|
70
|
+
|
71
|
+
This leverages on the syntax already provided by Org Babel, but one
|
72
|
+
difference here is that if we run it once again without changes...
|
73
|
+
|
74
|
+
```sh
|
75
|
+
$ org-converge server.org
|
76
|
+
```
|
77
|
+
|
78
|
+
...it would finish soon since the configuration has already converged.
|
79
|
+
|
80
|
+
Next, let's say that we no only one want to set the configured templates,
|
81
|
+
but that we also want to install some packages. In that case, we
|
82
|
+
should be able to do the following:
|
83
|
+
|
84
|
+
```org
|
85
|
+
#+macro: multitenancy_enabled true
|
86
|
+
#+macro: status_port true
|
87
|
+
#+macro: project_path path/to/project
|
88
|
+
|
89
|
+
* Configuring the component
|
90
|
+
|
91
|
+
#+begin_src yaml :tangle /etc/component.yml
|
92
|
+
multitenant: false
|
93
|
+
status_port: 10004
|
94
|
+
#+end_src
|
95
|
+
|
96
|
+
* Installing the dependencies
|
97
|
+
|
98
|
+
Need the following so that ~bundle install~ can compile
|
99
|
+
the native extensions correctly.
|
100
|
+
|
101
|
+
#+begin_src sh
|
102
|
+
apt-get install build-essentials -y
|
103
|
+
#+end_src
|
104
|
+
|
105
|
+
Then the following should work:
|
106
|
+
|
107
|
+
#+begin_src sh
|
108
|
+
cd {{{project_path}}}
|
109
|
+
bundle install
|
110
|
+
#+end_src
|
111
|
+
```
|
112
|
+
|
113
|
+
As long as the repo has been already checked out in the directory,
|
114
|
+
the previous example will succeed.
|
115
|
+
|
116
|
+
```sh
|
117
|
+
org-converge server.org
|
118
|
+
```
|
119
|
+
|
120
|
+
If that is not the case, then org-converge will fail
|
121
|
+
and pickup from that last step.
|
122
|
+
|
123
|
+
More practical examples can be found in the examples directory, more will be added as
|
124
|
+
long as dogfooding from this goes well.
|
125
|
+
|
126
|
+
# Contributing
|
127
|
+
|
128
|
+
The project is in very early development at this moment, but if you
|
129
|
+
feel that it is interesting enough, please create a ticket to start
|
130
|
+
the discussion.
|
data/Rakefile
CHANGED
data/TODO
CHANGED
@@ -2,21 +2,28 @@
|
|
2
2
|
#+TODO: TODO | DONE CANCELED
|
3
3
|
#+startup: showeverything
|
4
4
|
|
5
|
-
* [
|
5
|
+
* [/] 0.0.4 version
|
6
6
|
|
7
7
|
- [ ] Macros can be loaded and applied to the configuration
|
8
8
|
- [ ] Actually support converging and idempotency
|
9
9
|
+ Do not do an operation unless it is required
|
10
10
|
+ Abort in case there was a failure in executing the script.
|
11
|
+
- [ ] Support SETUPFILE
|
12
|
+
- [ ] Heuristics for determining which binary to use for running the script
|
13
|
+
- [ ] Display how the run would look like without making changes
|
14
|
+
: org-converge setupfile.org --dry-run
|
15
|
+
|
16
|
+
* [0/3] 0.0.3 version
|
17
|
+
|
18
|
+
- [ ] Support run lists for sequential execution
|
11
19
|
|
12
|
-
* [
|
20
|
+
* [2/2] 0.0.2 version of org-converge
|
13
21
|
|
14
22
|
Run the code blocks!
|
15
23
|
|
16
|
-
- [
|
17
|
-
Only when
|
18
|
-
- [
|
19
|
-
: org-converge setupfile.org --dry-run
|
24
|
+
- [X] Code blocks are executed by default after tangling in temp dir
|
25
|
+
Only when ~:shebang~ exists as an argument
|
26
|
+
- [X] Default parallel execution of blocks
|
20
27
|
|
21
28
|
* [3/3] 0.0.1 version
|
22
29
|
|
@@ -28,20 +35,7 @@ Need some basic functionality of what Org babel offers first.
|
|
28
35
|
- [X] ~--tangle~ flag
|
29
36
|
- [X] Support a root dir for when not running relative to the directory
|
30
37
|
|
31
|
-
* [
|
32
|
-
** CANCELED We don't need to create the directories in most cases
|
33
|
-
|
34
|
-
Something like this is not required because the ~:tangle~ blocks
|
35
|
-
would create the necessary directories behind the scenes.
|
36
|
-
|
37
|
-
#+begin_src org
|
38
|
-
,We need to prepare some directories for the configuration:
|
39
|
-
|
40
|
-
,#+begin_src converge
|
41
|
-
,mkdir -p etc/fluentd/config
|
42
|
-
,#+end_src
|
43
|
-
#+end_src
|
44
|
-
|
38
|
+
* [1/18] Ideas
|
45
39
|
** CANCELED How to set the permissions from the directory from the file that is being tangled when it does not exists?
|
46
40
|
|
47
41
|
By default, this would be 0644, but we also need to specify the
|
@@ -53,6 +47,22 @@ hmm dont't like this syntax for folders
|
|
53
47
|
|
54
48
|
Let's keep it simple and just use a babel block that shells out to create the directories
|
55
49
|
until I can think of something better.
|
50
|
+
** TODO Clarify which ones of the header arguments to implement
|
51
|
+
|
52
|
+
http://orgmode.org/manual/Specific-header-arguments.html#Specific-header-arguments
|
53
|
+
|
54
|
+
** TODO We don't need to create the directories in most cases (:mkdirp yes)
|
55
|
+
|
56
|
+
Something like this is not required because the ~:tangle~ blocks
|
57
|
+
would create the necessary directories behind the scenes.
|
58
|
+
|
59
|
+
#+begin_src org
|
60
|
+
,We need to prepare some directories for the configuration:
|
61
|
+
|
62
|
+
,#+begin_src converge
|
63
|
+
,mkdir -p etc/fluentd/config
|
64
|
+
,#+end_src
|
65
|
+
#+end_src
|
56
66
|
|
57
67
|
** TODO By default, it should use current dir for tangling
|
58
68
|
** TODO Converging: Only do an operation when it didn't finish
|
@@ -165,3 +175,25 @@ sudo service td-agent start
|
|
165
175
|
#+begin_src sh
|
166
176
|
sudo /etc/register-to-balancer
|
167
177
|
#+end_src
|
178
|
+
|
179
|
+
** TODO ~#+NAME:~ could be used in the logger for identifying the process
|
180
|
+
** TODO Support caching?
|
181
|
+
|
182
|
+
#+begin_src emacs-lisp :cache yes :exports results
|
183
|
+
(random)
|
184
|
+
#+end_src
|
185
|
+
|
186
|
+
#+RESULTS[db54597aed193d861d01bf92110e10f28f8f40d4]:
|
187
|
+
: 842438499349743708
|
188
|
+
|
189
|
+
** TODO Support :eval ?
|
190
|
+
|
191
|
+
#+begin_src sh :eval (print "Really doing this...")
|
192
|
+
echo "Going ahead with operation X!"
|
193
|
+
#+end_src
|
194
|
+
|
195
|
+
* Links
|
196
|
+
|
197
|
+
Super useful notes:
|
198
|
+
http://eschulte.github.io/org-scraps
|
199
|
+
|
data/lib/org-converge.rb
CHANGED
@@ -2,6 +2,7 @@ require 'org-ruby'
|
|
2
2
|
require 'org-converge/babel_output_buffer'
|
3
3
|
require 'org-converge/babel'
|
4
4
|
require 'org-converge/command'
|
5
|
+
require 'org-converge/engine'
|
5
6
|
require 'org-converge/version'
|
6
7
|
|
7
8
|
module Orgmode
|
@@ -25,9 +26,15 @@ module Orgmode
|
|
25
26
|
end
|
26
27
|
|
27
28
|
module StringWithColors
|
28
|
-
def red;
|
29
|
-
def green;
|
30
|
-
def yellow;
|
29
|
+
def red; colorize("\e[0m\e[31m"); end
|
30
|
+
def green; colorize("\e[0m\e[32m"); end
|
31
|
+
def yellow; colorize("\e[0m\e[33m"); end
|
32
|
+
def blue; colorize("\e[0m\e[34m"); end
|
33
|
+
def magenta; colorize("\e[0m\e[35m"); end
|
34
|
+
def cyan; colorize("\e[0m\e[36m"); end
|
35
|
+
def white; colorize("\e[0m\e[37m"); end
|
36
|
+
def bright_black; colorize("\e[0m\e[30m"); end
|
37
|
+
def bright_magenta; colorize("\e[0m\e[35m"); end
|
31
38
|
def bold; colorize("\e[0m\e[1m"); end
|
32
39
|
def colorize(color_code); "#{color_code}#{self}\e[0m"; end
|
33
40
|
end
|
data/lib/org-converge/babel.rb
CHANGED
@@ -29,7 +29,9 @@ module Orgmode
|
|
29
29
|
|
30
30
|
logger.info "BEGIN(#{tangle_file}): Tangling #{lines.count} lines at '#{file}'"
|
31
31
|
# TODO: should abort when the directory does not exists
|
32
|
+
# Org mode blocks have :mkdirp true
|
32
33
|
# TODO: should abort when the directory failed because of permissions
|
34
|
+
# TODO: should apply :tangle-mode for permissions
|
33
35
|
if not Dir.exists?(File.dirname(file))
|
34
36
|
logger.error "Could not tangle #{file} because directory does not exists!"
|
35
37
|
raise TangleError
|
@@ -52,7 +54,26 @@ module Orgmode
|
|
52
54
|
logger.info "END(#{file}): done."
|
53
55
|
end
|
54
56
|
|
55
|
-
logger.info "Tangling succeeded!"
|
57
|
+
logger.info "Tangling succeeded!"
|
58
|
+
end
|
59
|
+
|
60
|
+
def tangle_runnable_blocks!(run_dir='run')
|
61
|
+
FileUtils.mkdir_p(run_dir)
|
62
|
+
|
63
|
+
logger.info "Tangling #{ob.scripts.count} scripts within directory: #{run_dir}..."
|
64
|
+
|
65
|
+
ob.scripts.each_pair do |script_key, script|
|
66
|
+
file = script_key.to_s
|
67
|
+
if File.exists?(file)
|
68
|
+
logger.warn "File already exists at #{file}, it will be overwritten"
|
69
|
+
end
|
70
|
+
|
71
|
+
File.open(File.join(run_dir, file), 'w') do |f|
|
72
|
+
script[:lines].each_line do |line|
|
73
|
+
f.puts line
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
56
77
|
end
|
57
78
|
|
58
79
|
class TangleError < Exception; end
|
@@ -12,12 +12,13 @@ module Orgmode
|
|
12
12
|
|
13
13
|
# ~@scripts~ are tangled in order and ran
|
14
14
|
# : @scripts = [text, text, ...]
|
15
|
-
@scripts = []
|
15
|
+
@scripts = Hash.new {|h,k| h[k] = {:lines => '', :header => {}, :lang => ''}}
|
16
|
+
@scripts_counter = 0
|
16
17
|
|
17
18
|
@buffer = ''
|
18
19
|
end
|
19
20
|
|
20
|
-
def push_mode(mode, indent)
|
21
|
+
def push_mode(mode, indent);
|
21
22
|
super(mode, indent)
|
22
23
|
end
|
23
24
|
|
@@ -30,13 +31,21 @@ module Orgmode
|
|
30
31
|
def insert(line)
|
31
32
|
# We try to get the lang from #+BEGIN_SRC blocks
|
32
33
|
if line.begin_block?
|
33
|
-
|
34
|
-
|
34
|
+
case
|
35
|
+
when line.block_header_arguments[':tangle']
|
35
36
|
@current_tangle = line.block_header_arguments[':tangle']
|
36
|
-
|
37
|
-
@shebang = line.block_header_arguments[':shebang']
|
37
|
+
when line.block_header_arguments[':shebang']
|
38
38
|
@current_tangle = nil
|
39
39
|
@buffer = ''
|
40
|
+
|
41
|
+
# Need to keep track of the options from a block before running it
|
42
|
+
@scripts[@scripts_counter][:header] = {
|
43
|
+
:shebang => line.block_header_arguments[':shebang']
|
44
|
+
}
|
45
|
+
@scripts[@scripts_counter][:lang] = line.block_lang
|
46
|
+
|
47
|
+
# TODO: have a way to specify which are the default binaries to be used per language
|
48
|
+
# when binary_detected?(@block_lang)
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
@@ -51,8 +60,9 @@ module Orgmode
|
|
51
60
|
when (!@buffer.empty? and not (line.begin_block? or line.assigned_paragraph_type == :code))
|
52
61
|
# Fix indentation and remove pre fix commas from Org mode before flushing
|
53
62
|
strip_code_block!
|
54
|
-
@scripts << @buffer
|
63
|
+
@scripts[@scripts_counter][:lines] << @buffer
|
55
64
|
@buffer = ''
|
65
|
+
@scripts_counter += 1
|
56
66
|
end
|
57
67
|
|
58
68
|
@output_type = line.assigned_paragraph_type || line.paragraph_type
|
@@ -66,6 +76,7 @@ module Orgmode
|
|
66
76
|
# TODO: This should be in the parent class....
|
67
77
|
def output_footnotes!; false; end
|
68
78
|
|
79
|
+
# TODO: This should be part of some utils package from OrgRuby
|
69
80
|
def strip_code_block!
|
70
81
|
if @code_block_indent and @code_block_indent > 0
|
71
82
|
strip_regexp = Regexp.new("^" + " " * @code_block_indent)
|
data/lib/org-converge/command.rb
CHANGED
@@ -3,19 +3,21 @@ module OrgConverge
|
|
3
3
|
attr_reader :dotorg
|
4
4
|
attr_reader :logger
|
5
5
|
attr_reader :ob
|
6
|
+
attr_reader :engine
|
6
7
|
|
7
8
|
def initialize(options)
|
8
9
|
@options = options
|
9
10
|
@dotorg = options['<org_file>']
|
10
11
|
@logger = Logger.new(options['--log'] || STDOUT)
|
11
12
|
@root_dir = options['--root-dir']
|
12
|
-
@
|
13
|
+
@run_dir = File.expand_path('run')
|
14
|
+
@ob = Orgmode::Parser.new(File.read(dotorg)).babelize
|
15
|
+
@babel = nil
|
13
16
|
end
|
14
17
|
|
15
18
|
def execute!
|
16
19
|
case
|
17
20
|
when @options['--showfiles']
|
18
|
-
|
19
21
|
showfiles
|
20
22
|
when @options['--tangle']
|
21
23
|
tangle!
|
@@ -25,20 +27,37 @@ module OrgConverge
|
|
25
27
|
|
26
28
|
true
|
27
29
|
rescue => e
|
30
|
+
@logger.error e
|
28
31
|
false
|
29
32
|
end
|
30
33
|
|
31
34
|
def converge!
|
32
35
|
tangle!
|
36
|
+
run_blocks!
|
33
37
|
end
|
34
38
|
|
35
39
|
def tangle!
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
40
|
+
results = babel.tangle!
|
41
|
+
rescue Orgmode::Babel::TangleError
|
42
|
+
logger.error "Cannot converge because there were errors during tangle step".red
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO: Too much foreman has made this running blocks in parallel the default behavior.
|
46
|
+
# We should actually be supporting run lists instead, but liking this experiment so far.
|
47
|
+
def run_blocks!
|
48
|
+
@engine = OrgConverge::Engine.new(:logger => @logger, :babel => @babel)
|
49
|
+
babel.tangle_runnable_blocks!(@run_dir)
|
50
|
+
babel.ob.scripts.each do |key, script|
|
51
|
+
file = File.expand_path("#{@run_dir}/#{key}")
|
52
|
+
cmd = "#{script[:lang]} #{file}"
|
53
|
+
@engine.register script[:lang], cmd, { :cwd => @root_dir, :logger => logger }
|
41
54
|
end
|
55
|
+
logger.info "Running code blocks now! (#{babel.ob.scripts.count} runnable blocks found in total)"
|
56
|
+
@engine.start
|
57
|
+
end
|
58
|
+
|
59
|
+
def babel
|
60
|
+
@babel ||= Orgmode::Babel.new(ob, { :logger => @logger, :root_dir => @root_dir })
|
42
61
|
end
|
43
62
|
|
44
63
|
def showfiles
|
@@ -49,9 +68,9 @@ module OrgConverge
|
|
49
68
|
end
|
50
69
|
end
|
51
70
|
|
52
|
-
ob.scripts.
|
53
|
-
puts "---------- script: #{index} --------------".green
|
54
|
-
puts
|
71
|
+
ob.scripts.each do |index, block|
|
72
|
+
puts "---------- script: #{index} to be run with: #{block[:header][:shebang]} --------------".green
|
73
|
+
puts block[:lines]
|
55
74
|
end
|
56
75
|
end
|
57
76
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# Re-use most of the proven tricks from Foreman for this
|
3
|
+
# and just customize to watch the output from runnable code blocks
|
4
|
+
#
|
5
|
+
require 'foreman/engine'
|
6
|
+
require 'foreman/process'
|
7
|
+
|
8
|
+
module OrgConverge
|
9
|
+
class Engine < Foreman::Engine
|
10
|
+
|
11
|
+
attr_reader :logger
|
12
|
+
attr_reader :babel
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
super(options)
|
16
|
+
@logger = options[:logger] || Logger.new(STDOUT)
|
17
|
+
@babel = options[:babel]
|
18
|
+
end
|
19
|
+
|
20
|
+
# We allow other processes to exit with 0 status
|
21
|
+
# to continue with the runlist
|
22
|
+
def start
|
23
|
+
register_signal_handlers
|
24
|
+
spawn_processes
|
25
|
+
watch_for_output
|
26
|
+
sleep 0.1
|
27
|
+
begin
|
28
|
+
status = watch_for_termination
|
29
|
+
end while @running.count > 0
|
30
|
+
logger.info "Run has completed successfully.".green
|
31
|
+
end
|
32
|
+
|
33
|
+
# Overriden: we do not consider process formations
|
34
|
+
def spawn_processes
|
35
|
+
@processes.each do |process|
|
36
|
+
reader, writer = create_pipe
|
37
|
+
begin
|
38
|
+
pid = process.run(:output => writer)
|
39
|
+
@names[process] = "#{@names[process]}(#{pid})"
|
40
|
+
writer.puts "started with pid #{pid}"
|
41
|
+
rescue Errno::ENOENT
|
42
|
+
writer.puts "unknown command: #{process.command}"
|
43
|
+
end
|
44
|
+
@running[pid] = [process]
|
45
|
+
@readers[pid] = reader
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def register(name, command, options={})
|
50
|
+
options[:env] ||= env
|
51
|
+
options[:cwd] ||= File.dirname(command.split(" ").first)
|
52
|
+
process = OrgConverge::CodeBlockProcess.new(command, options)
|
53
|
+
@names[process] = name
|
54
|
+
@processes << process
|
55
|
+
end
|
56
|
+
|
57
|
+
def output(name, data)
|
58
|
+
data.to_s.lines.map(&:chomp).each do |message|
|
59
|
+
|
60
|
+
# FIXME: In case the process has finished before its lines where flushed
|
61
|
+
ps = name.empty? ? '<defunct>' : name.split('.').first
|
62
|
+
output = "#{pad_process_name(ps)}".yellow
|
63
|
+
output += " -- "
|
64
|
+
output += message
|
65
|
+
# FIXME: When the process has stopped already,
|
66
|
+
# the name of the process does not appear
|
67
|
+
logger.info output
|
68
|
+
end
|
69
|
+
rescue Errno::EPIPE
|
70
|
+
terminate_gracefully
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def name_padding
|
75
|
+
@name_padding ||= begin
|
76
|
+
name_padding = @names.values.map { |n| n.length }.sort.last
|
77
|
+
[ 9, name_padding ].max
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def pad_process_name(name)
|
82
|
+
name.ljust(name_padding, " ")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class CodeBlockProcess < Foreman::Process; end
|
87
|
+
end
|
data/lib/org-converge/version.rb
CHANGED
data/org-converge.gemspec
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
#+title: Running scripts in parallel
|
2
|
+
|
3
|
+
In the following example, the following 3 scripts should be run in parallel
|
4
|
+
with all output being flushed to the screen.
|
5
|
+
|
6
|
+
- Count some numbers with bash
|
7
|
+
|
8
|
+
#+begin_src sh :shebang #!/bin/bash
|
9
|
+
for i in `seq 1 5`; do
|
10
|
+
echo "Writing! $i"
|
11
|
+
echo "hello $i" >> out.log
|
12
|
+
sleep $(($RANDOM % 10))
|
13
|
+
done
|
14
|
+
#+end_src
|
15
|
+
|
16
|
+
- Count some numbers with ruby
|
17
|
+
|
18
|
+
#+begin_src ruby :shebang #!/usr/bin/ruby
|
19
|
+
10.times do |n|
|
20
|
+
puts "And now writing! #{n}"
|
21
|
+
File.open("out.log", "a") {|f| f.puts "Hello again #{n}" }
|
22
|
+
sleep rand.round(2)
|
23
|
+
end
|
24
|
+
#+end_src
|
25
|
+
|
26
|
+
- Print some numbers with python
|
27
|
+
|
28
|
+
#+begin_src python :shebang #!/usr/bin/python
|
29
|
+
for i in range(0,3):
|
30
|
+
print i
|
31
|
+
#+end_src
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-03-
|
12
|
+
date: 2014-03-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: docopt
|
16
|
-
requirement: &
|
16
|
+
requirement: &70243331730100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.5.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70243331730100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: org-ruby
|
27
|
-
requirement: &
|
27
|
+
requirement: &70243331729260 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,18 @@ dependencies:
|
|
32
32
|
version: 0.9.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70243331729260
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: foreman
|
38
|
+
requirement: &70243331728140 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.63.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70243331728140
|
36
47
|
description: A light configuration management tool for Org mode
|
37
48
|
email:
|
38
49
|
- waldemar.quevedo@gmail.com
|
@@ -42,8 +53,10 @@ extensions: []
|
|
42
53
|
extra_rdoc_files: []
|
43
54
|
files:
|
44
55
|
- .gitmodules
|
56
|
+
- .travis.yml
|
45
57
|
- Gemfile
|
46
58
|
- LICENSE
|
59
|
+
- README.md
|
47
60
|
- README.org
|
48
61
|
- Rakefile
|
49
62
|
- TODO
|
@@ -56,8 +69,10 @@ files:
|
|
56
69
|
- lib/org-converge/babel.rb
|
57
70
|
- lib/org-converge/babel_output_buffer.rb
|
58
71
|
- lib/org-converge/command.rb
|
72
|
+
- lib/org-converge/engine.rb
|
59
73
|
- lib/org-converge/version.rb
|
60
74
|
- org-converge.gemspec
|
75
|
+
- spec/converge_examples/basic_run_example/setup.org
|
61
76
|
- spec/converge_examples/basic_tangle/conf.yml.expected
|
62
77
|
- spec/converge_examples/basic_tangle/setup.org
|
63
78
|
- spec/converge_spec.rb
|
@@ -88,7 +103,9 @@ specification_version: 3
|
|
88
103
|
summary: Provides an 'org-converge' command which can be used for tangling and running
|
89
104
|
Org mode code blocks
|
90
105
|
test_files:
|
106
|
+
- spec/converge_examples/basic_run_example/setup.org
|
91
107
|
- spec/converge_examples/basic_tangle/conf.yml.expected
|
92
108
|
- spec/converge_examples/basic_tangle/setup.org
|
93
109
|
- spec/converge_spec.rb
|
94
110
|
- spec/spec_helper.rb
|
111
|
+
has_rdoc:
|