automateit 0.70923

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data.tar.gz.sig +1 -0
  2. data/CHANGES.txt +100 -0
  3. data/Hoe.rake +35 -0
  4. data/Manifest.txt +111 -0
  5. data/README.txt +44 -0
  6. data/Rakefile +284 -0
  7. data/TESTING.txt +57 -0
  8. data/TODO.txt +26 -0
  9. data/TUTORIAL.txt +390 -0
  10. data/bin/ai +3 -0
  11. data/bin/aifield +82 -0
  12. data/bin/aitag +128 -0
  13. data/bin/automateit +117 -0
  14. data/docs/friendly_errors.txt +50 -0
  15. data/docs/previews.txt +86 -0
  16. data/env.sh +4 -0
  17. data/examples/basic/Rakefile +26 -0
  18. data/examples/basic/config/automateit_env.rb +16 -0
  19. data/examples/basic/config/fields.yml +3 -0
  20. data/examples/basic/config/tags.yml +13 -0
  21. data/examples/basic/dist/README.txt +9 -0
  22. data/examples/basic/dist/myapp_server.erb +30 -0
  23. data/examples/basic/install.log +15 -0
  24. data/examples/basic/lib/README.txt +10 -0
  25. data/examples/basic/recipes/README.txt +4 -0
  26. data/examples/basic/recipes/install.rb +53 -0
  27. data/examples/basic/recipes/uninstall.rb +6 -0
  28. data/gpl.txt +674 -0
  29. data/lib/automateit.rb +66 -0
  30. data/lib/automateit/account_manager.rb +106 -0
  31. data/lib/automateit/account_manager/linux.rb +171 -0
  32. data/lib/automateit/account_manager/passwd.rb +69 -0
  33. data/lib/automateit/account_manager/portable.rb +136 -0
  34. data/lib/automateit/address_manager.rb +165 -0
  35. data/lib/automateit/address_manager/linux.rb +80 -0
  36. data/lib/automateit/address_manager/portable.rb +37 -0
  37. data/lib/automateit/cli.rb +80 -0
  38. data/lib/automateit/common.rb +65 -0
  39. data/lib/automateit/constants.rb +33 -0
  40. data/lib/automateit/edit_manager.rb +292 -0
  41. data/lib/automateit/error.rb +10 -0
  42. data/lib/automateit/field_manager.rb +103 -0
  43. data/lib/automateit/interpreter.rb +641 -0
  44. data/lib/automateit/package_manager.rb +242 -0
  45. data/lib/automateit/package_manager/apt.rb +63 -0
  46. data/lib/automateit/package_manager/egg.rb +64 -0
  47. data/lib/automateit/package_manager/gem.rb +179 -0
  48. data/lib/automateit/package_manager/portage.rb +69 -0
  49. data/lib/automateit/package_manager/yum.rb +65 -0
  50. data/lib/automateit/platform_manager.rb +47 -0
  51. data/lib/automateit/platform_manager/darwin.rb +30 -0
  52. data/lib/automateit/platform_manager/debian.rb +26 -0
  53. data/lib/automateit/platform_manager/freebsd.rb +25 -0
  54. data/lib/automateit/platform_manager/gentoo.rb +26 -0
  55. data/lib/automateit/platform_manager/lsb.rb +40 -0
  56. data/lib/automateit/platform_manager/struct.rb +78 -0
  57. data/lib/automateit/platform_manager/uname.rb +29 -0
  58. data/lib/automateit/platform_manager/windows.rb +33 -0
  59. data/lib/automateit/plugin.rb +7 -0
  60. data/lib/automateit/plugin/base.rb +32 -0
  61. data/lib/automateit/plugin/driver.rb +218 -0
  62. data/lib/automateit/plugin/manager.rb +232 -0
  63. data/lib/automateit/project.rb +460 -0
  64. data/lib/automateit/root.rb +14 -0
  65. data/lib/automateit/service_manager.rb +79 -0
  66. data/lib/automateit/service_manager/chkconfig.rb +39 -0
  67. data/lib/automateit/service_manager/rc_update.rb +37 -0
  68. data/lib/automateit/service_manager/sysv.rb +126 -0
  69. data/lib/automateit/service_manager/update_rcd.rb +35 -0
  70. data/lib/automateit/shell_manager.rb +261 -0
  71. data/lib/automateit/shell_manager/base_link.rb +67 -0
  72. data/lib/automateit/shell_manager/link.rb +24 -0
  73. data/lib/automateit/shell_manager/portable.rb +421 -0
  74. data/lib/automateit/shell_manager/symlink.rb +32 -0
  75. data/lib/automateit/shell_manager/which.rb +25 -0
  76. data/lib/automateit/tag_manager.rb +63 -0
  77. data/lib/automateit/tag_manager/struct.rb +101 -0
  78. data/lib/automateit/tag_manager/tag_parser.rb +91 -0
  79. data/lib/automateit/tag_manager/yaml.rb +29 -0
  80. data/lib/automateit/template_manager.rb +55 -0
  81. data/lib/automateit/template_manager/base.rb +172 -0
  82. data/lib/automateit/template_manager/erb.rb +17 -0
  83. data/lib/ext/metaclass.rb +17 -0
  84. data/lib/ext/object.rb +18 -0
  85. data/lib/hashcache.rb +22 -0
  86. data/lib/helpful_erb.rb +63 -0
  87. data/lib/nested_error.rb +33 -0
  88. data/lib/queued_logger.rb +68 -0
  89. data/lib/tempster.rb +239 -0
  90. data/misc/index_gem_repository.rb +303 -0
  91. data/misc/setup_egg.rb +12 -0
  92. data/misc/setup_gem_dependencies.sh +7 -0
  93. data/misc/setup_rubygems.sh +21 -0
  94. data/misc/which.cmd +6 -0
  95. data/spec/extras/automateit_service_sysv_test +50 -0
  96. data/spec/extras/scratch.rb +15 -0
  97. data/spec/extras/simple_recipe.rb +8 -0
  98. data/spec/integration/account_manager_spec.rb +218 -0
  99. data/spec/integration/address_manager_linux_spec.rb +119 -0
  100. data/spec/integration/address_manager_portable_spec.rb +30 -0
  101. data/spec/integration/cli_spec.rb +215 -0
  102. data/spec/integration/examples_spec.rb +54 -0
  103. data/spec/integration/examples_spec_editor.rb +71 -0
  104. data/spec/integration/package_manager_spec.rb +104 -0
  105. data/spec/integration/platform_manager_spec.rb +69 -0
  106. data/spec/integration/service_manager_sysv_spec.rb +115 -0
  107. data/spec/integration/shell_manager_spec.rb +471 -0
  108. data/spec/integration/template_manager_erb_spec.rb +31 -0
  109. data/spec/spec_helper.rb +23 -0
  110. data/spec/unit/edit_manager_spec.rb +162 -0
  111. data/spec/unit/field_manager_spec.rb +79 -0
  112. data/spec/unit/hashcache_spec.rb +28 -0
  113. data/spec/unit/interpreter_spec.rb +98 -0
  114. data/spec/unit/platform_manager_spec.rb +44 -0
  115. data/spec/unit/plugins_spec.rb +253 -0
  116. data/spec/unit/tag_manager_spec.rb +189 -0
  117. data/spec/unit/template_manager_erb_spec.rb +137 -0
  118. metadata +249 -0
  119. metadata.gz.sig +0 -0
@@ -0,0 +1,31 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "AutomateIt::TemplateManager::ERB" do
4
+ before(:all) do
5
+ @a = AutomateIt.new(:verbosity => Logger::WARN)
6
+ @m = @a.template_manager
7
+ @d = @m[:erb]
8
+ @d.setup(:default_check => :mtime)
9
+ @d.available?.should be_true
10
+ end
11
+
12
+ it "should set mode when rendering" do
13
+ @a.mktempdircd do
14
+ source = "foo"
15
+ target = "bar"
16
+ mode1 = 0646 if INTERPRETER.shell_manager.provides_mode?
17
+ mode2 = 0100646
18
+ File.open(source, "w+"){|h| h.write("<%=variable%>")}
19
+
20
+ opts = {:file => source, :to => target, :locals => {:variable => 42}}
21
+ opts[:mode] = mode1 if mode1
22
+ @a.render(opts).should be_true
23
+ File.read(target).should == "42"
24
+ if INTERPRETER.shell_manager.provides_mode?
25
+ File.stat(target).mode.should == mode2
26
+ else
27
+ puts "NOTE: Can't check permission modes on this platform, #{__FILE__}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ AutomateIt_Base = File.dirname(File.expand_path(__FILE__)) unless defined?(AutomateIt_Base)
2
+ AutomateIt_Lib = File.join(AutomateIt_Base, "/../lib") unless defined?(AutomateIt_Lib)
3
+ AutomateIt_Bin = File.join(AutomateIt_Base, "/../bin") unless defined?(AutomateIt_Bin)
4
+
5
+ $LOAD_PATH.unshift(AutomateIt_Lib)
6
+
7
+ # Remove environmental variables that will contaminate tests
8
+ ENV.delete("AUTOMATEIT_PROJECT")
9
+
10
+ require 'automateit'
11
+
12
+ # Create a global instance, using WARN verbosity so that
13
+ # INTERPRETER.mktempdircd calls don't generate output.
14
+ unless defined?(INTERPRETER)
15
+ INTERPRETER = AutomateIt.new(:verbosity => Logger::WARN)
16
+ end
17
+
18
+ # Inject matchers into interpreter, e.g., 'should be_true'
19
+ INTERPRETER.class.send(:include, Spec::Matchers)
20
+
21
+ def write_to(filename, text)
22
+ File.open(filename, "w+"){|h| h.write(text)}
23
+ end
@@ -0,0 +1,162 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "AutomateIt::EditManager for strings" do
4
+ before(:all) do
5
+ @a = AutomateIt.new(:verbosity => Logger::WARN)
6
+ end
7
+
8
+ before(:each) do
9
+ @input = "This\nis\n\a\nstring."
10
+ end
11
+
12
+ it "should pass contents" do
13
+ @a.edit(:text => @input) do
14
+ contents.should == "This\nis\n\a\nstring."
15
+ end
16
+ end
17
+
18
+ it "should pass params" do
19
+ @a.edit(:text => @input, :params => {:hello => "world"}) do
20
+ params[:hello].should == "world"
21
+ end
22
+ end
23
+
24
+ it "should find contained lines" do
25
+ @a.edit(:text => @input) do
26
+ contains?(/This/).should == true
27
+ end
28
+ end
29
+
30
+ it "should prepend lines to the top" do
31
+ output = @a.edit(:text => @input) do
32
+ prepend "PREPEND"
33
+ prepend "PREPEND" # Duplicate line will be ignored.
34
+ end
35
+ output.should =~ /\APREPEND\nThis/s
36
+ end
37
+
38
+ it "should prepend lines to the top unless they match an expression" do
39
+ output = @a.edit(:text => @input) do
40
+ prepend "PREPEND", :unless => /PR.+ND/
41
+ prepend "PRETENDER", :unless => /PR.+ND/ # Regexp matches.
42
+ end
43
+ output.should =~ /\APREPEND\nThis/s
44
+ end
45
+
46
+ it "should append lines to the bottom" do
47
+ output = @a.edit(:text => @input) do
48
+ append "APPEND"
49
+ append "APPEND" # Duplicate line will be ignored.
50
+ end
51
+ output.should =~ /string\.\nAPPEND\Z/s
52
+ end
53
+
54
+ it "should append lines to the bottom unless they match an expression" do
55
+ output = @a.edit(:text => @input) do
56
+ append "APPEND", :unless => /^APP/
57
+ append "APPENDIX", :unless => /^APP/ # Regexp matches.
58
+ end
59
+ output.should =~ /^string\.\nAPPEND\Z/s
60
+ end
61
+
62
+ it "should delete lines" do
63
+ output = @a.edit(:text => @input) do
64
+ delete "This"
65
+ end
66
+ output.should_not =~ /This/
67
+ end
68
+
69
+ it "should comment lines" do
70
+ output = @a.edit(:text => @input) do
71
+ comment_style "<", ">"
72
+ comment "This"
73
+ end
74
+ output.should =~ /^<This>$/s
75
+ end
76
+
77
+ it "should uncomment lines" do
78
+ output = @a.edit(:text => @input) do
79
+ comment_style "T", "s"
80
+ uncomment "hi"
81
+ end
82
+ output.should =~ /^hi\nis\n/s
83
+ end
84
+
85
+ it "should replace strings" do
86
+ output = @a.edit(:text => @input) do
87
+ replace "This", "That"
88
+ end
89
+ output.should =~ /^That\nis\n/s
90
+ end
91
+
92
+ it "should manipulate contents" do
93
+ output = @a.edit(:text => @input) do
94
+ manipulate do |buffer|
95
+ buffer.gsub(/i/, "@")
96
+ end
97
+ end
98
+ output.should =~ /^Th@s\n@s\n/
99
+ end
100
+
101
+ it "should tell if content is different after an edit" do
102
+ @a.edit(:text => @input) do
103
+ different?.should == false
104
+ append "changing"
105
+ different?.should == true
106
+ end
107
+ end
108
+
109
+ it "should provide session with access to interpreter" do
110
+ @a.lookup["foo"] = "bar"
111
+ output = @a.edit(:text => @input) do
112
+ manipulate do |b|
113
+ lookup "foo"
114
+ end
115
+ end
116
+ output.should == "bar"
117
+ end
118
+
119
+ it "should raise exceptions for invalid methods" do
120
+ lambda {
121
+ @a.edit(:text => @input) do
122
+ qwoiuerjzxiuo
123
+ end
124
+ }.should raise_error(NameError, /qwoiuerjzxiuo/)
125
+ end
126
+ end
127
+
128
+ describe "AutomateIt::EditManager for files" do
129
+ before(:all) do
130
+ @a = AutomateIt.new(:verbosity => Logger::WARN)
131
+ @filename = "input"
132
+ end
133
+
134
+ before(:each) do
135
+ @input = "This\nis\n\a\nstring."
136
+ end
137
+
138
+ it "should edit a file" do
139
+ File.should_receive(:read).with(@filename).and_return(@input)
140
+ File.should_receive(:open).with(@filename, "w+").and_return(true)
141
+ result = @a.edit(:file => @filename) do
142
+ append "APPEND"
143
+ end
144
+ result.should be_true
145
+ end
146
+
147
+ it "should not rewrite an unchanged file" do
148
+ File.should_receive(:read).with(@filename).and_return(@input)
149
+ result = @a.edit(:file => @filename) do
150
+ # Do nothing
151
+ end
152
+ result.should be_false
153
+ end
154
+
155
+ it "should default to editing a file" do
156
+ File.should_receive(:read).with(@filename).and_return(@input)
157
+ result = @a.edit(@filename) do
158
+ # Do nothing
159
+ end
160
+ result.should be_false
161
+ end
162
+ end
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "AutomateIt::FieldManager", :shared => true do
4
+ before(:all) do
5
+ @a = AutomateIt.new
6
+ @a.tags << "magical_hosts"
7
+ @m = @a.field_manager
8
+ end
9
+
10
+ it "should be able to lookup entire hash" do
11
+ rv = @m.lookup("*")
12
+ rv.keys.should include("hash")
13
+ rv["hash"].should be_a_kind_of(Hash)
14
+ rv.keys.should include("key")
15
+ rv["key"].should == "value"
16
+ end
17
+
18
+ it "should lookup keys by string" do
19
+ @m.lookup("key").should == "value"
20
+ end
21
+
22
+ it "should lookup keys by symbol" do
23
+ @m.lookup(:key).should == "value"
24
+ end
25
+
26
+ it "should lookup hash" do
27
+ @m.lookup(:hash)["leafkey"].should == "leafvalue"
28
+ end
29
+
30
+ it "should lookup leaves" do
31
+ @m.lookup("hash#leafkey").should == "leafvalue"
32
+ @m.lookup("hash#branchkey#deepleafkey").should == "deepleafvalue"
33
+ end
34
+
35
+ it "should have aliased lookup into the interpreter" do
36
+ @m.should equal(@m.interpreter.field_manager)
37
+ @m[:yaml].should equal(@m.interpreter.field_manager[:yaml])
38
+ end
39
+
40
+ it "should be aliases into the interpreter" do
41
+ @a.lookup("hash#leafkey").should == "leafvalue"
42
+ end
43
+ end
44
+
45
+ describe AutomateIt::FieldManager::Struct do
46
+ it_should_behave_like "AutomateIt::FieldManager"
47
+
48
+ before(:all) do
49
+ @m.setup(:default => :struct, :struct => {
50
+ "key" => "value",
51
+ "hash" => {
52
+ "leafkey" => "leafvalue",
53
+ "branchkey" => {
54
+ "deepleafkey" => "deepleafvalue",
55
+ },
56
+ },
57
+ })
58
+ end
59
+ end
60
+
61
+ describe AutomateIt::FieldManager::YAML do
62
+ it_should_behave_like "AutomateIt::FieldManager"
63
+
64
+ before(:all) do
65
+ @m[:yaml].should_receive(:_read).with("demo.yml").and_return(<<-EOB)
66
+ <%="key"%>: value
67
+ hash:
68
+ leafkey: leafvalue
69
+ branchkey:
70
+ deepleafkey: deepleafvalue
71
+ magical: <%= tagged?("magical_hosts") ? true : false %>
72
+ EOB
73
+ @m.setup(:default => :yaml, :file => "demo.yml")
74
+ end
75
+
76
+ it "should expose the interpreter to ERB statements" do
77
+ @a.lookup("magical").should be_true
78
+ end
79
+ end
@@ -0,0 +1,28 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "HashCache" do
4
+ before(:each) do
5
+ @c = HashCache.new
6
+ end
7
+
8
+ it "should store and fetch values" do
9
+ @c.store("foo", "bar")
10
+ @c.fetch("foo").should == "bar"
11
+ end
12
+
13
+ it "should store values when needed if given a block" do
14
+ @c.fetch("foo"){"bar"}.should == "bar"
15
+ @c.fetch("foo").should == "bar"
16
+ end
17
+
18
+ it "should use HashCached values" do
19
+ @c.fetch("foo"){"bar"}.should == "bar"
20
+ @c.fetch("foo"){raise Exception.new("won't be raised")}.should == "bar"
21
+ end
22
+
23
+ it "should invalidate values" do
24
+ @c.store("foo", "bar")
25
+ @c.delete("foo")
26
+ @c.fetch("foo").should be_nil
27
+ end
28
+ end
@@ -0,0 +1,98 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe AutomateIt::Interpreter do
4
+ before(:all) do
5
+ @a = AutomateIt::Interpreter.new(:verbosity => Logger::WARN)
6
+ end
7
+
8
+ it "should have a logger" do
9
+ @a.log.should be_a_kind_of(Logger)
10
+ end
11
+
12
+ it "should provide a preview mode" do
13
+ @a.preview = true
14
+ @a.preview?.should be_true
15
+ @a.preview_for("answer"){42}.should == :preview
16
+ @a.noop?.should be_true
17
+ @a.writing?.should be_false
18
+
19
+ @a.preview = false
20
+ @a.preview?.should be_false
21
+ @a.preview_for("answer"){42}.should == 42
22
+ @a.noop?.should be_false
23
+ @a.writing?.should be_true
24
+ end
25
+
26
+ it "should eval commands within Interpreter's context" do
27
+ @a.preview = true
28
+ @a.instance_eval{preview?}.should be_true
29
+ @a.instance_eval{self}.should == @a
30
+ @a.instance_eval("preview?").should be_true
31
+ end
32
+
33
+ it "should be able to include methods into a class" do
34
+ @a.preview = true
35
+ @a.instance_eval do
36
+ class MyInterpreterWrapper1
37
+ def initialize(interpreter)
38
+ interpreter.include_in(self)
39
+ end
40
+
41
+ def answer
42
+ 42
43
+ end
44
+
45
+ # Method overridden by Interpreter#preview?
46
+ def preview?
47
+ raise ArgumentError.new("MyInterpreterWrapper#preview? wasn't overriden")
48
+ end
49
+ end
50
+ mc = MyInterpreterWrapper1.new(self)
51
+ mc.answer.should == 42 # Instance method
52
+ mc.preview?.should == true # Interpreter method that overrides instance
53
+ lambda{ mc.not_a_method }.should raise_error(NoMethodError)
54
+ end
55
+ end
56
+
57
+ it "should be able to add method_missing to a class" do
58
+ @a.preview = true
59
+ @a.instance_eval do
60
+ class MyInterpreterWrapper2
61
+ def initialize(interpreter)
62
+ interpreter.add_method_missing_to(self)
63
+ end
64
+
65
+ def answer
66
+ 42
67
+ end
68
+
69
+ # Method masking Interpreter#preview?
70
+ def preview?
71
+ 42
72
+ end
73
+ end
74
+ mc = MyInterpreterWrapper2.new(self)
75
+ mc.answer.should == 42 # Instance method
76
+ mc.preview?.should == 42 # Instance method masking Interpreter
77
+ lambda{ mc.not_a_method }.should raise_error(NoMethodError)
78
+ end
79
+ end
80
+
81
+ it "should be able to add method_missing to a class with an existing method_missing" do
82
+ @a.preview = true
83
+ @a.instance_eval do
84
+ class MyInterpreterWrapper3
85
+ def initialize(interpreter)
86
+ interpreter.add_method_missing_to(self)
87
+ end
88
+
89
+ def method_missing(method, *args, &block)
90
+ 42
91
+ end
92
+ end
93
+ mc = MyInterpreterWrapper3.new(self)
94
+ mc.answer.should == 42 # Instance#method_missing
95
+ mc.preview?.should == true # Interpreter method
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "AutomateIt::PlatformManager" do
4
+ before(:all) do
5
+ @a = AutomateIt.new
6
+ @m = @a.platform_manager
7
+ @m.setup(:default => :struct, :struct => {
8
+ :os => "mizrahi",
9
+ :arch => "realian",
10
+ :distro => "momo",
11
+ :version => "s100",
12
+ })
13
+ end
14
+
15
+ it "should query key by symbol" do
16
+ @m.query(:os).should == "mizrahi"
17
+ end
18
+
19
+ it "should query key by string" do
20
+ @m.query("distro").should == "momo"
21
+ end
22
+
23
+ it "should query by two-key query" do
24
+ @m.query("os#arch").should == "mizrahi_realian"
25
+ @m.query("distro#version").should == "momo_s100"
26
+ end
27
+
28
+ it "should query by three-part query" do
29
+ @m.query("os#distro#version").should == "mizrahi_momo_s100"
30
+ @m.query("distro#version#arch").should == "momo_s100_realian"
31
+ end
32
+
33
+ it "should query by aliases" do
34
+ @m.query("release#version").should == "s100_s100"
35
+ end
36
+
37
+ it "should fail on invalid top-level keys" do
38
+ lambda { @m.query(:asdf) }.should raise_error(IndexError)
39
+ end
40
+
41
+ it "should fail on invalid subkeys" do
42
+ lambda { @m.query("os#asdf") }.should raise_error(IndexError)
43
+ end
44
+ end