necktie 0.2.1 → 0.3.0

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