org-converge 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/wallyqs/org-converge.svg?branch=master)](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:
|