necktie 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. data/README.rdoc +174 -0
  2. data/bin/necktie +2 -1
  3. data/lib/necktie/files.rb +29 -0
  4. data/lib/necktie/rake.rb +127 -0
  5. data/lib/necktie/services.rb +11 -7
  6. data/lib/necktie.rb +4 -54
  7. data/necktie.gemspec +3 -3
  8. data/vendor/rake/CHANGES +477 -0
  9. data/vendor/rake/MIT-LICENSE +21 -0
  10. data/vendor/rake/README.rdoc +194 -0
  11. data/vendor/rake/Rakefile +421 -0
  12. data/vendor/rake/TODO +20 -0
  13. data/vendor/rake/bin/rake +31 -0
  14. data/vendor/rake/doc/command_line_usage.rdoc +102 -0
  15. data/vendor/rake/doc/example/Rakefile1 +38 -0
  16. data/vendor/rake/doc/example/Rakefile2 +35 -0
  17. data/vendor/rake/doc/example/a.c +6 -0
  18. data/vendor/rake/doc/example/b.c +6 -0
  19. data/vendor/rake/doc/example/main.c +11 -0
  20. data/vendor/rake/doc/glossary.rdoc +51 -0
  21. data/vendor/rake/doc/jamis.rb +591 -0
  22. data/vendor/rake/doc/proto_rake.rdoc +127 -0
  23. data/vendor/rake/doc/rake.1.gz +0 -0
  24. data/vendor/rake/doc/rakefile.rdoc +566 -0
  25. data/vendor/rake/doc/rational.rdoc +151 -0
  26. data/vendor/rake/doc/release_notes/rake-0.4.14.rdoc +23 -0
  27. data/vendor/rake/doc/release_notes/rake-0.4.15.rdoc +35 -0
  28. data/vendor/rake/doc/release_notes/rake-0.5.0.rdoc +53 -0
  29. data/vendor/rake/doc/release_notes/rake-0.5.3.rdoc +78 -0
  30. data/vendor/rake/doc/release_notes/rake-0.5.4.rdoc +46 -0
  31. data/vendor/rake/doc/release_notes/rake-0.6.0.rdoc +141 -0
  32. data/vendor/rake/doc/release_notes/rake-0.7.0.rdoc +119 -0
  33. data/vendor/rake/doc/release_notes/rake-0.7.1.rdoc +59 -0
  34. data/vendor/rake/doc/release_notes/rake-0.7.2.rdoc +121 -0
  35. data/vendor/rake/doc/release_notes/rake-0.7.3.rdoc +47 -0
  36. data/vendor/rake/doc/release_notes/rake-0.8.0.rdoc +114 -0
  37. data/vendor/rake/doc/release_notes/rake-0.8.2.rdoc +165 -0
  38. data/vendor/rake/doc/release_notes/rake-0.8.3.rdoc +112 -0
  39. data/vendor/rake/doc/release_notes/rake-0.8.4.rdoc +147 -0
  40. data/vendor/rake/doc/release_notes/rake-0.8.5.rdoc +53 -0
  41. data/vendor/rake/doc/release_notes/rake-0.8.6.rdoc +55 -0
  42. data/vendor/rake/doc/release_notes/rake-0.8.7.rdoc +55 -0
  43. data/vendor/rake/install.rb +88 -0
  44. data/vendor/rake/lib/rake/alt_system.rb +108 -0
  45. data/vendor/rake/lib/rake/application.rb +579 -0
  46. data/vendor/rake/lib/rake/classic_namespace.rb +9 -0
  47. data/vendor/rake/lib/rake/clean.rb +35 -0
  48. data/vendor/rake/lib/rake/cloneable.rb +25 -0
  49. data/vendor/rake/lib/rake/contrib/compositepublisher.rb +24 -0
  50. data/vendor/rake/lib/rake/contrib/ftptools.rb +153 -0
  51. data/vendor/rake/lib/rake/contrib/publisher.rb +75 -0
  52. data/vendor/rake/lib/rake/contrib/rubyforgepublisher.rb +18 -0
  53. data/vendor/rake/lib/rake/contrib/sshpublisher.rb +47 -0
  54. data/vendor/rake/lib/rake/contrib/sys.rb +209 -0
  55. data/vendor/rake/lib/rake/default_loader.rb +10 -0
  56. data/vendor/rake/lib/rake/dsl.rb +136 -0
  57. data/vendor/rake/lib/rake/early_time.rb +18 -0
  58. data/vendor/rake/lib/rake/environment.rb +40 -0
  59. data/vendor/rake/lib/rake/ext/module.rb +60 -0
  60. data/vendor/rake/lib/rake/ext/string.rb +165 -0
  61. data/vendor/rake/lib/rake/ext/time.rb +14 -0
  62. data/vendor/rake/lib/rake/file_creation_task.rb +24 -0
  63. data/vendor/rake/lib/rake/file_list.rb +395 -0
  64. data/vendor/rake/lib/rake/file_task.rb +47 -0
  65. data/vendor/rake/lib/rake/file_utils.rb +108 -0
  66. data/vendor/rake/lib/rake/gempackagetask.rb +97 -0
  67. data/vendor/rake/lib/rake/invocation_chain.rb +51 -0
  68. data/vendor/rake/lib/rake/invocation_exception_mixin.rb +16 -0
  69. data/vendor/rake/lib/rake/lib/project.rake +24 -0
  70. data/vendor/rake/lib/rake/loaders/makefile.rb +44 -0
  71. data/vendor/rake/lib/rake/multi_task.rb +16 -0
  72. data/vendor/rake/lib/rake/name_space.rb +25 -0
  73. data/vendor/rake/lib/rake/packagetask.rb +184 -0
  74. data/vendor/rake/lib/rake/psuedo_status.rb +24 -0
  75. data/vendor/rake/lib/rake/rake_file_utils.rb +133 -0
  76. data/vendor/rake/lib/rake/rake_module.rb +25 -0
  77. data/vendor/rake/lib/rake/rake_test_loader.rb +15 -0
  78. data/vendor/rake/lib/rake/rdoctask.rb +209 -0
  79. data/vendor/rake/lib/rake/ruby182_test_unit_fix.rb +25 -0
  80. data/vendor/rake/lib/rake/rule_recursion_overflow_error.rb +20 -0
  81. data/vendor/rake/lib/rake/runtest.rb +23 -0
  82. data/vendor/rake/lib/rake/task.rb +318 -0
  83. data/vendor/rake/lib/rake/task_argument_error.rb +7 -0
  84. data/vendor/rake/lib/rake/task_arguments.rb +78 -0
  85. data/vendor/rake/lib/rake/task_manager.rb +328 -0
  86. data/vendor/rake/lib/rake/tasklib.rb +24 -0
  87. data/vendor/rake/lib/rake/testtask.rb +175 -0
  88. data/vendor/rake/lib/rake/win32.rb +55 -0
  89. data/vendor/rake/lib/rake.rb +72 -0
  90. data/vendor/rake/rake.blurb +19 -0
  91. data/vendor/rake/rake.gemspec +214 -0
  92. data/vendor/rake/rakelib/extra.rake +8 -0
  93. data/vendor/rake/rakelib/publish.rake +22 -0
  94. data/vendor/rake/rakelib/rbx.rake +82 -0
  95. data/vendor/rake/rakelib/ruby19.rake +88 -0
  96. data/vendor/rake/rakelib/tags.rake +18 -0
  97. data/vendor/rake/test/capture_stdout.rb +26 -0
  98. data/vendor/rake/test/check_expansion.rb +5 -0
  99. data/vendor/rake/test/check_no_expansion.rb +5 -0
  100. data/vendor/rake/test/contrib/test_sys.rb +47 -0
  101. data/vendor/rake/test/data/chains/Rakefile +15 -0
  102. data/vendor/rake/test/data/comments/Rakefile +18 -0
  103. data/vendor/rake/test/data/default/Rakefile +19 -0
  104. data/vendor/rake/test/data/dryrun/Rakefile +22 -0
  105. data/vendor/rake/test/data/file_creation_task/Rakefile +33 -0
  106. data/vendor/rake/test/data/imports/Rakefile +19 -0
  107. data/vendor/rake/test/data/imports/deps.mf +1 -0
  108. data/vendor/rake/test/data/multidesc/Rakefile +17 -0
  109. data/vendor/rake/test/data/namespace/Rakefile +66 -0
  110. data/vendor/rake/test/data/nosearch/dummy +1 -0
  111. data/vendor/rake/test/data/rakelib/test1.rb +5 -0
  112. data/vendor/rake/test/data/rakelib/test2.rake +3 -0
  113. data/vendor/rake/test/data/rbext/rakefile.rb +3 -0
  114. data/vendor/rake/test/data/sample.mf +14 -0
  115. data/vendor/rake/test/data/statusreturn/Rakefile +8 -0
  116. data/vendor/rake/test/data/sys/sys1.rake +3 -0
  117. data/vendor/rake/test/data/unittest/Rakefile +1 -0
  118. data/vendor/rake/test/data/unittest/subdir/README +0 -0
  119. data/vendor/rake/test/data/verbose/Rakefile +34 -0
  120. data/vendor/rake/test/filecreation.rb +32 -0
  121. data/vendor/rake/test/functional/functional_test.rb +15 -0
  122. data/vendor/rake/test/functional/session_based_tests.rb +442 -0
  123. data/vendor/rake/test/in_environment.rb +32 -0
  124. data/vendor/rake/test/lib/application_test.rb +769 -0
  125. data/vendor/rake/test/lib/clean_test.rb +15 -0
  126. data/vendor/rake/test/lib/definitions_test.rb +85 -0
  127. data/vendor/rake/test/lib/dsl_test.rb +41 -0
  128. data/vendor/rake/test/lib/earlytime_test.rb +35 -0
  129. data/vendor/rake/test/lib/environment_test.rb +18 -0
  130. data/vendor/rake/test/lib/extension_test.rb +63 -0
  131. data/vendor/rake/test/lib/file_creation_task_test.rb +62 -0
  132. data/vendor/rake/test/lib/file_task_test.rb +143 -0
  133. data/vendor/rake/test/lib/filelist_test.rb +623 -0
  134. data/vendor/rake/test/lib/fileutils_test.rb +251 -0
  135. data/vendor/rake/test/lib/ftp_test.rb +59 -0
  136. data/vendor/rake/test/lib/invocation_chain_test.rb +81 -0
  137. data/vendor/rake/test/lib/makefile_loader_test.rb +26 -0
  138. data/vendor/rake/test/lib/multitask_test.rb +53 -0
  139. data/vendor/rake/test/lib/namespace_test.rb +55 -0
  140. data/vendor/rake/test/lib/package_task_test.rb +118 -0
  141. data/vendor/rake/test/lib/pathmap_test.rb +210 -0
  142. data/vendor/rake/test/lib/pseudo_status_test.rb +26 -0
  143. data/vendor/rake/test/lib/rake_test.rb +41 -0
  144. data/vendor/rake/test/lib/rdoc_task_test.rb +88 -0
  145. data/vendor/rake/test/lib/require_test.rb +35 -0
  146. data/vendor/rake/test/lib/rules_test.rb +349 -0
  147. data/vendor/rake/test/lib/task_arguments_test.rb +89 -0
  148. data/vendor/rake/test/lib/task_manager_test.rb +173 -0
  149. data/vendor/rake/test/lib/task_test.rb +376 -0
  150. data/vendor/rake/test/lib/tasklib_test.rb +12 -0
  151. data/vendor/rake/test/lib/test_task_test.rb +77 -0
  152. data/vendor/rake/test/lib/testtask_test.rb +49 -0
  153. data/vendor/rake/test/lib/top_level_functions_test.rb +86 -0
  154. data/vendor/rake/test/lib/win32_test.rb +72 -0
  155. data/vendor/rake/test/rake_test_setup.rb +24 -0
  156. data/vendor/rake/test/reqfile.rb +3 -0
  157. data/vendor/rake/test/reqfile2.rb +3 -0
  158. data/vendor/rake/test/reqfile3.rake +3 -0
  159. data/vendor/rake/test/shellcommand.rb +3 -0
  160. data/vendor/rake/test/test_helper.rb +13 -0
  161. metadata +212 -56
  162. /data/{rush → vendor/rush}/README.rdoc +0 -0
  163. /data/{rush → vendor/rush}/Rakefile +0 -0
  164. /data/{rush → vendor/rush}/VERSION +0 -0
  165. /data/{rush → vendor/rush}/bin/rush +0 -0
  166. /data/{rush → vendor/rush}/bin/rushd +0 -0
  167. /data/{rush → vendor/rush}/lib/rush/access.rb +0 -0
  168. /data/{rush → vendor/rush}/lib/rush/array_ext.rb +0 -0
  169. /data/{rush → vendor/rush}/lib/rush/box.rb +0 -0
  170. /data/{rush → vendor/rush}/lib/rush/commands.rb +0 -0
  171. /data/{rush → vendor/rush}/lib/rush/config.rb +0 -0
  172. /data/{rush → vendor/rush}/lib/rush/dir.rb +0 -0
  173. /data/{rush → vendor/rush}/lib/rush/embeddable_shell.rb +0 -0
  174. /data/{rush → vendor/rush}/lib/rush/entry.rb +0 -0
  175. /data/{rush → vendor/rush}/lib/rush/exceptions.rb +0 -0
  176. /data/{rush → vendor/rush}/lib/rush/file.rb +0 -0
  177. /data/{rush → vendor/rush}/lib/rush/find_by.rb +0 -0
  178. /data/{rush → vendor/rush}/lib/rush/fixnum_ext.rb +0 -0
  179. /data/{rush → vendor/rush}/lib/rush/head_tail.rb +0 -0
  180. /data/{rush → vendor/rush}/lib/rush/local.rb +0 -0
  181. /data/{rush → vendor/rush}/lib/rush/process.rb +0 -0
  182. /data/{rush → vendor/rush}/lib/rush/process_set.rb +0 -0
  183. /data/{rush → vendor/rush}/lib/rush/remote.rb +0 -0
  184. /data/{rush → vendor/rush}/lib/rush/search_results.rb +0 -0
  185. /data/{rush → vendor/rush}/lib/rush/server.rb +0 -0
  186. /data/{rush → vendor/rush}/lib/rush/shell.rb +0 -0
  187. /data/{rush → vendor/rush}/lib/rush/ssh_tunnel.rb +0 -0
  188. /data/{rush → vendor/rush}/lib/rush/string_ext.rb +0 -0
  189. /data/{rush → vendor/rush}/lib/rush.rb +0 -0
  190. /data/{rush → vendor/rush}/rush.gemspec +0 -0
  191. /data/{rush → vendor/rush}/spec/access_spec.rb +0 -0
  192. /data/{rush → vendor/rush}/spec/array_ext_spec.rb +0 -0
  193. /data/{rush → vendor/rush}/spec/base.rb +0 -0
  194. /data/{rush → vendor/rush}/spec/box_spec.rb +0 -0
  195. /data/{rush → vendor/rush}/spec/commands_spec.rb +0 -0
  196. /data/{rush → vendor/rush}/spec/config_spec.rb +0 -0
  197. /data/{rush → vendor/rush}/spec/dir_spec.rb +0 -0
  198. /data/{rush → vendor/rush}/spec/embeddable_shell_spec.rb +0 -0
  199. /data/{rush → vendor/rush}/spec/entry_spec.rb +0 -0
  200. /data/{rush → vendor/rush}/spec/file_spec.rb +0 -0
  201. /data/{rush → vendor/rush}/spec/find_by_spec.rb +0 -0
  202. /data/{rush → vendor/rush}/spec/fixnum_ext_spec.rb +0 -0
  203. /data/{rush → vendor/rush}/spec/local_spec.rb +0 -0
  204. /data/{rush → vendor/rush}/spec/process_set_spec.rb +0 -0
  205. /data/{rush → vendor/rush}/spec/process_spec.rb +0 -0
  206. /data/{rush → vendor/rush}/spec/remote_spec.rb +0 -0
  207. /data/{rush → vendor/rush}/spec/rush_spec.rb +0 -0
  208. /data/{rush → vendor/rush}/spec/search_results_spec.rb +0 -0
  209. /data/{rush → vendor/rush}/spec/shell_spec.rb +0 -0
  210. /data/{rush → vendor/rush}/spec/ssh_tunnel_spec.rb +0 -0
  211. /data/{rush → vendor/rush}/spec/string_ext_spec.rb +0 -0
  212. /data/{session → vendor/session}/lib/session-2.4.0.rb +0 -0
  213. /data/{session → vendor/session}/lib/session.rb +0 -0
  214. /data/{session → vendor/session}/test/session.rb +0 -0
data/README.rdoc ADDED
@@ -0,0 +1,174 @@
1
+ I use Necktie to setup and upgrade multiple servers.
2
+
3
+
4
+ == Dress to impress
5
+
6
+ Necktie runs a set of scripts (or configuration tasks) that can create and edit
7
+ files, install and setup services, mount volumes, and basically anything you
8
+ can script with Ruby and a shell.
9
+
10
+ To use Necktie:
11
+ - Write your Necktie tasks using Ruby
12
+ - Include support files (config, binaries, etc)
13
+ - git push
14
+ - cap necktie
15
+
16
+ I use it to:
17
+
18
+ - gem install, apt-get
19
+ - Configure Nginx, install and setup Unicorn
20
+ - Change memcached configuration from default
21
+ - Setup MySQL to use a mounted (EBS) volume
22
+ - Install and update cron scripts
23
+
24
+
25
+ == Tasking
26
+
27
+ Necktie is based on Rake, so if you know Rake you already know most of Necktie.
28
+ At the base of your Necktie project there's a file called necktie (or Necktie,
29
+ or necktie.rb), with a list of task. For example:
30
+
31
+ file "/var/myapp" do
32
+ append "/etc/fstab", "\n/mnt/myapp /var/myapp none bind" unless read("/etc/fstab")["/mnt/myapp"]
33
+ mkdir_p "/var/myapp/"
34
+ sh "mount /var/myapp"
35
+ end
36
+
37
+ task :rubygems do
38
+ FileList["gems/*.gem"].each do |gem|
39
+ install_gem gem
40
+ end
41
+ end
42
+
43
+ task :nginx do
44
+ rm_rf "/etc/nginx/sites-enabled/*"
45
+ cp "etc/nginx/unicorn.conf", "/etc/nginx/sites-available/"
46
+ ln_sf "/etc/nginx/sites-available/unicorn.conf", "/etc/nginx/sites-enabled/"
47
+ services.start "nginx"
48
+ end
49
+
50
+ task :unicorn=>[:rubygems] do
51
+ cp "etc/init.d/unicorn", "/etc/init.d/"
52
+ chmod 0750, "/etc/init.d/unicorn"
53
+ end
54
+
55
+ task :app=>["/var/myapp", :nginx, :unicorn]
56
+
57
+ You then run the app task, which runs all the dependencies necessary to setup
58
+ your application directory, system gems, Nginx and Unicorn configuration. Ready
59
+ for deployment.
60
+
61
+ If you changed one of the configuration files, you can run Necktie again: it
62
+ will pull updates from the Git repository and run these tasks with the new
63
+ configuration files.
64
+
65
+ Note: The nginx and unicorn files will run every time you run the app task, so
66
+ you can use them to push out new configuration. In contrast, the /var/myapp
67
+ directory is mounted by a file task that will only run once (if the directory
68
+ doesn't exist).
69
+
70
+
71
+ == cap necktie
72
+
73
+ I use Capistrano to setup new instances and upgrade existing ones. I then run
74
+ deploy:cold on the new instances, or deploy to upgrade running instances.
75
+
76
+ The Capistrano tasks looks something like this (see also:
77
+ extra/capistrano/necktie.rb):
78
+
79
+ # Copy Gem over so not depending on gem server being online, and all servers get
80
+ # to use the same version of Necktie.
81
+ gem_spec = Gem::SourceIndex.from_installed_gems.find_name("necktie").last
82
+ gem_file = File.join(Gem.dir, "cache", spec.file_name)
83
+ upload gem_file, File.basename(gem_file), :via=>:scp
84
+ sudo "gem install #{File.basename(gem_file)}"
85
+ # Run Necktie as sudo.
86
+ sudo "necktie #{necktie_url} #{ENV["ROLES"].to_s.gsub(',', ' ')}"
87
+
88
+ To setup a new server:
89
+
90
+ cap necktie HOSTS=ec2-75-101-239-12.compute-1.amazonaws.com
91
+
92
+ To upgrade instances:
93
+
94
+ git push && cap necktie
95
+
96
+
97
+ == Feel the rush
98
+
99
+ Necktie includes Rush, so you can write tasks like this:
100
+
101
+ unless processes.find { |p| p.cmdline[/memcached\s.*-l\s0.0.0.0/] }
102
+ box["/etc/memcached.conf"].replace_contents! /^-l 127.0.0.1/, "-l 0.0.0.0"
103
+ Services.start "memcached"
104
+ end
105
+
106
+ You can learn more about Rush here: http://rush.heroku.com
107
+
108
+ Of course, there's also FileUtils, system and sh, so you can just:
109
+
110
+ cp "etc/init.d/unicorn", "/etc/init.d"
111
+ chmod 0755, "/etc/init.d/unicorn"
112
+ sh "service start unicorn"
113
+
114
+ Note: The current directory (launch_dir and Dir.pwd) is the root directory
115
+ of your Necktie repository. You can use relative paths to access files from your
116
+ Necktie repository.
117
+
118
+
119
+ == Role play
120
+
121
+ If you have different setups, split them into roles and give each role its own
122
+ head task. You can then run Necktie for one or several roles, in the order they
123
+ are listed on the command line.
124
+
125
+ For example:
126
+
127
+ task :app=>["rubygems", "nginx", "unicorn", "/var/myapp"]
128
+ task :db=>["mount", "master", "backup"]
129
+
130
+
131
+ I recommend using the same roles for Necktie and Capistrano, then you can:
132
+
133
+ cap necktie ROLES=app,db
134
+
135
+ Note: Command line arguments are either task names (run in order), or
136
+ name=value pairs that set environment variables (e.g. RAILS_ENV=production).
137
+
138
+
139
+ == gem install
140
+
141
+ You can use install_gem in one of two ways. You can pass it a gem name and
142
+ (optional, but highly recommended) version requirement. For example:
143
+
144
+ install_gem "unicorn", "~= 0.93"
145
+
146
+ You can store the gem file in your Necktie repository and install it from there:
147
+
148
+ install_gem "gems/unicorn-0.93.3.gem"
149
+
150
+ I prefer the later, so I'm not affected when gem sources go offline just as I
151
+ decide to run my Necktie tasks.
152
+
153
+ Since install_gem will only install the same gem/version once, a run-always
154
+ rubygems.rb task is all you need:
155
+
156
+ launch_dir["gems/*.gem"].each do |gem|
157
+ install_gem gem.to_s
158
+ end
159
+
160
+
161
+ == License
162
+
163
+ Necktie, copyright (C) 2009 Assaf Arkin, released under the "Use for good, not
164
+ evil" license (http://www.json.org/license.html)
165
+
166
+ Includes Rake, created by Jim Weirich and released under the MIT license
167
+ http://rake.rubyforge.org/ http://github.com/jimweirich/rake
168
+
169
+ Includes Rush, created by Adam Wiggins and released under the MIT License
170
+ http://rush.heroku.com http://github.com/adamwiggins/rush
171
+
172
+ Includes Session, created by Ara T. Howard and released under the Ruby License
173
+ http://raa.ruby-lang.org/project/session
174
+ http://www.codeforpeople.com/lib/ruby/session
data/bin/necktie CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  $LOAD_PATH.unshift File.expand_path("../lib", File.dirname(__FILE__)),
3
- File.expand_path("../rush/lib", File.dirname(__FILE__)), File.expand_path("../session/lib", File.dirname(__FILE__))
3
+ File.expand_path("../vendor/rake/lib", File.dirname(__FILE__)), File.expand_path("../vendor/rush/lib", File.dirname(__FILE__)),
4
+ File.expand_path("../vendor/session/lib", File.dirname(__FILE__))
4
5
  require "necktie"
5
6
  necktie ARGV
@@ -0,0 +1,29 @@
1
+ def read(name)
2
+ File.read(name)
3
+ end
4
+
5
+ def write(name, contents = nil)
6
+ contents ||= yield
7
+ File.open name, "w" do |f|
8
+ f.write contents
9
+ end
10
+ end
11
+
12
+ def append(name, contents = nil)
13
+ contents ||= yield
14
+ File.open name, "a" do |f|
15
+ f.write contents
16
+ end
17
+ end
18
+
19
+ def update(name, from = nil, to = nil)
20
+ contents = File.read(name)
21
+ if from && to
22
+ contents = contents.sub(from, to)
23
+ else
24
+ contents = yield(contents)
25
+ end
26
+ File.open name, "w" do |f|
27
+ f.write contents
28
+ end
29
+ end
@@ -0,0 +1,127 @@
1
+ require "rake"
2
+
3
+ module Necktie
4
+ class Application < Rake::Application
5
+
6
+ def initialize
7
+ super
8
+ @name = "necktie"
9
+ @rakefiles = ["Necktie", "necktie", "Necktie.rb", "necktie.rb"]
10
+ options.nosearch = true
11
+ end
12
+
13
+ def run
14
+ standard_exception_handling do
15
+ handle_options
16
+ Dir.chdir clone_repo do
17
+ collect_tasks
18
+ load_rakefile
19
+ top_level
20
+ end
21
+ end
22
+ end
23
+
24
+ def clone_repo
25
+ @git_url = ARGV.shift or fail "expecting first argument to be a Git repository URL"
26
+ repo = File.expand_path(".necktie")
27
+ if File.exist?(repo)
28
+ puts "Pulling latest updates to #{repo}"
29
+ system "cd #{repo.inspect} && git pull origin #{ENV["BRANCH"] || "master"}" or fail
30
+ else
31
+ puts "Cloning #{@git_url} to #{repo}"
32
+ system "git clone #{@git_url} #{repo.inspect}" or fail
33
+ end
34
+ repo
35
+ end
36
+
37
+ def necktie_options
38
+ [
39
+ ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
40
+ lambda { |value|
41
+ options.show_tasks = :describe
42
+ options.show_task_pattern = Regexp.new(value || '')
43
+ TaskManager.record_task_metadata = true
44
+ }
45
+ ],
46
+ ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.",
47
+ lambda { |value|
48
+ puts eval(value)
49
+ exit
50
+ }
51
+ ],
52
+ ['--execute-continue', '-E CODE',
53
+ "Execute some Ruby code, then continue with normal task processing.",
54
+ lambda { |value| eval(value) }
55
+ ],
56
+ ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
57
+ lambda { |value| options.show_prereqs = true }
58
+ ],
59
+ ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
60
+ lambda { |value|
61
+ options.show_tasks = :tasks
62
+ options.show_task_pattern = Regexp.new(value || '')
63
+ Rake::TaskManager.record_task_metadata = true
64
+ }
65
+ ],
66
+ ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
67
+ lambda { |value|
68
+ options.trace = true
69
+ verbose(true)
70
+ }
71
+ ],
72
+ ['--verbose', '-v', "Log message to standard output.",
73
+ lambda { |value| verbose(true) }
74
+ ],
75
+ ['--version', '-V', "Display the program version.",
76
+ lambda { |value|
77
+ spec = Gem::Specification.load(File.expand_path("../necktie.gemspec", File.dirname(__FILE__)))
78
+ puts "Necktie, version #{spec.version}"
79
+ exit
80
+ }
81
+ ],
82
+ ['--where', '-W [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
83
+ lambda { |value|
84
+ options.show_tasks = :lines
85
+ options.show_task_pattern = Regexp.new(value || '')
86
+ Rake::TaskManager.record_task_metadata = true
87
+ }
88
+ ],
89
+ ]
90
+ end
91
+
92
+ # Read and handle the command line options.
93
+ def handle_options
94
+ options.rakelib = ['necktie']
95
+ options.top_level_dsl = true
96
+
97
+ OptionParser.new do |opts|
98
+ opts.banner = "necktie git_url {options} tasks..."
99
+ opts.separator ""
100
+ opts.separator "Options are ..."
101
+
102
+ opts.on_tail("-h", "--help", "-H", "Display this help message.") do
103
+ puts opts
104
+ exit
105
+ end
106
+
107
+ necktie_options.each { |args| opts.on(*args) }
108
+ opts.environment('RAKEOPT')
109
+ end.parse!
110
+
111
+ Rake::DSL.include_in_top_scope
112
+ end
113
+
114
+ def raw_load_rakefile # :nodoc:
115
+ @rakefile = have_rakefile
116
+ fail "No Necktie file found (looking for: #{@rakefiles.join(', ')})" if @rakefile.nil?
117
+ Rake::Environment.load_rakefile(File.expand_path(@rakefile)) if @rakefile && @rakefile != ''
118
+ options.rakelib.each do |rlib|
119
+ glob("necktie/*.rb") do |name|
120
+ add_import name
121
+ end
122
+ end
123
+ load_imports
124
+ end
125
+
126
+ end
127
+ end
@@ -1,33 +1,37 @@
1
- module Services
2
- def self.start(name)
1
+ class Services
2
+ def start(name)
3
3
  puts " ** Starting service #{name}"
4
4
  system "update-rc.d #{name} defaults" and
5
5
  system "service #{name} start" or
6
6
  fail "failed to start #{name}"
7
7
  end
8
8
 
9
- def self.enable(name)
9
+ def enable(name)
10
10
  system "update-rc.d #{name} defaults" or "cannot enable #{name}"
11
11
  end
12
12
 
13
- def self.stop(name)
13
+ def stop(name)
14
14
  puts " ** Stopping service #{name}"
15
15
  system "service #{name} stop" and
16
16
  system "update-rc.d -f #{name} remove" or
17
17
  fail "failed to stop #{name}"
18
18
  end
19
19
 
20
- def self.disable(name)
20
+ def disable(name)
21
21
  system "update-rc.d -f #{name} remove" or fail "cannot disable #{name}"
22
22
  end
23
23
 
24
- def self.restart(name)
24
+ def restart(name)
25
25
  puts " ** Stopping service #{name}"
26
26
  system "service #{name} restart" or fail "failed to restart #{name}"
27
27
  end
28
28
 
29
- def self.status(name)
29
+ def running?(name)
30
30
  status = File.read("|service --status-all 2>&1")[/^ \[ (.) \] #{Regexp.escape name}$/,1]
31
31
  status == "+" ? true : status == "-" ? false : nil
32
32
  end
33
33
  end
34
+
35
+ def services
36
+ @services ||= Services.new
37
+ end
data/lib/necktie.rb CHANGED
@@ -1,59 +1,9 @@
1
- require "fileutils"
2
- extend FileUtils
1
+ require "necktie/rake"
2
+ require "necktie/files"
3
3
  require "necktie/gems"
4
4
  require "necktie/services"
5
5
  require "necktie/rush"
6
6
 
7
7
 
8
- def necktie(args)
9
- etc = "/etc/necktie"
10
- File.writable?(etc) or File.writable?(File.dirname(etc)) or fail "Can't write to #{etc}. You should be running necktie as sudo."
11
-
12
- envs, args = args.partition { |a| a[/=/] }
13
- git_url = args.shift or fail "Usage: necktie git-url role* name=value*"
14
- roles = args
15
- # Setup environment variable from name=value arguments.
16
- envs.each do |env|
17
- name, value = env.split("=")
18
- ENV[name] = value
19
- end
20
-
21
- # Default role is app. For all rules, execute setup scripts.
22
- if roles.empty?
23
- puts " Default role: app"
24
- roles = ["app"]
25
- end
26
-
27
- repo = File.expand_path(".necktie")
28
- if File.exist?(repo)
29
- puts " * Pulling latest updates to #{repo}"
30
- system "cd #{repo.inspect} && git pull origin #{ENV["branch"] || "master"}" or fail
31
- else
32
- puts " * Cloning #{git_url} to #{repo}"
33
- system "git clone #{git_url} #{repo.inspect}" or fail
34
- end
35
-
36
- Dir.chdir repo do
37
- executed = File.exist?(etc) ? File.read(etc).split("\n") : []
38
- roles.each do |role|
39
- skip = executed.map { |t| t[/^#{Regexp.escape role}\/(.*)$/, 1] }.reject(&:nil?)
40
- tasks = Dir["tasks/#{role}/*.rb"].sort.map { |name| File.basename(name).gsub(/\.rb$/, "") }
41
- todo = tasks - skip
42
- if tasks.empty?
43
- puts " * No tasks for role #{role}"
44
- elsif todo.empty?
45
- puts " * All tasks completed for role #{role}"
46
- else
47
- puts " * Now in role: #{role}"
48
- File.open etc, "a" do |f|
49
- todo.each do |task|
50
- puts " ** Executing #{task}"
51
- load "tasks/#{role}/#{task}.rb"
52
- f.puts task if task[/^\d+_/]
53
- end
54
- end
55
- end
56
- end
57
- end
58
-
59
- end
8
+ Rake.application = Necktie::Application.new
9
+ Rake.application.run
data/necktie.gemspec CHANGED
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "necktie"
3
- spec.version = "0.2.1"
3
+ spec.version = "0.3.0"
4
4
  spec.author = "Assaf Arkin"
5
5
  spec.email = "assaf@labnotes.org"
6
6
  spec.homepage = ""
7
7
  spec.summary = "Dress to impress"
8
- spec.description = ""
8
+ spec.description = "Configure your servers remotely using Ruby and Git"
9
9
 
10
- spec.files = Dir["{bin,lib,rush,session}/**/*", "*.{gemspec,rdoc}"]
10
+ spec.files = Dir["{bin,lib,vendor}/**/*", "*.{gemspec,rdoc}"]
11
11
  spec.executable = "necktie"
12
12
  end