conman 0.1.0 → 0.1.1
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/README.md +55 -17
- data/lib/conman/ingredient.rb +35 -0
- data/lib/conman/recipe.rb +1 -34
- data/lib/conman.rb +10 -9
- metadata +6 -18
data/README.md
CHANGED
@@ -3,20 +3,31 @@ conman - Server Configuration Management
|
|
3
3
|
|
4
4
|
__This is still under active development and is subject to change__
|
5
5
|
|
6
|
+
Conman is a simple server configuration management library. The core concepts are around:
|
7
|
+
|
8
|
+
* _Ingredients_ - reusable, sharable components that achieve specific tasks
|
9
|
+
* _Recipes_ - your public or private recipes that make use of the Ingredients
|
10
|
+
|
11
|
+
Ingredients should ensure that they are idempotent. Public Recipes may include setting up a LAMP system for example.
|
12
|
+
|
6
13
|
Installation
|
7
14
|
------------
|
8
15
|
|
9
16
|
gem install conman
|
10
17
|
|
11
|
-
|
12
|
-
|
18
|
+
Ingredient Repository
|
19
|
+
---------------------
|
13
20
|
|
14
|
-
Our
|
21
|
+
Our ingredient library can be found at: [github.com/moocode/ingredients](http://github.com/moocode/ingredients)
|
15
22
|
|
16
|
-
Creating your first
|
17
|
-
|
23
|
+
Creating your first Ingredient
|
24
|
+
------------------------------
|
18
25
|
|
19
|
-
|
26
|
+
An ingredient is a simple Ruby Class whose name ends with Ingredient and (optionally) subclasses Ingredient.
|
27
|
+
The Ingredient superclass just provides some helper methods if you wish to use them. Because they are just Ruby classes
|
28
|
+
they can be tested using any test framework you like. See our ingredients repository for some examples.
|
29
|
+
|
30
|
+
class FileIngredient < Ingredient
|
20
31
|
def create(options={})
|
21
32
|
`touch #{options[:path]}` unless exists? :path => options[:path]
|
22
33
|
end
|
@@ -26,22 +37,49 @@ Creating your first Recipe
|
|
26
37
|
end
|
27
38
|
end
|
28
39
|
|
29
|
-
Your first
|
30
|
-
|
40
|
+
Your first Recipe
|
41
|
+
-----------------
|
31
42
|
|
32
|
-
class
|
33
|
-
file :create :path => '/tmp/foo.txt'
|
43
|
+
class MyRecipe < Recipe
|
44
|
+
file :create, :path => '/tmp/foo.txt'
|
34
45
|
end
|
35
46
|
|
36
|
-
|
37
|
-
|
47
|
+
Running your Recipe
|
48
|
+
-------------------
|
49
|
+
|
50
|
+
conman ships with a binary for running your recipes. It takes a path to a folder of ingredients and a recipe file:
|
51
|
+
|
52
|
+
conman -i /path/to/ingredients /path/to/recipes/my_recipe.rb
|
53
|
+
|
54
|
+
Alternatively you can run them from a script (handy for testing)
|
38
55
|
|
39
|
-
|
40
|
-
|
41
|
-
|
56
|
+
Conman.init :ingredients => '/path/to/ingredients/'
|
57
|
+
Conman.run '/path/to/recipes/my_recipe.rb'
|
58
|
+
|
59
|
+
Testing
|
60
|
+
-------
|
61
|
+
|
62
|
+
Here's an example of a TestUnit test for an ingredient:
|
63
|
+
|
64
|
+
require 'test/unit'
|
65
|
+
require 'rubygems'
|
66
|
+
require 'mocha'
|
67
|
+
require 'conman'
|
68
|
+
|
69
|
+
class FileIngredientTest < Test::Unit::TestCase
|
70
|
+
def setup
|
71
|
+
@@conman ||= Conman.init(:ingredients => '/path/to/ingredients/file.rb')
|
72
|
+
@file = FileIngredient.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_create
|
76
|
+
FileIngredient.any_instance.expects(:create).returns('touch /tmp/moo.txt')
|
77
|
+
@file.create :path => '/tmp/moo.txt'
|
78
|
+
end
|
79
|
+
end
|
42
80
|
|
43
|
-
|
44
|
-
|
81
|
+
Preparing a live server
|
82
|
+
-----------------------
|
45
83
|
|
46
84
|
First you need to install all the pre-requisites (ruby, rubygems, conman, git-core)
|
47
85
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Ingredient
|
2
|
+
|
3
|
+
def self.method_missing(m, *args, &block)
|
4
|
+
Recipe.execute_recipe(m, args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def method_missing(m, *args, &block)
|
8
|
+
Recipe.execute_recipe(m, args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.execute_recipe(class_name, args={})
|
12
|
+
clazz_name = (class_name.to_s.split('_').map {|w| w.capitalize}.join) + 'Ingredient'
|
13
|
+
clazz = Kernel.const_get(clazz_name)
|
14
|
+
method = args.shift
|
15
|
+
#puts "Calling #{clazz.name}##{method} with #{args.first.inspect}"
|
16
|
+
recipe = clazz.new
|
17
|
+
if args.empty?
|
18
|
+
recipe.send method
|
19
|
+
else
|
20
|
+
recipe.send method, args.first
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def option?(options, targets)
|
25
|
+
targets = [targets] unless targets.is_a? Array
|
26
|
+
targets.each do |target|
|
27
|
+
return false unless options[target] and !options[target].nil? and !options[target].to_s.strip.empty?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def option!(options, targets)
|
32
|
+
raise ArgumentError, "Missing required parameter from #{options.inspect}, required = #{targets.inspect}" unless option?(options, targets)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/conman/recipe.rb
CHANGED
@@ -1,35 +1,2 @@
|
|
1
|
-
class Recipe
|
2
|
-
|
3
|
-
def self.method_missing(m, *args, &block)
|
4
|
-
Recipe.execute_recipe(m, args)
|
5
|
-
end
|
6
|
-
|
7
|
-
def method_missing(m, *args, &block)
|
8
|
-
Recipe.execute_recipe(m, args)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.execute_recipe(class_name, args={})
|
12
|
-
clazz_name = (class_name.to_s.split('_').map {|w| w.capitalize}.join) + 'Recipe'
|
13
|
-
clazz = Kernel.const_get(clazz_name)
|
14
|
-
method = args.shift
|
15
|
-
#puts "Calling #{clazz.name}##{method} with #{args.first.inspect}"
|
16
|
-
recipe = clazz.new
|
17
|
-
if args.empty?
|
18
|
-
recipe.send method
|
19
|
-
else
|
20
|
-
recipe.send method, args.first
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def option?(options, targets)
|
25
|
-
targets = [targets] unless targets.is_a? Array
|
26
|
-
targets.each do |target|
|
27
|
-
return false unless options[target] and !options[target].nil? and !options[target].to_s.strip.empty?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def option!(options, targets)
|
32
|
-
raise ArgumentError, "Missing required parameter from #{options.inspect}, required = #{targets.inspect}" unless option?(options, targets)
|
33
|
-
end
|
34
|
-
|
1
|
+
class Recipe < Ingredient
|
35
2
|
end
|
data/lib/conman.rb
CHANGED
@@ -1,24 +1,25 @@
|
|
1
|
+
require 'conman/ingredient'
|
1
2
|
require 'conman/recipe'
|
2
3
|
|
3
4
|
class Conman
|
4
5
|
def self.init(options)
|
5
|
-
|
6
|
+
ingredients_folder = options[:ingredients]
|
6
7
|
|
7
|
-
puts "initializing with
|
8
|
+
puts "initializing with ingredients folder: #{ingredients_folder}"
|
8
9
|
|
9
|
-
abort "You must specify
|
10
|
+
abort "You must specify an ingredient" if ingredients_folder.nil? or ingredients_folder.empty?
|
10
11
|
|
11
|
-
|
12
|
+
ingredients = []
|
12
13
|
|
13
|
-
Dir.glob(
|
14
|
-
|
15
|
-
|
14
|
+
Dir.glob(ingredients_folder + '*').each do |f|
|
15
|
+
ingredients << "#{File.join f, File.basename(f)}.rb" if File.directory? f
|
16
|
+
ingredients << f unless File.directory? f
|
16
17
|
end
|
17
18
|
|
18
19
|
#puts "Loading recipes: #{recipes.inspect}"
|
19
|
-
puts "Loading #{
|
20
|
+
puts "Loading #{ingredients.size} ingredient(s)"
|
20
21
|
|
21
|
-
|
22
|
+
ingredients.each {|ingredient| load ingredient}
|
22
23
|
end
|
23
24
|
|
24
25
|
def self.run(options)
|
metadata
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: false
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 0.1.0
|
4
|
+
version: 0.1.1
|
11
5
|
platform: ruby
|
12
6
|
authors:
|
13
7
|
- Richard Taylor
|
@@ -31,10 +25,10 @@ files:
|
|
31
25
|
- LICENSE
|
32
26
|
- README.md
|
33
27
|
- lib/conman.rb
|
28
|
+
- lib/conman/ingredient.rb
|
34
29
|
- lib/conman/recipe.rb
|
35
|
-
- bin/conman
|
36
30
|
has_rdoc: true
|
37
|
-
homepage: http://github.com/
|
31
|
+
homepage: http://github.com/moocode/conman
|
38
32
|
licenses: []
|
39
33
|
|
40
34
|
post_install_message:
|
@@ -44,27 +38,21 @@ rdoc_options:
|
|
44
38
|
require_paths:
|
45
39
|
- lib
|
46
40
|
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
41
|
requirements:
|
49
42
|
- - ">="
|
50
43
|
- !ruby/object:Gem::Version
|
51
|
-
hash: 3
|
52
|
-
segments:
|
53
|
-
- 0
|
54
44
|
version: "0"
|
45
|
+
version:
|
55
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
-
none: false
|
57
47
|
requirements:
|
58
48
|
- - ">="
|
59
49
|
- !ruby/object:Gem::Version
|
60
|
-
hash: 3
|
61
|
-
segments:
|
62
|
-
- 0
|
63
50
|
version: "0"
|
51
|
+
version:
|
64
52
|
requirements: []
|
65
53
|
|
66
54
|
rubyforge_project: conman
|
67
|
-
rubygems_version: 1.3.
|
55
|
+
rubygems_version: 1.3.5
|
68
56
|
signing_key:
|
69
57
|
specification_version: 3
|
70
58
|
summary: conman is a server configuration management library
|