automateit 0.70923

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.
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