Permalink
Browse files

Refactor resource to name "stow" and give all variables descriptive n…

…ames.

Previously the resource was "stow_package" which was misleading since it
wasn't really a package, yet the older "stowify" name was a verb. The new
"stow" name more clearly indicates what's being done.

Previously many variables had terse names like "o", "s", "downloaded" or
"extracted". Now they have more descriptive names like "struct",
"downloaded_file" or "extracted_directory", which will hopefully be easier
to understand.

Added more documentation.
  • Loading branch information...
1 parent da128d2 commit 9d0e041521f6209c1c31b1a006a87dd5e9b3a884 @igal committed Jun 19, 2012
View
@@ -98,8 +98,8 @@ Recipes
Resources and Providers
-----------------------
-* [stow resource](http://github.com/igal/antipackaging/blob/master/cookbooks/stow_package/resources/default.rb) - A custom Chef resource to download, compile, install and stow applications.
-* [stow provider](http://github.com/igal/antipackaging/blob/master/cookbooks/stow_package/providers/default.rb) - A custom Chef provider to implement the above resource.
+* [stow resource](http://github.com/igal/antipackaging/blob/master/cookbooks/stow/resources/default.rb) - A custom Chef resource to download, compile, install and stow applications.
+* [stow provider](http://github.com/igal/antipackaging/blob/master/cookbooks/stow/providers/default.rb) - A custom Chef provider to implement the above resource.
Running examples
----------------
View
@@ -1,6 +1,6 @@
desc "Regenerate cookbook metadata.json files"
task :metadata do
- %w[antipackaging stow_package].each do |name|
+ %w[antipackaging stow].each do |name|
sh "knife cookbook metadata #{name} -o cookbooks"
end
end
@@ -2,10 +2,10 @@
package "stow"
# Define stow directory
-stow = "/usr/local/stow"
+stow_directory = "/usr/local/stow"
# Create stow directory
-directory stow
+directory stow_directory
#=======================================================================
@@ -29,30 +29,30 @@
# NOT: url = "http://nginx.org/download/#{name_and_version}.tar.gz"
# Derived variables
-cache = Chef::Config[:file_cache_path]
-downloaded = ::File.join(cache, ::File.basename(url))
-extracted = ::File.join(cache, name_and_version)
-installed = ::File.join(stow, name_and_version)
-check_installed = ::File.join(installed, check) # <- "/usr/local/stow/ngnix-1.3.1/sbin/ngnix"
-check_stowed = ::File.join(stow, "..", check) # <- "/usr/local/sbin/nginx"
+cache_directory = Chef::Config[:file_cache_path]
+downloaded_file = ::File.join(cache_directory, ::File.basename(url))
+extracted_directory = ::File.join(cache_directory, name_and_version)
+installed_directory = ::File.join(stow_directory, name_and_version)
+check_installed = ::File.join(installed_directory, check) # <- "/usr/local/stow/ngnix-1.3.1/sbin/ngnix"
+check_stowed = ::File.join(stow_directory, "..", check) # <- "/usr/local/sbin/nginx"
# Ensure nginx
if (::File.stat(check_stowed).ino != ::File.stat(check_installed).ino rescue true)
# Download archive
- remote_file downloaded do
+ remote_file downloaded_file do
source url
end
# Install nginx
bash "install_nginx" do
- cwd cache
+ cwd cache_directory
code <<-HERE
set -e -x
- (cd #{stow} && stow -D #{name}-*) || true
- rm -rf #{installed}
- rm -rf #{extracted}
- dtrx -n #{downloaded}
- (cd #{extracted} && ./configure --prefix=#{installed} && make && make install && cd #{stow} && stow #{name_and_version})
+ (cd #{stow_directory} && stow -D #{name}-*) || true
+ rm -rf #{installed_directory}
+ rm -rf #{extracted_directory}
+ dtrx -n #{downloaded_file}
+ (cd #{extracted_directory} && ./configure --prefix=#{installed_directory} && make && make install && cd #{stow_directory} && stow #{name_and_version})
HERE
end
end
@@ -1,5 +1,5 @@
# Same as `standalone.rb` recipe, but now using a custom resource.
-stow_package "nginx" do
+stow "nginx" do
version "1.3.1"
check "sbin/nginx"
url "https://s3.amazonaws.com/igalfiles/#{@name}-#{@version}.tar.gz"
@@ -10,7 +10,7 @@
end
# Same resource, but for different software with a trickier installation.
-stow_package "ts" do
+stow "ts" do
version "0.7.3"
check "bin/ts"
url "https://s3.amazonaws.com/igalfiles/#{@name}-#{@version}.tar.gz"
@@ -1,9 +1,9 @@
-stow_package "nginx" do
+stow "nginx" do
check "sbin/nginx"
action :uninstall
end
-stow_package "ts" do
+stow "ts" do
check "bin/ts"
action :uninstall
end
@@ -0,0 +1 @@
+default['stow']['directory'] = '/usr/local/stow'
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,106 @@
+# Structure representing paths and other properties of a stow resource, which
+# can be reused by both the :install and :uninstall actions. See the actions
+# definitions below to see how this is used.
+StowStruct = Struct.new(:name, :version, :name_and_version, :separator, :url,
+ :install, :dependencies, :downloaded_file, :extracted_directory,
+ :installed_directory, :stow_directory, :cache_directory, :check,
+ :check_installed, :check_stowed, :placeholder) do
+
+ # Return new structure parsed from a +node+ and +new_resource+.
+ def self.parse(node, new_resource)
+ struct = self.new
+ struct.name = new_resource.name
+ struct.version = new_resource.version
+ struct.url = new_resource.url
+ struct.separator = new_resource.separator
+ struct.placeholder = new_resource.placeholder
+ struct.dependencies = new_resource.dependencies
+ struct.install = new_resource.install
+
+ struct.stow_directory = node.stow.directory
+ struct.cache_directory = Chef::Config[:file_cache_path]
+ struct.name_and_version = [struct.name, struct.separator, struct.version].join if struct.version
+ struct.downloaded_file = ::File.join(struct.cache_directory, ::File.basename(struct.url)) if struct.url
+ struct.extracted_directory = ::File.join(struct.cache_directory, struct.name_and_version) if struct.version
+ struct.installed_directory = ::File.join(struct.stow_directory, struct.name_and_version) if struct.version
+ struct.check = new_resource.check
+ struct.check_installed = ::File.join(struct.installed_directory, struct.check) if struct.installed_directory
+ struct.check_stowed = ::File.join(struct.stow_directory, "..", struct.check)
+ return struct
+ end
+end
+
+action :install do
+ # Ensure all required arguments were specified
+ %w[version check url install].each do |name|
+ unless new_resource.send(name)
+ raise ArgumentError, "stow: '#{name}' must be specified"
+ end
+ end
+
+ struct = StowStruct.parse(node, new_resource)
+
+ # Install tools needed for extracting and stowing
+ package "dtrx"
+ package "stow"
+ directory struct.stow_directory
+
+ # Only build new software if it's not already present
+ if (::File.stat(struct.check_installed).ino != ::File.stat(struct.check_stowed).ino rescue true)
+ # Download source
+ remote_file struct.downloaded_file do
+ source struct.url
+ end
+
+ # Install dependencies
+ if struct.dependencies
+ struct.dependencies.each do |name|
+ package name
+ end
+ end
+
+ # Install software
+ bash "install_#{struct.name_and_version}" do
+ # Figure out what commands to run to install the software
+ installer =
+ case struct.install
+ when String
+ # When given a string, substitute the placeholder ("@@PREFIX@@") with name of install directory.
+ struct.install.gsub(/#{struct.placeholder}/, struct.installed_directory)
+ when Proc
+ # When given a proc, call it with the name of the install directory.
+ struct.install.call(struct.installed_directory)
+ else
+ raise ArgumentError, "stow: 'install' must be a String or Proc, not: #{struct.install.class}"
+ end
+
+ # Go into directory with the downloaded file
+ cwd struct.cache_directory
+
+ code <<-HERE
+ set -e -x
+ (cd #{struct.stow_directory} && stow -D #{struct.name}#{struct.separator}*) || true
+ rm -rf #{struct.installed_directory}
+ rm -rf #{struct.extracted_directory}
+ dtrx -n #{struct.downloaded_file}
+ (cd #{struct.extracted_directory} && #{installer} && cd #{struct.stow_directory} && stow #{struct.name_and_version})
+ HERE
+ end
+ end
+end
+
+action :uninstall do
+ struct = StowStruct.parse(node, new_resource)
+
+ execute "uninstall_#{struct.name}" do
+ only_if { ::File.exist?(struct.check_stowed) }
+
+ cwd struct.stow_directory
+
+ if struct.name_and_version
+ command "stow -D #{struct.name_and_version}"
+ else
+ command "stow -D #{struct.name}#{struct.separator}*"
+ end
+ end
+end
@@ -1 +0,0 @@
-default['stow']['dir'] = '/usr/local/stow'
@@ -1,84 +0,0 @@
-StowPaths = Struct.new(:name, :version, :name_and_version, :separator, :url, :downloaded, :extracted, :installed, :stow, :cache, :check, :check_installed, :check_stowed, :placeholder) do
- def self.parse(node, resource)
- o = self.new
- o.name = resource.name
- o.version = resource.version
- o.url = resource.url
- o.separator = resource.separator
- o.placeholder = resource.placeholder
-
- o.stow = node.stow.dir
- o.cache = Chef::Config[:file_cache_path]
- o.name_and_version = [o.name, o.separator, o.version].join if o.version
- o.downloaded = ::File.join(o.cache, ::File.basename(o.url)) if o.url
- o.extracted = ::File.join(o.cache, o.name_and_version) if o.version
- o.installed = ::File.join(o.stow, o.name_and_version) if o.version
- o.check = resource.check
- o.check_installed = ::File.join(o.installed, o.check) if o.installed
- o.check_stowed = ::File.join(o.stow, "..", o.check)
- return o
- end
-end
-
-action :install do
- %w[version check url install].each do |name|
- unless new_resource.send(name)
- raise ArgumentError, "stow: '#{name}' must be specified"
- end
- end
-
- s = StowPaths.parse(node, new_resource)
-
- package "dtrx"
- package "stow"
- directory node.stow.dir
-
- if (::File.stat(s.check_installed).ino != ::File.stat(s.check_stowed).ino rescue true)
- # Download
- remote_file s.downloaded do
- source s.url
- end
-
- # Dependencies
- if new_resource.dependencies
- new_resource.dependencies.each do |name|
- package name
- end
- end
-
- # Install
- bash "install_#{s.name_and_version}" do
- installer =
- case new_resource.install
- when String
- new_resource.install.gsub(/#{s.placeholder}/, s.installed)
- when Proc
- new_resource.install.call(s.installed)
- else
- raise ArgumentError, "stow: 'install' must be a String or Proc, not: #{new_resource.install.class}"
- end
- cwd s.cache
- code <<-HERE
- set -e -x
- (cd #{s.stow} && stow -D #{s.name}#{s.separator}*) || true
- rm -rf #{s.installed}
- rm -rf #{s.extracted}
- dtrx -n #{s.downloaded}
- (cd #{s.extracted} && #{installer} && cd #{s.stow} && stow #{s.name_and_version})
- HERE
- end
- end
-end
-
-action :uninstall do
- s = StowPaths.parse(node, new_resource)
- execute "uninstall_#{new_resource.name}" do
- only_if { ::File.exist?(s.check_stowed) }
- cwd s.stow
- if s.name_and_version
- command "stow -D #{s.name_and_version}"
- else
- command "stow -D #{s.name}#{s.separator}*"
- end
- end
-end

0 comments on commit 9d0e041

Please sign in to comment.