summaryrefslogtreecommitdiff
path: root/lib/chef/resource/deploy.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/resource/deploy.rb')
-rw-r--r--lib/chef/resource/deploy.rb403
1 files changed, 403 insertions, 0 deletions
diff --git a/lib/chef/resource/deploy.rb b/lib/chef/resource/deploy.rb
new file mode 100644
index 0000000000..8b614028bf
--- /dev/null
+++ b/lib/chef/resource/deploy.rb
@@ -0,0 +1,403 @@
+#
+# Author:: Daniel DeLeo (<dan@kallistec.com>)
+# Author:: Tyler Cloke (<tyler@opscode.com>)
+# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# EX:
+# deploy "/my/deploy/dir" do
+# repo "git@github.com/whoami/project"
+# revision "abc123" # or "HEAD" or "TAG_for_1.0" or (subversion) "1234"
+# user "deploy_ninja"
+# enable_submodules true
+# migrate true
+# migration_command "rake db:migrate"
+# environment "RAILS_ENV" => "production", "OTHER_ENV" => "foo"
+# shallow_clone true
+# action :deploy # or :rollback
+# restart_command "touch tmp/restart.txt"
+# git_ssh_wrapper "wrap-ssh4git.sh"
+# scm_provider Chef::Provider::Git # is the default, for svn: Chef::Provider::Subversion
+# svn_username "whoami"
+# svn_password "supersecret"
+# end
+
+require "chef/resource/scm"
+
+class Chef
+ class Resource
+
+ # Deploy: Deploy apps from a source control repository.
+ #
+ # Callbacks:
+ # Callbacks can be a block or a string. If given a block, the code
+ # is evaluated as an embedded recipe, and run at the specified
+ # point in the deploy process. If given a string, the string is taken as
+ # a path to a callback file/recipe. Paths are evaluated relative to the
+ # release directory. Callback files can contain chef code (resources, etc.)
+ #
+ class Deploy < Chef::Resource
+
+ provider_base Chef::Provider::Deploy
+
+ identity_attr :repository
+
+ state_attrs :deploy_to, :revision
+
+ def initialize(name, run_context=nil)
+ super
+ @resource_name = :deploy
+ @deploy_to = name
+ @environment = nil
+ @repository_cache = 'cached-copy'
+ @copy_exclude = []
+ @purge_before_symlink = %w{log tmp/pids public/system}
+ @create_dirs_before_symlink = %w{tmp public config}
+ @symlink_before_migrate = {"config/database.yml" => "config/database.yml"}
+ @symlinks = {"system" => "public/system", "pids" => "tmp/pids", "log" => "log"}
+ @revision = 'HEAD'
+ @action = :deploy
+ @migrate = false
+ @rollback_on_error = false
+ @remote = "origin"
+ @enable_submodules = false
+ @shallow_clone = false
+ @scm_provider = Chef::Provider::Git
+ @svn_force_export = false
+ @provider = Chef::Provider::Deploy::Timestamped
+ @allowed_actions.push(:force_deploy, :deploy, :rollback)
+ @additional_remotes = Hash[]
+ @keep_releases = 5
+ end
+
+ # where the checked out/cloned code goes
+ def destination
+ @destination ||= shared_path + "/#{@repository_cache}"
+ end
+
+ # where shared stuff goes, i.e., logs, tmp, etc. goes here
+ def shared_path
+ @shared_path ||= @deploy_to + "/shared"
+ end
+
+ # where the deployed version of your code goes
+ def current_path
+ @current_path ||= @deploy_to + "/current"
+ end
+
+ def depth
+ @shallow_clone ? "5" : nil
+ end
+
+ # note: deploy_to is your application "meta-root."
+ def deploy_to(arg=nil)
+ set_or_return(
+ :deploy_to,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def repo(arg=nil)
+ set_or_return(
+ :repo,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+ alias :repository :repo
+
+ def remote(arg=nil)
+ set_or_return(
+ :remote,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def role(arg=nil)
+ set_or_return(
+ :role,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def restart_command(arg=nil, &block)
+ arg ||= block
+ set_or_return(
+ :restart_command,
+ arg,
+ :kind_of => [ String, Proc ]
+ )
+ end
+ alias :restart :restart_command
+
+ def migrate(arg=nil)
+ set_or_return(
+ :migrate,
+ arg,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
+ def migration_command(arg=nil)
+ set_or_return(
+ :migration_command,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def rollback_on_error(arg=nil)
+ set_or_return(
+ :rollback_on_error,
+ arg,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
+ def user(arg=nil)
+ set_or_return(
+ :user,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def group(arg=nil)
+ set_or_return(
+ :group,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def enable_submodules(arg=nil)
+ set_or_return(
+ :enable_submodules,
+ arg,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
+ def shallow_clone(arg=nil)
+ set_or_return(
+ :shallow_clone,
+ arg,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
+ def repository_cache(arg=nil)
+ set_or_return(
+ :repository_cache,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def copy_exclude(arg=nil)
+ set_or_return(
+ :copy_exclude,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def revision(arg=nil)
+ set_or_return(
+ :revision,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+ alias :branch :revision
+
+ def git_ssh_wrapper(arg=nil)
+ set_or_return(
+ :git_ssh_wrapper,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+ alias :ssh_wrapper :git_ssh_wrapper
+
+ def svn_username(arg=nil)
+ set_or_return(
+ :svn_username,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def svn_password(arg=nil)
+ set_or_return(
+ :svn_password,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def svn_arguments(arg=nil)
+ set_or_return(
+ :svn_arguments,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ def svn_info_args(arg=nil)
+ set_or_return(
+ :svn_arguments,
+ arg,
+ :kind_of => [ String ])
+ end
+
+ def scm_provider(arg=nil)
+ klass = if arg.kind_of?(String) || arg.kind_of?(Symbol)
+ lookup_provider_constant(arg)
+ else
+ arg
+ end
+ set_or_return(
+ :scm_provider,
+ klass,
+ :kind_of => [ Class ]
+ )
+ end
+
+ def svn_force_export(arg=nil)
+ set_or_return(
+ :svn_force_export,
+ arg,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
+ def environment(arg=nil)
+ if arg.is_a?(String)
+ Chef::Log.debug "Setting RAILS_ENV, RACK_ENV, and MERB_ENV to `#{arg}'"
+ Chef::Log.warn "[DEPRECATED] please modify your deploy recipe or attributes to set the environment using a hash"
+ arg = {"RAILS_ENV"=>arg,"MERB_ENV"=>arg,"RACK_ENV"=>arg}
+ end
+ set_or_return(
+ :environment,
+ arg,
+ :kind_of => [ Hash ]
+ )
+ end
+
+ # The number of old release directories to keep around after cleanup
+ def keep_releases(arg=nil)
+ [set_or_return(
+ :keep_releases,
+ arg,
+ :kind_of => [ Integer ]), 1].max
+ end
+
+ # An array of paths, relative to your app's root, to be purged from a
+ # SCM clone/checkout before symlinking. Use this to get rid of files and
+ # directories you want to be shared between releases.
+ # Default: ["log", "tmp/pids", "public/system"]
+ def purge_before_symlink(arg=nil)
+ set_or_return(
+ :purge_before_symlink,
+ arg,
+ :kind_of => Array
+ )
+ end
+
+ # An array of paths, relative to your app's root, where you expect dirs to
+ # exist before symlinking. This runs after #purge_before_symlink, so you
+ # can use this to recreate dirs that you had previously purged.
+ # For example, if you plan to use a shared directory for pids, and you
+ # want it to be located in $APP_ROOT/tmp/pids, you could purge tmp,
+ # then specify tmp here so that the tmp directory will exist when you
+ # symlink the pids directory in to the current release.
+ # Default: ["tmp", "public", "config"]
+ def create_dirs_before_symlink(arg=nil)
+ set_or_return(
+ :create_dirs_before_symlink,
+ arg,
+ :kind_of => Array
+ )
+ end
+
+ # A Hash of shared/dir/path => release/dir/path. This attribute determines
+ # which files and dirs in the shared directory get symlinked to the current
+ # release directory, and where they go. If you have a directory
+ # $shared/pids that you would like to symlink as $current_release/tmp/pids
+ # you specify it as "pids" => "tmp/pids"
+ # Default {"system" => "public/system", "pids" => "tmp/pids", "log" => "log"}
+ def symlinks(arg=nil)
+ set_or_return(
+ :symlinks,
+ arg,
+ :kind_of => Hash
+ )
+ end
+
+ # A Hash of shared/dir/path => release/dir/path. This attribute determines
+ # which files in the shared directory get symlinked to the current release
+ # directory and where they go. Unlike map_shared_files, these are symlinked
+ # *before* any migration is run.
+ # For a rails/merb app, this is used to link in a known good database.yml
+ # (with the production db password) before running migrate.
+ # Default {"config/database.yml" => "config/database.yml"}
+ def symlink_before_migrate(arg=nil)
+ set_or_return(
+ :symlink_before_migrate,
+ arg,
+ :kind_of => Hash
+ )
+ end
+
+ # Callback fires before migration is run.
+ def before_migrate(arg=nil, &block)
+ arg ||= block
+ set_or_return(:before_migrate, arg, :kind_of => [Proc, String])
+ end
+
+ # Callback fires before symlinking
+ def before_symlink(arg=nil, &block)
+ arg ||= block
+ set_or_return(:before_symlink, arg, :kind_of => [Proc, String])
+ end
+
+ # Callback fires before restart
+ def before_restart(arg=nil, &block)
+ arg ||= block
+ set_or_return(:before_restart, arg, :kind_of => [Proc, String])
+ end
+
+ # Callback fires after restart
+ def after_restart(arg=nil, &block)
+ arg ||= block
+ set_or_return(:after_restart, arg, :kind_of => [Proc, String])
+ end
+
+ def additional_remotes(arg=nil)
+ set_or_return(
+ :additional_remotes,
+ arg,
+ :kind_of => Hash
+ )
+ end
+
+ end
+ end
+end