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
data/bin/ai ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ load File.join(File.dirname(__FILE__), "automateit")
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # XXX What can go wrong with this loading approach?
4
+ libdir = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
5
+ if File.directory?(libdir) and File.exists?(File.join(libdir, "automateit.rb"))
6
+ $LOAD_PATH.unshift(libdir)
7
+ end
8
+
9
+ require 'rubygems'
10
+ require 'optparse'
11
+ require 'automateit'
12
+
13
+ OptionParser.new do |parser|
14
+ PROG = File.basename($0)
15
+ opts = {}
16
+ parser.banner = <<EOB
17
+ #{PROG} - tool for querying AutomateIt fields
18
+
19
+ Usage: #{PROG} [options] query
20
+
21
+ Examples:
22
+ # Load 'myproject' and get value of 'user' field in 'myapp' hash:
23
+ #{PROG} -p myproject myapp#user
24
+
25
+ # Same but using environmental variable to specify project:
26
+ AUTOMATEIT_PROJECT=myproject
27
+ #{PROG} myapp#user
28
+
29
+ # Dump the 'myapp' hash contents as YAML
30
+ #{PROG} -y myapp#user
31
+
32
+ # Dump the 'myapp' hash contents as XML
33
+ #{PROG} -x myapp#user
34
+
35
+ Options:
36
+ EOB
37
+ parser.on("-p", "--project PATH", "Set project path") do |v|
38
+ opts[:project] = v
39
+ end
40
+
41
+ parser.on("-Y", "--yaml", "Dump as YAML") do |v|
42
+ opts[:yaml] = v
43
+ end
44
+
45
+ parser.on("-X", "--xml", "Dump as XML") do |v|
46
+ opts[:xml] = v
47
+ end
48
+
49
+ parser.on("-h", "--help", "Display this help message") do |v|
50
+ puts parser
51
+ exit
52
+ end
53
+
54
+ parser.on("-v", "--version", "Display version") do |v|
55
+ puts AutomateIt::VERSION
56
+ exit 0
57
+ end
58
+
59
+ args = parser.parse!.dup
60
+
61
+ # Clear ARGV so that IRB doesn't try to parse our options
62
+ opts[:args] = args
63
+ ARGV.clear
64
+
65
+ query = args.first unless args.empty?
66
+
67
+ interpreter = AutomateIt.new(:project => opts[:project])
68
+ result = interpreter.lookup(query)
69
+ if result.nil?
70
+ puts result.inspect
71
+ exit 1
72
+ elsif opts[:yaml]
73
+ puts result.to_yaml
74
+ elsif opts[:xml]
75
+ require 'active_support/core_ext/hash'
76
+ require 'active_support/core_ext/array'
77
+ puts result.to_xml
78
+ else
79
+ puts result.is_a?(String) ? result : result.inspect
80
+ end
81
+ exit 0
82
+ end
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # XXX What can go wrong with this loading approach?
4
+ libdir = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
5
+ if File.directory?(libdir) and File.exists?(File.join(libdir, "automateit.rb"))
6
+ $LOAD_PATH.unshift(libdir)
7
+ end
8
+
9
+ require 'rubygems'
10
+ require 'optparse'
11
+ require 'automateit'
12
+
13
+ OptionParser.new do |parser|
14
+ PROG = File.basename($0)
15
+ opts = {}
16
+ parser.banner = <<EOB
17
+ #{PROG} - tool for querying AutomateIt tags
18
+
19
+ Usage: #{PROG} [options] [arguments...]
20
+
21
+ Examples:
22
+ # Load 'myproject' and see if it's tagged with 'apache' or 'svn':
23
+ #{PROG} -p myproject 'apache || svn'
24
+ echo $?
25
+
26
+ # Same but using environmental variable to specify project:
27
+ AUTOMATEIT_PROJECT=myproject
28
+ #{PROG} 'apache || svn'
29
+ echo $?
30
+
31
+ # Dump the results of a query as YAML
32
+ #{PROG} -Y myapp#user
33
+
34
+ # Dump the results of a query as XML
35
+ #{PROG} -X myapp#user
36
+
37
+ Options:
38
+ EOB
39
+ parser.on("-s", "--tags", "List tags for this host") do |v|
40
+ opts[:tags] = v
41
+ end
42
+
43
+ parser.on("-f", "--tags_for HOST", "List tags for a specific host") do |v|
44
+ opts[:tags_for] = v
45
+ end
46
+
47
+ parser.on("-t", "--tagged? QUERY", "Is this host tagged with the query?") do |v|
48
+ opts[:tagged?] = v
49
+ end
50
+
51
+ parser.on("-w", "--hosts_tagged_with QUERY", "List hosts tagged with query") do |v|
52
+ opts[:hosts_tagged_with] = v
53
+ end
54
+
55
+ parser.on("-p", "--project PATH", "Set project path") do |v|
56
+ opts[:project] = v
57
+ end
58
+
59
+ parser.on("-Y", "--yaml", "Dump as YAML") do |v|
60
+ opts[:yaml] = v
61
+ end
62
+
63
+ parser.on("-X", "--xml", "Dump as XML") do |v|
64
+ opts[:xml] = v
65
+ end
66
+
67
+ parser.on("-h", "--help", "Display this help message") do |v|
68
+ puts parser
69
+ exit
70
+ end
71
+
72
+ parser.on("-v", "--version", "Display version") do |v|
73
+ puts AutomateIt::VERSION
74
+ exit 0
75
+ end
76
+
77
+ args = parser.parse!.dup
78
+
79
+ # Clear ARGV so that IRB doesn't try to parse our options
80
+ opts[:args] = args
81
+ ARGV.clear
82
+
83
+ interpreter = AutomateIt.new(:project => opts[:project])
84
+ result = nil
85
+
86
+ unless opts[:tags] or opts[:tags_for] or opts[:tagged?] or opts[:hosts_tagged_with]
87
+ if args.first
88
+ opts[:tagged?] = args.first
89
+ else
90
+ puts parser
91
+ puts "\nERROR: insufficient arguments"
92
+ exit 1
93
+ end
94
+ end
95
+
96
+ result = \
97
+ if opts[:tags]
98
+ interpreter.tags
99
+ elsif opts[:tags_for]
100
+ interpreter.tags_for(opts[:tags_for])
101
+ elsif opts[:tagged?]
102
+ exit(interpreter.tagged?(opts[:tagged?]) ? 0 : 1)
103
+ elsif opts[:hosts_tagged_with]
104
+ interpreter.hosts_tagged_with(opts[:hosts_tagged_with])
105
+ end
106
+
107
+ puts(
108
+ if result.nil?
109
+ result.inspect
110
+ elsif opts[:yaml]
111
+ result.to_yaml
112
+ elsif opts[:xml]
113
+ require 'active_support/core_ext/hash'
114
+ require 'active_support/core_ext/array'
115
+ result.to_xml
116
+ else
117
+ case result
118
+ when String: result
119
+ when Set: result.sort.to_a.join(' ')
120
+ when Array: result.sort.join(' ')
121
+ else result.inspect
122
+ end
123
+ end
124
+ )
125
+
126
+ exit 0
127
+ end
128
+
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # XXX What can go wrong with this loading approach?
4
+ libdir = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
5
+ if File.directory?(libdir) and File.exists?(File.join(libdir, "automateit.rb"))
6
+ $LOAD_PATH.unshift(libdir)
7
+ end
8
+
9
+ require 'rubygems'
10
+ require 'logger'
11
+ require 'optparse'
12
+ require 'automateit'
13
+
14
+ include AutomateIt::Constants
15
+
16
+ OptionParser.new do |parser|
17
+ PROG = File.basename($0)
18
+ opts = {}
19
+ parser.banner = <<EOB
20
+ #{PROG} - tool for automating the setup and maintenance of servers
21
+
22
+ Usage: #{PROG} [options] [recipe]
23
+
24
+ Examples:
25
+ # Start an interactive shell session
26
+ #{PROG}
27
+
28
+ # Execute a recipe
29
+ #{PROG} myrecipe.rb
30
+
31
+ # Preview the commands a recipe will run without running them
32
+ #{PROG} -n myrecipe.rb
33
+
34
+ # Eval a string
35
+ #{PROG} -e "puts tags.to_a.inspect"
36
+
37
+ Options:
38
+ EOB
39
+ parser.on("-c", "--create PATH", "Create project at path") do |v|
40
+ opts[:create] = v
41
+ end
42
+
43
+ parser.on("-p", "--project PATH", "Set project path") do |v|
44
+ opts[:project] = v
45
+ end
46
+
47
+ parser.on("-n", "--preview", "Preview without executing commands") do |v|
48
+ opts[:preview] = v
49
+ end
50
+
51
+ parser.on("-e", "--eval STRING", "Evaluate string") do |v|
52
+ opts[:eval] = v
53
+ end
54
+
55
+ parser.on("-q", "--quiet", "Print only errors") do |v|
56
+ opts[:verbosity] = Logger::ERROR
57
+ end
58
+
59
+ parser.on("-d", "--debug", "Print debugging information") do |v|
60
+ opts[:verbosity] = Logger::DEBUG
61
+ end
62
+
63
+ parser.on("-T", "--trace", "Display raw exception traces") do |v|
64
+ opts[:friendly_exceptions] = ! v
65
+ end
66
+
67
+ parser.on("-h", "--help", "Display this help message") do |v|
68
+ puts parser
69
+ exit
70
+ end
71
+
72
+ parser.on("-v", "--version", "Display version") do |v|
73
+ puts AutomateIt::VERSION
74
+ exit 0
75
+ end
76
+
77
+ args = parser.parse!.dup
78
+
79
+ # Clear ARGV so that IRB doesn't try to parse our options
80
+ opts[:args] = args
81
+ ARGV.clear
82
+
83
+ opts[:recipe] = args.first unless args.empty?
84
+
85
+ # Save vars because +run+ will delete opts
86
+ argscopy = args.clone
87
+ optscopy = opts.clone
88
+
89
+ begin
90
+ rv = AutomateIt::CLI.run(opts)
91
+ rescue Exception => e
92
+ msg = nil
93
+ if opts[:friendly_exceptions] != false and e.is_a?(AutomateIt::Error)
94
+ # Friendly message
95
+ msg = PERROR+e.message
96
+ msg << "\n\n"+PNOTE+"Use 'automateit --trace' to see complete backtrace"
97
+ else
98
+ # Raw backtrace
99
+ puts PERROR+"AutomateIt error trace:"
100
+ stack = e.backtrace.clone
101
+ msg = "#{stack.shift}: #{e.message} (#{e.exception.class})}";
102
+ for line in stack
103
+ msg << "\n "+line
104
+ end
105
+ end
106
+ puts msg
107
+ exit 1
108
+ rescue SysExit => e
109
+ # Don't display errors when exit gets called
110
+ end
111
+ if optscopy[:create] or optscopy[:eval] or argscopy.size > 0
112
+ exit rv ? 0 :1
113
+ else
114
+ # CTRL-D ends the line prematurely, so add a newline
115
+ puts
116
+ end
117
+ end
@@ -0,0 +1,50 @@
1
+ == User-friendly error messages
2
+
3
+ AutomateIt provides user-friendly error messages that make it easier to fix
4
+ problems in recipes and templates. These pinpoint the cause and show code
5
+ snippets.
6
+
7
+ For example, one of the sample recipes is executed -- but there's a problem and
8
+ the output is shown below.
9
+
10
+ The message is telling us the error happened in the
11
+ 'examples/basic/recipes/install.rb' recipe at line 47. The first snippet shows
12
+ the end of a failed TemplateManager +render+ call.
13
+
14
+ In the second code snippet, we see there was a problem with the ERB template
15
+ 'dist/myapp_server.erb'. This template failed at line 5 because it couldn't
16
+ find a variable called +pat+.
17
+
18
+ With the help of the second snippet, we quickly see that there's a typo -- that
19
+ bad variable should have been +path+. Problem solved!
20
+
21
+ root@kagami> automateit -n examples/basic/recipes/install.rb
22
+ !! Problem with recipe 'examples/basic/recipes/install.rb' at line 47
23
+
24
+ 41 :to => "/etc/init.d/myapp_server",
25
+ 42 :mode => 0555,
26
+ 43 :locals => {
27
+ 44 :path => lookup(:path),
28
+ 45 :user => lookup(:user),
29
+ 46 :port => lookup(:port),
30
+ * 47 }
31
+ 48 )
32
+ 49
33
+
34
+ (NestedError) Problem with template 'dist/myapp_server.erb' at line 5:
35
+
36
+ 1 #!/usr/bin/env ruby
37
+ 2
38
+ 3 user = "<%=user%>"
39
+ 4 port = "<%=port%>"
40
+ * 5 path = "<%=pat%>"
41
+ 6 pid = "mongrel.pid"
42
+ 7
43
+
44
+ (NameError) undefined local variable or method `pat' for #<AutomateIt::TemplateManager::ERB:0xb78a4e8c>
45
+ /home/igal/workspace/automateit/app/lib/helpful_erb.rb:60:in `result'
46
+ /home/igal/workspace/automateit/app/lib/automateit/template_manager/erb.rb:105:in `render'
47
+ (eval):2:in `render'
48
+ examples/basic/recipes/install.rb:47:in `invoke'
49
+
50
+ => Use 'automateit --trace' to see complete backtrace
@@ -0,0 +1,86 @@
1
+ == Previews
2
+
3
+ AutomateIt provides a way to preview commands without actually running them.
4
+ Read the TUTORIAL.txt[link:files/TUTORIAL_txt.html] to learn the basic previewing concepts and commands.
5
+
6
+ === WARNING: Previewing code can be dangerous!
7
+
8
+ AutomateIt only provides logic for previewing its own commands. Recipe authors
9
+ are responsible for providing previewing logic for their own custom code.
10
+
11
+ Here's what *not* to do with previews:
12
+
13
+ puts "Hello!"
14
+
15
+ The above +puts+ method will execute in both preview and non-preview modes.
16
+ To execute custom code only in a specific mode, wrap it with conditionals.
17
+
18
+ For example:
19
+
20
+ if preview?
21
+ puts "This is a preview"
22
+ end
23
+
24
+ preview_for("PREVIEW: Will run custom commands") do
25
+ puts "Custom commands"
26
+ end
27
+
28
+ When in preview mode, the above recipe will display:
29
+
30
+ This is a preview
31
+ => PREVIEW: Will run custom commands
32
+
33
+ When run normally without preview mode:
34
+
35
+ Custom commands
36
+
37
+ Therefore, wrap all non-AutomateIt commands (e.g. +system+) that shouldn't be
38
+ executed during the preview with conditionals.
39
+
40
+ === WARNING: Changing directories during preview can be dangerous!
41
+
42
+ AutomateIt will only *pretend* to make directories in preview mode. In
43
+ preview mode, it will also only *pretend* to change into non-existent
44
+ directories when using commands like #cd, #mkdir and #mktempdircd.
45
+
46
+ This can be *disastrous* if you're executing non-AutomateIt commands (e.g.
47
+ +system+) that use *relative* *paths* and expect to be run inside the
48
+ newly-created temporary directory because the +chdir+ didn't actually happen.
49
+
50
+ For example:
51
+
52
+ # DON'T EVER DO THIS!!!
53
+ mkdir_p "/tmp/foo/bar" do
54
+ system "echo 'I'm going to do: rm -rf *'"
55
+ end
56
+
57
+ If that directory didn't already exist, then running the above code in
58
+ preview mode would cause the +system+ command to actually run! If that wasn't
59
+ an +echo+ command, it would have deleted the contents of your *current*
60
+ directory -- not the <tt>/tmp/foo/bar</tt> directory -- because that
61
+ directory wasn't actually created due to the preview mode!
62
+
63
+ The correct way to write the above example is:
64
+
65
+ mkdir_p "/tmp/foo/bar" do
66
+ preview_for("PREVIEW: Deleting all files in directory /tmp/foo/bar") do
67
+ system "echo 'I'm going to do: rm -rf *'"
68
+ end
69
+ end
70
+
71
+ The Interpreter#preview_for method provides conditional execution of blocks.
72
+ When running in preview mode, it will display the supplied message and not
73
+ execute the block containing the +system+ command:
74
+
75
+ => PREVIEW: Deleting all files in directory /tmp/foo/bar
76
+
77
+ When running without preview mode, the method will not display the message
78
+ but will call block, generating the following output:
79
+
80
+ ** echo 'I'm going to do: rm -rf *'"
81
+ I'm going to do: rm -rf *
82
+
83
+ === Conclusion
84
+
85
+ Keeping the preview issues in mind and wrapping custom code with conditionals
86
+ will help you write code that can be safely previewed.