org-converge 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/TODO CHANGED
@@ -2,19 +2,28 @@
2
2
  #+TODO: TODO | DONE CANCELED
3
3
  #+startup: showeverything
4
4
 
5
- * [0/8] > 0.0.9 version
5
+ * [0/7] > 0.0.9 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
11
+ + This would work by using the ~:cache true~ to a block header argument
12
+ - [ ] Support for ~#+SETUPFILE~
12
13
  - [ ] Heuristics for determining which binary to use for running the script
13
14
  - [ ] Display how the run would look like without making changes
14
15
  : org-converge setupfile.org --dry-run
15
16
  - [ ] Use :eval for evaling blocks (off by default)
16
17
  - [ ] Can use :dir for running a process relative to that directory
17
- - [ ] Use rake task manager
18
+
19
+ * [0/1] 0.0.8 version
20
+
21
+ - [ ] ~org-spec~ exploration
22
+
23
+ * [2/2] 0.0.7 version
24
+
25
+ - [X] Add ~org-run~ and ~org-tangle~ aliases
26
+ - [X] Use rake task manager
18
27
 
19
28
  * [3/3] 0.0.6 version
20
29
 
@@ -55,37 +64,36 @@ Need some basic functionality of what Org babel offers first.
55
64
  - [X] ~--tangle~ flag
56
65
  - [X] Support a root dir for when not running relative to the directory
57
66
 
58
- * [3/20] Ideas
59
- ** CANCELED How to set the permissions from the directory from the file that is being tangled when it does not exists?
67
+ * [6/21] Ideas
68
+ ** TODO Chaining resources with ~#+NAME:~ directives and ~:notify~ argument
60
69
 
61
- By default, this would be 0644, but we also need to specify the
62
- user:group of it so the syntax would have to be:
70
+ One idea is to be able to notify resources by naming the code blocks.
63
71
 
64
- #+begin_src conf :tangle etc/something/config/path :chmod 0664 :user td-agent :group
65
- hmm dont't like this syntax for folders
72
+ Example: Here first the td-agent service would try to start,
73
+ and if it succeeds, then it would execute the script defined in the
74
+ ~announce-availability~ resource.
75
+
76
+ #+name: td-agent-start
77
+ #+begin_src sh :notify announce-availability
78
+ sudo service td-agent start
66
79
  #+end_src
67
80
 
68
- Let's keep it simple and just use a babel block that shells out to create the directories
69
- until I can think of something better.
81
+ #+name: announce-availability
82
+ #+begin_src sh
83
+ sudo /etc/register-to-balancer
84
+ #+end_src
85
+
86
+ - Support for ~:before all~ and ~:after all~ added
87
+ ** TODO Add namespace dynamically to the tasks using an in buffer setting
88
+
89
+ When including files there can be some potential scoping issues.
90
+
70
91
  ** TODO Inject macros within the environment variables from a runnable process
71
92
  ** TODO Clarify which ones of the header arguments to implement
72
93
 
73
94
  http://orgmode.org/manual/Specific-header-arguments.html#Specific-header-arguments
74
95
 
75
96
  ** TODO Use sshkit for running remote processes
76
- ** TODO We don't need to create the directories in most cases (:mkdirp yes)
77
-
78
- Something like this is not required because the ~:tangle~ blocks
79
- would create the necessary directories behind the scenes.
80
-
81
- #+begin_src org
82
- ,We need to prepare some directories for the configuration:
83
-
84
- ,#+begin_src converge
85
- ,mkdir -p etc/fluentd/config
86
- ,#+end_src
87
- #+end_src
88
-
89
97
  ** TODO By default, it should use current dir for tangling
90
98
  ** TODO Converging: Only do an operation when it didn't finish
91
99
 
@@ -130,24 +138,26 @@ fluentd:
130
138
 
131
139
  But need to
132
140
 
133
- ** TODO Using the :tags: to setup the things to run right away
141
+ ** TODO Choosing a templating language: default for now is mustache
134
142
 
135
- Kind of like the chef-solo runlist, a headline like this...
143
+ We could implement the macro systems, but it seems that it may not be
144
+ strong enough for providing with all the cases we may run into.
145
+ ** TODO Support caching?
136
146
 
137
- #+begin_src org
138
- ,* Everything in its right place :config:
139
-
140
- ,#+begin_src conf :tangle etc/this.yml
141
- ,hello: "world"
142
- ,#+end_src
147
+ #+begin_src emacs-lisp :cache yes :exports results
148
+ (random)
143
149
  #+end_src
144
150
 
145
- ...could be called like this
151
+ #+RESULTS[db54597aed193d861d01bf92110e10f28f8f40d4]:
152
+ : 842438499349743708
146
153
 
147
- #+begin_src sh
148
- org-converge fluentd.org -t config
154
+ ** TODO Support :eval ?
155
+
156
+ #+begin_src sh :eval (print "Really doing this...")
157
+ echo "Going ahead with operation X!"
149
158
  #+end_src
150
159
 
160
+ ** DONE ~#+NAME:~ could be used in the logger for identifying the process
151
161
  ** DONE Managing dependencies: could be handled with ~#+include~ directives
152
162
 
153
163
  One idea is that it would be useful to compile different manuals
@@ -167,52 +177,58 @@ We should be able to express that dependency somehow:
167
177
 
168
178
  # But one problem, is that once I have included something, sometimes we
169
179
  # will want "reopen" the previous manuals?
180
+ ** DONE We don't need to create the directories in most cases (:mkdirp yes)
170
181
 
171
- ** TODO Loading all the Org mode files first and then setup only one part
182
+ Something like this is not required because the ~:tangle~ blocks
183
+ would create the necessary directories behind the scenes.
172
184
 
173
- So maybe, each one of these tags would have to be namespaces under the
174
- name of the file:
185
+ #+begin_src org
186
+ ,We need to prepare some directories for the configuration:
187
+
188
+ ,#+begin_src converge
189
+ ,mkdir -p etc/fluentd/config
190
+ ,#+end_src
191
+ #+end_src
192
+ ** CANCELED How to set the permissions from the directory from the file that is being tangled when it does not exists?
175
193
 
176
- : org-converge logserver.org -t "fluentd::setup, fluentd::config, logserver::setup"
194
+ By default, this would be 0644, but we also need to specify the
195
+ user:group of it so the syntax would have to be:
177
196
 
178
- ** TODO Choosing a templating language: default for now is mustache
197
+ #+begin_src conf :tangle etc/something/config/path :chmod 0664 :user td-agent :group
198
+ hmm dont't like this syntax for folders
199
+ #+end_src
179
200
 
180
- We could implement the macro systems, but it seems that it may not be
181
- strong enough for providing with all the cases we may run into.
201
+ Let's keep it simple and just use a babel block that shells out to create the directories
202
+ until I can think of something better.
182
203
 
183
- ** TODO Chaining resources with ~#+NAME:~ directives and ~:notify~ argument
204
+ ** CANCELED Using the :tags: to setup the things to run right away
184
205
 
185
- One idea is to be able to notify resources by naming the code blocks.
206
+ Using the block ~#+name~ instead.
186
207
 
187
- Example: Here first the td-agent service would try to start,
188
- and if it succeeds, then it would execute the script defined in the
189
- ~announce-availability~ resource.
208
+ Kind of like the chef-solo runlist, a headline like this...
190
209
 
191
- #+name: td-agent-start
192
- #+begin_src sh :notify announce-availability
193
- sudo service td-agent start
210
+ #+begin_src org
211
+ ,* Everything in its right place :config:
212
+
213
+ ,#+begin_src conf :tangle etc/this.yml
214
+ ,hello: "world"
215
+ ,#+end_src
194
216
  #+end_src
195
217
 
196
- #+name: announce-availability
218
+ ...could be called like this
219
+
197
220
  #+begin_src sh
198
- sudo /etc/register-to-balancer
221
+ org-converge fluentd.org -t config
199
222
  #+end_src
200
223
 
201
- ** DONE ~#+NAME:~ could be used in the logger for identifying the process
202
- ** TODO Support caching?
203
-
204
- #+begin_src emacs-lisp :cache yes :exports results
205
- (random)
206
- #+end_src
224
+ ** CANCELED Loading all the Org mode files first and then setup only one part
207
225
 
208
- #+RESULTS[db54597aed193d861d01bf92110e10f28f8f40d4]:
209
- : 842438499349743708
226
+ Used ~#+name~ from blocks instead.
210
227
 
211
- ** TODO Support :eval ?
228
+ So maybe, each one of these tags would have to be namespaces under the
229
+ name of the file:
212
230
 
213
- #+begin_src sh :eval (print "Really doing this...")
214
- echo "Going ahead with operation X!"
215
- #+end_src
231
+ : org-converge logserver.org -t "fluentd::setup, fluentd::config, logserver::setup"
216
232
 
217
233
  * Links
218
234
 
data/bin/org-converge CHANGED
@@ -8,7 +8,7 @@ doc = <<OPTIONS
8
8
  org-converge: A light configuration management tool for Org mode
9
9
 
10
10
  Usage:
11
- org-converge <org_file> [--tangle] [--showfiles] [--log=<logfile>] [--root-dir=<root_dir>] [--runmode=<runmode>] [--name=<block_name>]
11
+ org-converge <org_file> [--showfiles] [--log=<logfile>] [--root-dir=<root_dir>] [--runmode=<runmode>] [--name=<block_name>]
12
12
 
13
13
  Options:
14
14
 
data/bin/org-run ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ # alias for org-converge
5
+ load File.expand_path('../org-converge', __FILE__)
data/bin/org-tangle ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+ require 'docopt'
4
+ require 'org-converge'
5
+
6
+ doc = <<OPTIONS
7
+
8
+ org-tangle: Org babel tangling feature using the Org mode Ruby parser
9
+
10
+ Usage:
11
+ org-tangle <org_file> [--showfiles] [--log=<logfile>] [--root-dir=<root_dir>]
12
+
13
+ Options:
14
+
15
+ -h --help Show this screen.
16
+
17
+ OPTIONS
18
+
19
+ begin
20
+ require "pp"
21
+ cmd = Docopt::docopt(doc)
22
+ rescue Docopt::Exit => e
23
+ puts e.message
24
+ end
25
+
26
+ exit 1 unless cmd
27
+
28
+ o = OrgConverge::Command.new(cmd.merge({'--tangle' => true }))
29
+ o.execute!
@@ -1,3 +1,5 @@
1
+ require 'rake'
2
+
1
3
  module Orgmode
2
4
  class BabelOutputBuffer < OutputBuffer
3
5
  attr_reader :tangle
@@ -11,11 +13,21 @@ module Orgmode
11
13
 
12
14
  # ~@tangle~ files are put in the right path
13
15
  # : @tangle['/path'] = [Lines]
14
- @tangle = Hash.new {|h,k| h[k] = {:lines => '', :header => {}, :lang => ''}}
16
+ @tangle = Hash.new {|h,k| h[k] = {
17
+ :lines => '',
18
+ :header => {},
19
+ :lang => ''
20
+ }
21
+ }
15
22
 
16
23
  # ~@scripts~ are tangled in order and ran
17
24
  # : @scripts = [text, text, ...]
18
- @scripts = Hash.new {|h,k| h[k] = {:lines => '', :header => {}, :lang => ''}}
25
+ @scripts = Hash.new {|h,k| h[k] = {
26
+ :lines => '',
27
+ :header => {},
28
+ :lang => ''
29
+ }
30
+ }
19
31
  @scripts_counter = 0
20
32
  @buffer = ''
21
33
  end
@@ -50,7 +62,9 @@ module Orgmode
50
62
  @scripts[@scripts_counter][:header] = {
51
63
  :shebang => line.block_header_arguments[':shebang'],
52
64
  :mkdirp => line.block_header_arguments[':mkdirp'],
53
- :name => line.properties['block_name']
65
+ :name => line.properties['block_name'],
66
+ :before => line.block_header_arguments[':before'],
67
+ :after => line.block_header_arguments[':after']
54
68
  }
55
69
  @scripts[@scripts_counter][:lang] = line.block_lang
56
70
  # TODO: have a way to specify which are the default binaries to be used per language
@@ -58,8 +58,8 @@ module OrgConverge
58
58
  run_blocks_in_parallel!
59
59
  when 'sequential'
60
60
  run_blocks_sequentially!
61
- when 'runlist'
62
- # TODO
61
+ when 'chained', 'chain', 'tasks'
62
+ run_blocks_chain!
63
63
  else # parallel by default
64
64
  run_blocks_in_parallel!
65
65
  end
@@ -71,6 +71,53 @@ module OrgConverge
71
71
  logger.error "Cannot converge because there were errors during tangle step".fg 'red'
72
72
  end
73
73
 
74
+ def run_blocks_chain!
75
+ # Chain the blocks by defining them as Rake::Tasks dynamically
76
+ tasks = { }
77
+
78
+ babel.tangle_runnable_blocks!(@run_dir)
79
+ babel.ob.scripts.each do |key, script|
80
+ task_name = script[:header][:name]
81
+ next unless task_name
82
+
83
+ task = Rake::Task.define_task task_name do
84
+ with_running_engine do |engine|
85
+ file = File.expand_path("#{@run_dir}/#{key}")
86
+ cmd = "#{script[:lang]} #{file}"
87
+ engine.register task_name, cmd, { :cwd => @root_dir, :logger => logger }
88
+ end
89
+ end
90
+ tasks[task_name] = {
91
+ :task => task,
92
+ :script => script
93
+ }
94
+ end
95
+
96
+ # Now onto define the prerequisites and actions
97
+ tasks.each_pair do |task_name, task_definition|
98
+ prerequisite_task = task_definition[:script][:header][:after]
99
+ if prerequisite_task and tasks[prerequisite_task]
100
+ task_definition[:task].prerequisites << tasks[prerequisite_task][:task]
101
+ end
102
+
103
+ postrequisite_task = task_definition[:script][:header][:before]
104
+ if postrequisite_task and tasks[postrequisite_task]
105
+ tasks[postrequisite_task][:task].prerequisites << task_definition[:task]
106
+ end
107
+ end
108
+
109
+ # The task that marks the run as done needs to be defined explicitly
110
+ # otherwise a block named default will tried to be run
111
+ final_task = babel.ob.in_buffer_settings['FINAL_TASK'] || 'default'
112
+
113
+ if tasks[final_task]
114
+ logger.info "Running final task: #{tasks[final_task][:task]}"
115
+ tasks[final_task][:task].invoke
116
+ else
117
+ logger.error "Could not find a final task to run!"
118
+ end
119
+ end
120
+
74
121
  def run_blocks_sequentially!
75
122
  @engine = OrgConverge::Engine.new(:logger => @logger, :babel => @babel)
76
123
  babel.tangle_runnable_blocks!(@run_dir)
@@ -96,8 +143,6 @@ module OrgConverge
96
143
  logger.info "Run has completed successfully.".fg 'green'
97
144
  end
98
145
 
99
- # TODO: Too much foreman has made this running blocks in parallel the default behavior.
100
- # We should actually be supporting run lists instead, but liking this experiment so far.
101
146
  def run_blocks_in_parallel!
102
147
  @engine = OrgConverge::Engine.new(:logger => @logger, :babel => @babel)
103
148
  babel.tangle_runnable_blocks!(@run_dir)
@@ -1,3 +1,3 @@
1
1
  module OrgConverge
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
data/org-converge.gemspec CHANGED
@@ -14,8 +14,9 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "org-converge"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = OrgConverge::VERSION
17
- gem.add_runtime_dependency('docopt', '0.5.0')
18
- gem.add_runtime_dependency('org-ruby', '~> 0.9.4')
19
- gem.add_runtime_dependency('foreman', '~> 0.63.0')
20
- gem.add_runtime_dependency('tco', '~> 0.1.0')
17
+ gem.add_runtime_dependency('docopt', '~> 0.5.0')
18
+ gem.add_runtime_dependency('org-ruby', '~> 0.9.5')
19
+ gem.add_runtime_dependency('foreman', '~> 0.63.0')
20
+ gem.add_runtime_dependency('tco', '~> 0.1.0')
21
+ gem.add_runtime_dependency('rake', '~> 10.3')
21
22
  end
@@ -0,0 +1,43 @@
1
+ #+TITLE: Linked tasks example
2
+ #+runmode: tasks
3
+ #+final_task: final
4
+
5
+ The goal here is to be able to define dependencies
6
+ among blocks and run the correctly in that order.
7
+
8
+ With ~:after first~, the ~second~ block becomes
9
+ a prerequisite of the ~first~ block.
10
+
11
+ #+name: second
12
+ #+begin_src sh :after first
13
+ for i in `seq 5 10`; do
14
+ echo $i >> out.log
15
+ done
16
+ #+end_src
17
+
18
+ #+name: first
19
+ #+begin_src ruby
20
+ 5.times { |n| File.open("out.log", "a") {|f| f.puts n } }
21
+ #+end_src
22
+
23
+ Using ~:after all~ is special, since it means that the task
24
+ depends on everything else having run already.
25
+
26
+ #+name: final
27
+ #+begin_src python :after second :results output
28
+ print "Wrapping up with Python in the end"
29
+ f = open('out.log', 'a')
30
+ f.write('11')
31
+ f.close()
32
+ #+end_src
33
+
34
+ The same with ~:before all~, this would be executed
35
+ at the beginning.
36
+
37
+ #+name: prologue
38
+ #+begin_src sh :before first :results output
39
+ echo "init" > out.log
40
+ #+end_src
41
+
42
+ Note: Both ~:before all~ and ~:after all~ get accumulated
43
+ and are run sequentially after that.
@@ -85,4 +85,24 @@ describe OrgConverge::Command do
85
85
  expected_contents = "first\nsecond\n"
86
86
  File.read(File.join(example_dir, 'out.log')).should == expected_contents
87
87
  end
88
+
89
+ it "should run 'linked_tasks' in order" do
90
+ example_dir = File.join(EXAMPLES_DIR, 'linked_tasks')
91
+ setup_file = File.join(example_dir, 'tasks.org')
92
+
93
+ o = OrgConverge::Command.new({
94
+ '<org_file>' => setup_file,
95
+ '--root-dir' => example_dir
96
+ })
97
+ success = o.execute!
98
+ success.should == true
99
+
100
+ File.executable?(File.join(example_dir, 'run/0')).should == true
101
+ File.executable?(File.join(example_dir, 'run/1')).should == true
102
+ File.executable?(File.join(example_dir, 'run/2')).should == true
103
+ File.executable?(File.join(example_dir, 'run/3')).should == true
104
+
105
+ expected_contents = "init\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11"
106
+ File.read(File.join(example_dir, 'out.log')).should == expected_contents
107
+ end
88
108
  end
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.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,33 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-03 00:00:00.000000000 Z
12
+ date: 2014-05-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: docopt
16
- requirement: &70130002051260 !ruby/object:Gem::Requirement
16
+ requirement: &70254668243000 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - =
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
21
  version: 0.5.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70130002051260
24
+ version_requirements: *70254668243000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: org-ruby
27
- requirement: &70130002050780 !ruby/object:Gem::Requirement
27
+ requirement: &70254668242520 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: 0.9.4
32
+ version: 0.9.5
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70130002050780
35
+ version_requirements: *70254668242520
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: foreman
38
- requirement: &70130002050320 !ruby/object:Gem::Requirement
38
+ requirement: &70254664800460 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.63.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70130002050320
46
+ version_requirements: *70254664800460
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: tco
49
- requirement: &70130002049860 !ruby/object:Gem::Requirement
49
+ requirement: &70254664799380 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,12 +54,25 @@ dependencies:
54
54
  version: 0.1.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70130002049860
57
+ version_requirements: *70254664799380
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: &70254664798160 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '10.3'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70254664798160
58
69
  description: A light configuration management tool for Org mode
59
70
  email:
60
71
  - waldemar.quevedo@gmail.com
61
72
  executables:
62
73
  - org-converge
74
+ - org-run
75
+ - org-tangle
63
76
  extensions: []
64
77
  extra_rdoc_files: []
65
78
  files:
@@ -71,6 +84,8 @@ files:
71
84
  - Rakefile
72
85
  - TODO
73
86
  - bin/org-converge
87
+ - bin/org-run
88
+ - bin/org-tangle
74
89
  - examples/apt-get-install/setup.org
75
90
  - examples/fluentd/setup.org
76
91
  - examples/macro-config/setup.org
@@ -86,6 +101,7 @@ files:
86
101
  - spec/converge_examples/basic_tangle/conf.yml.expected
87
102
  - spec/converge_examples/basic_tangle/setup.org
88
103
  - spec/converge_examples/commented_block/run.org
104
+ - spec/converge_examples/linked_tasks/tasks.org
89
105
  - spec/converge_examples/runlist_example/setup.org
90
106
  - spec/converge_examples/specified_block/run.org
91
107
  - spec/converge_spec.rb
@@ -120,6 +136,7 @@ test_files:
120
136
  - spec/converge_examples/basic_tangle/conf.yml.expected
121
137
  - spec/converge_examples/basic_tangle/setup.org
122
138
  - spec/converge_examples/commented_block/run.org
139
+ - spec/converge_examples/linked_tasks/tasks.org
123
140
  - spec/converge_examples/runlist_example/setup.org
124
141
  - spec/converge_examples/specified_block/run.org
125
142
  - spec/converge_spec.rb