org-converge 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "org-ruby"]
2
+ path = org-ruby
3
+ url = https://github.com/wallyqs/org-ruby
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'rake'
5
+ gem 'rspec'
6
+ end
7
+
8
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Waldemar Quevedo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.org ADDED
@@ -0,0 +1,109 @@
1
+ # -*- mode: org; mode: auto-fill; -*-
2
+ #+TITLE: Org Converge
3
+ #+STARTUP: showeverything
4
+
5
+ * Description
6
+
7
+ This attempts to be an experiment of using Org mode syntax to
8
+ describe, configure and setting up something, borrowing some ideas
9
+ of what is possible to do with tools like =chef-solo=, =puppet=,
10
+ =ansible=, etc...
11
+
12
+ * Motivation
13
+
14
+ The Org babel syntax has proven to be flexible enough to produce
15
+ /reproducible research/ papers. Then, I believe that configuring and setting up
16
+ a server for example is something that could be also be done using
17
+ the same syntax, given that /converging/ the configuration is something
18
+ that one ought to be able to reproduce.
19
+
20
+ * Usage
21
+
22
+ : org-converge path/to/setup-file.org
23
+
24
+ * How it works
25
+
26
+ Org Converge uses an liberally extended version of Org Babel
27
+ features in order to give support for converging the configuration
28
+ of a server.
29
+
30
+ For example, using Org Babel and macros we can easily spread config
31
+ files on a server by writing the following on a ~server.org~ file.
32
+
33
+ #+begin_src org
34
+ ,#+MACRO: multitenancy_enabled true
35
+ ,#+MACRO: status_port true
36
+
37
+ ,#+begin_src yaml :tangle /etc/component.yml
38
+ multitenant: false
39
+ status_port: 10004
40
+ ,#+end_src
41
+ #+end_src
42
+
43
+ And then configure it by running it as follows, (considering we have
44
+ the correct permissions):
45
+
46
+ #+begin_src sh
47
+ org-converge server.org
48
+ #+end_src
49
+
50
+ This leverages on the syntax already provided by Org Babel, but one
51
+ difference here is that if we run it once again without changes...
52
+
53
+ #+begin_src sh
54
+ org-converge server.org
55
+ #+end_src
56
+
57
+ ...it would finish soon since the configuration has already converged.
58
+
59
+ Next, let's say that we no only one want to set the configured templates,
60
+ but that we also want to install some packages. In that case, we
61
+ should be able to do the following:
62
+
63
+ #+begin_src org
64
+ ,#+macro: multitenancy_enabled true
65
+ ,#+macro: status_port true
66
+ ,#+macro: project_path path/to/project
67
+
68
+ ,* Configuring the component
69
+
70
+ ,#+begin_src yaml :tangle /etc/component.yml
71
+ multitenant: false
72
+ status_port: 10004
73
+ ,#+end_src
74
+
75
+ ,* Installing the dependencies
76
+
77
+ Need the following so that ~bundle install~ can compile
78
+ the native extensions correctly.
79
+
80
+ ,#+begin_src sh
81
+ apt-get install build-essentials -y
82
+ ,#+end_src
83
+
84
+ Then the following should work:
85
+
86
+ ,#+begin_src sh
87
+ cd {{{project_path}}}
88
+ bundle install
89
+ ,#+end_src
90
+ #+end_src
91
+
92
+ As long as the repo has been already checked out in the directory,
93
+ the previous example will succeed.
94
+
95
+ #+begin_src sh
96
+ org-converge server.org
97
+ #+end_src
98
+
99
+ If that is not the case, then org-converge will fail
100
+ and pickup from that last step.
101
+
102
+ More practical examples can be found [[here]], more will be added as
103
+ long as dogfooding from this goes well.
104
+
105
+ * Contributing
106
+
107
+ The project is in very early development at this moment, but if you
108
+ feel that it is interesting enough, please create a ticket so start
109
+ the discussion.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = FileList['spec/**/*_spec.rb']
9
+ spec.rspec_opts = ['--format', 'documentation', '--colour']
10
+ end
data/TODO ADDED
@@ -0,0 +1,167 @@
1
+ # -*- mode: org; mode: auto-fill; -*-
2
+ #+TODO: TODO | DONE CANCELED
3
+ #+startup: showeverything
4
+
5
+ * [0/2] 0.0.3 version
6
+
7
+ - [ ] Macros can be loaded and applied to the configuration
8
+ - [ ] Actually support converging and idempotency
9
+ + Do not do an operation unless it is required
10
+ + Abort in case there was a failure in executing the script.
11
+
12
+ * [0/2] 0.0.2 version
13
+
14
+ Run the code blocks!
15
+
16
+ - [ ] Code blocks are executed by default after tangling
17
+ Only when :shebang exists as an argument
18
+ - [ ] Display how the run would look like
19
+ : org-converge setupfile.org --dry-run
20
+
21
+ * [3/3] 0.0.1 version
22
+
23
+ Need some basic functionality of what Org babel offers first.
24
+
25
+ - [X] Display files that were captured with command
26
+ : org-converge setupfile.org --showfiles
27
+ - [X] ~:tangle~ puts the files in the correct path
28
+ - [X] ~--tangle~ flag
29
+ - [X] Support a root dir for when not running relative to the directory
30
+
31
+ * [2/14] Ideas
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
+
45
+ ** CANCELED How to set the permissions from the directory from the file that is being tangled when it does not exists?
46
+
47
+ By default, this would be 0644, but we also need to specify the
48
+ user:group of it so the syntax would have to be:
49
+
50
+ #+begin_src conf :tangle etc/something/config/path :chmod 0664 :user td-agent :group
51
+ hmm dont't like this syntax for folders
52
+ #+end_src
53
+
54
+ Let's keep it simple and just use a babel block that shells out to create the directories
55
+ until I can think of something better.
56
+
57
+ ** TODO By default, it should use current dir for tangling
58
+ ** TODO Converging: Only do an operation when it didn't finish
59
+
60
+ Hence the name of the project
61
+
62
+ ** TODO For now we keep the indentation of the code blocks
63
+
64
+ The indentatin of the ~#+begin_src~ should always
65
+ be at the beginning of the file, not at the indentation
66
+ level from when the file was written in Org mode.
67
+
68
+ ** TODO We should have a whitelist of languages that can be executed and ignore everything
69
+
70
+ Under which heuristics or configuration should we decide which will be the
71
+ binary that should be used to execute the block? Specify with shebang?
72
+
73
+ - For now, unless shebang is specified it will be executed.
74
+ Then in the scripts buffer used ~index::shebang~ as a key.
75
+
76
+ ** TODO Setting permissions from a tangled file
77
+
78
+ It should be possible to tangle the files this way:
79
+
80
+ #+begin_src conf :tangle etc/something/config/path :chmod 0664 :user td-agent :group td-agent
81
+ <source>
82
+ </source>
83
+ #+end_src
84
+
85
+ ** TODO Adopting the ~#+SETUPFILE~ for loading a config that is done JSON or YAML
86
+
87
+ It seems that there is support for a ~#+SETUPFILE~
88
+
89
+ ** TODO Something more flexible than macros:
90
+
91
+ One example of syntax that we could use instead of macros:
92
+
93
+ #+begin_src yaml :session
94
+ fluentd:
95
+ port: 4224
96
+ path: here.log
97
+ #+end_src
98
+
99
+ But need to
100
+
101
+ ** TODO Using the :tags: to setup the things to run right away
102
+
103
+ Kind of like the chef-solo runlist, a headline like this...
104
+
105
+ #+begin_src org
106
+ ,* Everything in its right place :config:
107
+
108
+ ,#+begin_src conf :tangle etc/this.yml
109
+ ,hello: "world"
110
+ ,#+end_src
111
+ #+end_src
112
+
113
+ ...could be called like this
114
+
115
+ #+begin_src sh
116
+ org-converge fluentd.org -t config
117
+ #+end_src
118
+
119
+ ** TODO Managing dependencies: could be handled with ~#+include~ directives
120
+
121
+ One idea is that it would be useful to compile different manuals
122
+ that are dependent among each other.
123
+
124
+ For example, the centralized logs server would require fluentd.
125
+ We should be able to express that dependency somehow:
126
+
127
+ #+begin_src org :tangle logserver.org
128
+ ,#+include: "fluentd.org"
129
+
130
+ ,* Setup the centralized logserver :setup:
131
+
132
+ ,Once the fluentd.org has been converged, we can build upon this and
133
+ ,override the original config to make it particular for this logserver
134
+ #+end_src
135
+
136
+ # But one problem, is that once I have included something, sometimes we
137
+ # will want "reopen" the previous manuals?
138
+
139
+ ** TODO Loading all the Org mode files first and then setup only one part
140
+
141
+ So maybe, each one of these tags would have to be namespaces under the
142
+ name of the file:
143
+
144
+ : org-converge logserver.org -t "fluentd::setup, fluentd::config, logserver::setup"
145
+
146
+ ** TODO Choosing a templating language: default for now is mustache
147
+
148
+ We could implement the macro systems, but it seems that it may not be
149
+ strong enough for providing with all the cases we may run into.
150
+
151
+ ** TODO Chaining resources with ~#+NAME:~ directives and ~:notify~ argument
152
+
153
+ One idea is to be able to notify resources by naming the code blocks.
154
+
155
+ Example: Here first the td-agent service would try to start,
156
+ and if it succeeds, then it would execute the script defined in the
157
+ ~announce-availability~ resource.
158
+
159
+ #+name: td-agent-start
160
+ #+begin_src sh :notify announce-availability
161
+ sudo service td-agent start
162
+ #+end_src
163
+
164
+ #+name: announce-availability
165
+ #+begin_src sh
166
+ sudo /etc/register-to-balancer
167
+ #+end_src
data/bin/org-converge 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-converge: A light configuration management tool for Org mode
9
+
10
+ Usage:
11
+ org-converge <org_file> [--tangle] [--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)
29
+ o.execute!
@@ -0,0 +1,11 @@
1
+ #+TITLE: Installing some packages
2
+
3
+ * Just install some packages for example
4
+
5
+ #+begin_src sh
6
+ sudo apt-get install build-essentials
7
+ #+end_src
8
+
9
+ Should be able to be run with something like:
10
+
11
+ : org-converge examples/apt-get-install.org
@@ -0,0 +1,50 @@
1
+ # -*- mode: org; auto-fill-mode -*-
2
+ #+TITLE: Setting up Fluentd
3
+ #+startup: showeverything
4
+
5
+ * Introduction
6
+
7
+ The following will setup and configure ~fluentd~ on a node.
8
+
9
+ * Settings
10
+
11
+ These can be defined with Org mode macro directives, but thinking on
12
+ other ways to do it as well.
13
+
14
+ #+macro: fluentd_port 4224
15
+ #+macro: fluentd_filepath here.log
16
+
17
+ * Setup :setup:
18
+
19
+ Fluentd can be installed either as a package from treasure data or
20
+ just as a gem. In this example, we only install as a gem:
21
+
22
+ #+begin_src sh
23
+ gem install fluentd
24
+ #+end_src
25
+
26
+ * Configuration :config:
27
+
28
+ Set Fluentd to listen on the ~fluentd_port~ port and to write logs
29
+ to ~fluentd_filepath~.
30
+
31
+ #+begin_src conf :tangle etc/fluentd.conf
32
+ <source>
33
+ type forward
34
+ port {{{ fluentd_port }}}
35
+ </source>
36
+
37
+ <match **>
38
+ type file
39
+ path {{{ fluentd_filepath }}}
40
+ </match>
41
+ #+end_src
42
+
43
+ # A script to daemonize the process could be written here, as well as
44
+ # any /etc/default/* required settings...
45
+
46
+ * Start which was configured here :start:
47
+
48
+ #+begin_src sh
49
+ fluentd -c etc/fluentd.conf -vvv
50
+ #+end_src
@@ -0,0 +1,14 @@
1
+ #+TITLE: Using macros for configuration
2
+
3
+ #+macro: hello world
4
+ #+macro: application my-application
5
+
6
+ Hello {{{hello}}}, this will setup something for {{{application}}}.
7
+
8
+ #+begin_src sh :results output
9
+ echo "Hello for {{{application}}}" > /tmp/hello
10
+ #+end_src
11
+
12
+ #+RESULTS:
13
+ : Hello for {{{application}}}
14
+
@@ -0,0 +1,51 @@
1
+ #+TITLE: Simple example
2
+
3
+ It does not get more simple than this:
4
+
5
+ - First, configure something:
6
+
7
+ #+begin_src conf :tangle /tmp/my-conf
8
+ <source>
9
+ bind 0.0.0.0
10
+
11
+
12
+
13
+ port 4224
14
+
15
+
16
+
17
+
18
+ </source>
19
+
20
+ <match **>
21
+ type file
22
+
23
+
24
+ path /var/tmp/a.log
25
+ </match>
26
+ #+end_src
27
+
28
+ - And then run something
29
+
30
+ #+begin_src sh
31
+ echo "1) Hello world" > /tmp/my-echo
32
+ echo "2) Hello world" > /tmp/my-echo
33
+ echo "3) Hello world" > /tmp/my-echo
34
+ #+end_src
35
+
36
+ - Then configure something again
37
+
38
+ #+begin_src sh
39
+ echo "4) Hello world" >> /tmp/my-echo
40
+ echo "5) Hello world" >> /tmp/my-echo
41
+ echo "6) Hello world" >> /tmp/my-echo
42
+
43
+ echo "7) Hello world" >> /tmp/my-echo
44
+ #+end_src
45
+
46
+ - And send something to babel once again
47
+
48
+ #+begin_src conf :tangle /tmp/hello-conf.yml
49
+ status_port: 9090
50
+ no_tab_after_that: true
51
+ #+end_src
@@ -0,0 +1,60 @@
1
+ #
2
+ # Class with util methods that try to reimplement some of
3
+ # the functionality provided by Org Babel from Emacs
4
+ #
5
+ require 'fileutils'
6
+
7
+ module Orgmode
8
+ class Babel
9
+ attr_reader :ob # Babel Output Buffer with parsed contents
10
+ attr_reader :logger
11
+
12
+ def initialize(babel_output_buffer, options={})
13
+ @ob = babel_output_buffer
14
+ @options = options
15
+ @logger = options[:logger] || Logger.new(STDOUT)
16
+ @root_dir = options[:root_dir]
17
+ end
18
+
19
+ # TODO: should be able to tangle relatively to a dir
20
+ def tangle!
21
+ logger.info "Tangling #{ob.tangle.keys.count} files..."
22
+
23
+ ob.tangle.each do |tangle_file, lines|
24
+ file = if @root_dir
25
+ File.join(@root_dir, tangle_file)
26
+ else
27
+ tangle_file
28
+ end
29
+
30
+ logger.info "BEGIN(#{tangle_file}): Tangling #{lines.count} lines at '#{file}'"
31
+ # TODO: should abort when the directory does not exists
32
+ # TODO: should abort when the directory failed because of permissions
33
+ if not Dir.exists?(File.dirname(file))
34
+ logger.error "Could not tangle #{file} because directory does not exists!"
35
+ raise TangleError
36
+ end
37
+
38
+ if File.exists?(file)
39
+ logger.warn "File already exists at #{file}, it will be overwritten"
40
+ end
41
+
42
+ begin
43
+ File.open(file, 'w') do |f|
44
+ lines.each do |line|
45
+ f.puts line
46
+ end
47
+ end
48
+ rescue => e
49
+ logger.error "Problem while writing to '#{file}': #{e}"
50
+ raise TangleError
51
+ end
52
+ logger.info "END(#{file}): done."
53
+ end
54
+
55
+ logger.info "Tangling succeeded!".green
56
+ end
57
+
58
+ class TangleError < Exception; end
59
+ end
60
+ end
@@ -0,0 +1,82 @@
1
+ module Orgmode
2
+ class BabelOutputBuffer < OutputBuffer
3
+ attr_reader :tangle
4
+ attr_reader :scripts
5
+
6
+ def initialize(output)
7
+ super(output)
8
+
9
+ # ~@tangle~ files are put in the right path
10
+ # : @tangle['/path'] = [Lines]
11
+ @tangle = Hash.new {|h,k| h[k] = []}
12
+
13
+ # ~@scripts~ are tangled in order and ran
14
+ # : @scripts = [text, text, ...]
15
+ @scripts = []
16
+
17
+ @buffer = ''
18
+ end
19
+
20
+ def push_mode(mode, indent)
21
+ super(mode, indent)
22
+ end
23
+
24
+ def pop_mode(mode = nil)
25
+ m = super(mode)
26
+ @list_indent_stack.pop
27
+ m
28
+ end
29
+
30
+ def insert(line)
31
+ # We try to get the lang from #+BEGIN_SRC blocks
32
+ if line.begin_block?
33
+ @block_lang = line.block_lang
34
+ if line.block_header_arguments[':tangle']
35
+ @current_tangle = line.block_header_arguments[':tangle']
36
+ else
37
+ @shebang = line.block_header_arguments[':shebang']
38
+ @current_tangle = nil
39
+ @buffer = ''
40
+ end
41
+ end
42
+
43
+ case
44
+ when (line.assigned_paragraph_type == :code and @current_tangle)
45
+ # Need to keep track of the current tangle to buffer its lines
46
+ @tangle[@current_tangle] << line
47
+ when (line.assigned_paragraph_type == :code)
48
+ # When a tangle is not going on, it means that the lines would go
49
+ # into a runnable script
50
+ @buffer << line.output_text << "\n"
51
+ when (!@buffer.empty? and not (line.begin_block? or line.assigned_paragraph_type == :code))
52
+ # Fix indentation and remove pre fix commas from Org mode before flushing
53
+ strip_code_block!
54
+ @scripts << @buffer
55
+ @buffer = ''
56
+ end
57
+
58
+ @output_type = line.assigned_paragraph_type || line.paragraph_type
59
+ end
60
+
61
+ # Flushing is a bit different since we still need the metadata
62
+ # from lines in order to flush to correct tangle buffer
63
+ # TODO: Should be in the parent class as well...
64
+ def flush!; false; end
65
+
66
+ # TODO: This should be in the parent class....
67
+ def output_footnotes!; false; end
68
+
69
+ def strip_code_block!
70
+ if @code_block_indent and @code_block_indent > 0
71
+ strip_regexp = Regexp.new("^" + " " * @code_block_indent)
72
+ @buffer.gsub!(strip_regexp, "")
73
+ end
74
+ @code_block_indent = nil
75
+
76
+ # Strip proctective commas generated by Org mode (C-c ')
77
+ @buffer.gsub! /^(\s*)(,)(\s*)([*]|#\+)/ do |match|
78
+ "#{$1}#{$3}#{$4}"
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,58 @@
1
+ module OrgConverge
2
+ class Command
3
+ attr_reader :dotorg
4
+ attr_reader :logger
5
+ attr_reader :ob
6
+
7
+ def initialize(options)
8
+ @options = options
9
+ @dotorg = options['<org_file>']
10
+ @logger = Logger.new(options['--log'] || STDOUT)
11
+ @root_dir = options['--root-dir']
12
+ @ob = Orgmode::Parser.new(File.read(dotorg)).babelize
13
+ end
14
+
15
+ def execute!
16
+ case
17
+ when @options['--showfiles']
18
+
19
+ showfiles
20
+ when @options['--tangle']
21
+ tangle!
22
+ else
23
+ converge!
24
+ end
25
+
26
+ true
27
+ rescue => e
28
+ false
29
+ end
30
+
31
+ def converge!
32
+ tangle!
33
+ end
34
+
35
+ def tangle!
36
+ begin
37
+ babel = Orgmode::Babel.new(ob, { :logger => logger, :root_dir => @root_dir })
38
+ results = babel.tangle!
39
+ rescue Orgmode::Babel::TangleError
40
+ logger.error "Cannot converge because there were errors during tangle step".red
41
+ end
42
+ end
43
+
44
+ def showfiles
45
+ ob.tangle.each do |file, lines|
46
+ puts "---------- #{file} --------------".green
47
+ lines.each do |line|
48
+ puts line
49
+ end
50
+ end
51
+
52
+ ob.scripts.each_with_index do |script, index|
53
+ puts "---------- script: #{index} --------------".green
54
+ puts script
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module OrgConverge
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,37 @@
1
+ require 'org-ruby'
2
+ require 'org-converge/babel_output_buffer'
3
+ require 'org-converge/babel'
4
+ require 'org-converge/command'
5
+ require 'org-converge/version'
6
+
7
+ module Orgmode
8
+ class Parser
9
+
10
+ # This would return a babel output buffer which has the methods
11
+ # needed in order to be able to tangle the files
12
+ def babelize
13
+ # Feed the parsed contens and create the necessary internal structures
14
+ # for doing babel like features
15
+ output = ''
16
+ ob = BabelOutputBuffer.new(output)
17
+ translate(@header_lines, ob)
18
+ @headlines.each do |headline|
19
+ translate(headline.body_lines, ob)
20
+ end
21
+
22
+ ob
23
+ end
24
+ end
25
+ end
26
+
27
+ module StringWithColors
28
+ def red; colorize("\e[0m\e[31m"); end
29
+ def green; colorize("\e[0m\e[32m"); end
30
+ def yellow; colorize("\e[0m\e[33m"); end
31
+ def bold; colorize("\e[0m\e[1m"); end
32
+ def colorize(color_code); "#{color_code}#{self}\e[0m"; end
33
+ end
34
+
35
+ class String
36
+ include StringWithColors
37
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/org-converge/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Waldemar Quevedo"]
6
+ gem.email = ["waldemar.quevedo@gmail.com"]
7
+ gem.description = %q{A light configuration management tool for Org mode}
8
+ gem.summary = %q{Provides an 'org-converge' command which can be used for tangling and running Org mode code blocks}
9
+ gem.homepage = "https://github.com/wallyqs/org-converge"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "org-converge"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = OrgConverge::VERSION
17
+ gem.add_runtime_dependency('docopt', '0.5.0')
18
+ gem.add_runtime_dependency('org-ruby', '~> 0.9.2')
19
+ end
@@ -0,0 +1,7 @@
1
+ bind: 0.0.0.0
2
+ port: 2442
3
+
4
+ mysql:
5
+ db: users
6
+ host: somewhere-example.local
7
+ password: 111111111
@@ -0,0 +1,18 @@
1
+ #+TITLE: Relative Tangle
2
+
3
+ In this test, tangles files will exist relative to this file.
4
+
5
+ #+begin_src yaml :tangle conf.yml
6
+ bind: 0.0.0.0
7
+ port: 2442
8
+ #+end_src
9
+
10
+ e.g. including the connections to the database in the same file:
11
+
12
+ #+begin_src yaml :tangle conf.yml
13
+
14
+ mysql:
15
+ db: users
16
+ host: somewhere-example.local
17
+ password: 111111111
18
+ #+end_src
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe OrgConverge::Command do
4
+ context "when converging 'basic_tangle'" do
5
+ example_dir = File.join(EXAMPLES_DIR, 'basic_tangle')
6
+
7
+ it "should tangle a 'conf.yml' file" do
8
+ setup_file = File.join(example_dir, 'setup.org')
9
+ o = OrgConverge::Command.new({
10
+ '<org_file>' => setup_file,
11
+ '--root-dir' => example_dir
12
+ })
13
+ success = o.execute!
14
+ success.should == true
15
+
16
+ expected_contents = File.read(File.join(example_dir, 'conf.yml.expected'))
17
+
18
+ resulting_file = File.join(example_dir, 'conf.yml')
19
+ File.exists?(resulting_file).should == true
20
+
21
+ result = File.read(resulting_file)
22
+
23
+ result.should == expected_contents
24
+ end
25
+ end
26
+ end
27
+
28
+
@@ -0,0 +1,6 @@
1
+ require 'org-converge'
2
+ require 'fileutils'
3
+
4
+ RESULTS_DIR = File.expand_path("tmp/#{Time.now.strftime("test_%s")}", File.dirname(__FILE__))
5
+ SPEC_DIR = File.dirname(File.expand_path('.', __FILE__))
6
+ EXAMPLES_DIR = File.join(SPEC_DIR, 'converge_examples')
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: org-converge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Waldemar Quevedo
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-03-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: docopt
16
+ requirement: &70317759431040 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: 0.5.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70317759431040
25
+ - !ruby/object:Gem::Dependency
26
+ name: org-ruby
27
+ requirement: &70317759430520 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70317759430520
36
+ description: A light configuration management tool for Org mode
37
+ email:
38
+ - waldemar.quevedo@gmail.com
39
+ executables:
40
+ - org-converge
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitmodules
45
+ - Gemfile
46
+ - LICENSE
47
+ - README.org
48
+ - Rakefile
49
+ - TODO
50
+ - bin/org-converge
51
+ - examples/apt-get-install/setup.org
52
+ - examples/fluentd/setup.org
53
+ - examples/macro-config/setup.org
54
+ - examples/simple/setup.org
55
+ - lib/org-converge.rb
56
+ - lib/org-converge/babel.rb
57
+ - lib/org-converge/babel_output_buffer.rb
58
+ - lib/org-converge/command.rb
59
+ - lib/org-converge/version.rb
60
+ - org-converge.gemspec
61
+ - spec/converge_examples/basic_tangle/conf.yml.expected
62
+ - spec/converge_examples/basic_tangle/setup.org
63
+ - spec/converge_spec.rb
64
+ - spec/spec_helper.rb
65
+ homepage: https://github.com/wallyqs/org-converge
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.10
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Provides an 'org-converge' command which can be used for tangling and running
89
+ Org mode code blocks
90
+ test_files:
91
+ - spec/converge_examples/basic_tangle/conf.yml.expected
92
+ - spec/converge_examples/basic_tangle/setup.org
93
+ - spec/converge_spec.rb
94
+ - spec/spec_helper.rb