Class: Chef::Provider::Deploy
- Inherits:
-
Chef::Provider
- Object
- Chef::Provider
- Chef::Provider::Deploy
- Includes:
- DSL::Recipe, Mixin::Command, Mixin::FromFile
- Defined in:
- lib/chef/provider/deploy.rb,
lib/chef/provider/deploy/revision.rb,
lib/chef/provider/deploy/timestamped.rb
Direct Known Subclasses
Defined Under Namespace
Classes: Revision, Timestamped
Constant Summary
Constants included from Mixin::ShellOut
Mixin::ShellOut::DEPRECATED_OPTIONS
Instance Attribute Summary collapse
-
#previous_release_path ⇒ Object
readonly
Returns the value of attribute previous_release_path.
-
#release_path ⇒ Object
readonly
Returns the value of attribute release_path.
-
#scm_provider ⇒ Object
readonly
Returns the value of attribute scm_provider.
-
#shared_path ⇒ Object
readonly
Returns the value of attribute shared_path.
Attributes inherited from Chef::Provider
#action, #cookbook_name, #current_resource, #new_resource, #recipe_name, #run_context
Instance Method Summary collapse
- #action_deploy ⇒ Object
- #action_force_deploy ⇒ Object
- #action_rollback ⇒ Object
- #all_releases ⇒ Object
- #callback(what, callback_code = nil) ⇒ Object
- #cleanup! ⇒ Object
- #copy_cached_repo ⇒ Object
- #create_dirs_before_symlink ⇒ Object
- #define_resource_requirements ⇒ Object
- #deploy ⇒ Object
- #enforce_ownership ⇒ Object
-
#initialize(new_resource, run_context) ⇒ Deploy
constructor
A new instance of Deploy.
- #link_current_release_to_production ⇒ Object
- #link_tempfiles_to_current_release ⇒ Object
- #load_current_resource ⇒ Object
- #migrate ⇒ Object
- #purge_tempfiles_from_current_release ⇒ Object
- #restart ⇒ Object
- #rollback ⇒ Object
- #rollback_to(target_release_path) ⇒ Object
- #run(command, &block) ⇒ Object
- #run_scm_sync ⇒ Object
- #run_symlinks_before_migrate ⇒ Object
- #sudo(command, &block) ⇒ Object
- #svn_force_export ⇒ Object
- #symlink ⇒ Object
- #update_cached_repo ⇒ Object
- #verify_directories_exist ⇒ Object
- #whyrun_supported? ⇒ Boolean
Methods included from Mixin::Command
#chdir_or_tmpdir, #handle_command_failures, #output_of_command, #run_command, #run_command_and_return_stdout_stderr, #run_command_with_systems_locale
Methods included from Mixin::Command::Windows
Methods included from Mixin::Command::Unix
Methods included from Mixin::FromFile
Methods included from DSL::Recipe
#exec, #have_resource_class_for?, #resource_class_for
Methods included from Mixin::LazyModuleInclude
#descendants, #include, #included
Methods included from DSL::MethodMissing
#describe_self_for_error, #method_missing
Methods included from DSL::Definitions
add_definition, #evaluate_resource_definition, #has_resource_definition?
Methods included from DSL::Resources
add_resource_dsl, remove_resource_dsl
Methods included from DSL::ChefProvisioning
Methods included from DSL::Cheffish
Methods included from DSL::Powershell
Methods included from DSL::Audit
Methods included from DSL::RebootPending
Methods included from DSL::PlatformIntrospection
#docker?, #platform?, #platform_family?, #value_for_platform, #value_for_platform_family
Methods included from DSL::RegistryHelper
#registry_data_exists?, #registry_get_subkeys, #registry_get_values, #registry_has_subkeys?, #registry_key_exists?, #registry_value_exists?
Methods included from DSL::IncludeRecipe
#include_recipe, #load_recipe, #require_recipe
Methods included from DSL::DataQuery
#data_bag, #data_bag_item, #search
Methods included from EncryptedDataBagItem::CheckEncrypted
Methods included from Mixin::NotifyingBlock
#notifying_block, #subcontext_block
Methods included from DSL::DeclareResource
#build_resource, #declare_resource, #delete_resource, #delete_resource!, #edit_resource, #edit_resource!, #find_resource, #find_resource!, #with_run_context
Methods included from Mixin::ShellOut
#run_command_compatible_options, #shell_out, #shell_out!, #shell_out_with_systems_locale, #shell_out_with_systems_locale!
Methods included from Mixin::PowershellOut
#powershell_out, #powershell_out!
Methods included from Mixin::WindowsArchitectureHelper
#assert_valid_windows_architecture!, #disable_wow64_file_redirection, #forced_32bit_override_required?, #is_i386_process_on_x86_64_windows?, #node_supports_windows_architecture?, #node_windows_architecture, #restore_wow64_file_redirection, #valid_windows_architecture?, #with_os_architecture, #wow64_architecture_override_required?, #wow64_directory
Methods inherited from Chef::Provider
#action_nothing, #check_resource_semantics!, #cleanup_after_converge, #converge_by, #converge_if_changed, #events, include_resource_dsl, include_resource_dsl_module, #node, #process_resource_requirements, provides, provides?, #requirements, #resource_collection, #resource_updated?, #run_action, #set_updated_status, supports?, use_inline_resources, #whyrun_mode?
Methods included from Mixin::Provides
#provided_as, #provides, #provides?
Methods included from Mixin::DescendantsTracker
#descendants, descendants, direct_descendants, #direct_descendants, find_descendants_by_name, #find_descendants_by_name, #inherited, store_inherited
Methods included from DeprecatedLWRPClass
#const_missing, #deprecated_constants, #register_deprecated_lwrp_class
Constructor Details
#initialize(new_resource, run_context) ⇒ Deploy
Returns a new instance of Deploy.
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/chef/provider/deploy.rb', line 36 def initialize(new_resource, run_context) super(new_resource, run_context) # will resolve to either git or svn based on resource attributes, # and will create a resource corresponding to that provider @scm_provider = new_resource.scm_provider.new(new_resource, run_context) # @configuration is not used by Deploy, it is only for backwards compat with # chef-deploy or capistrano hooks that might use it to get environment information @configuration = @new_resource.to_hash @configuration[:environment] = @configuration[:environment] && @configuration[:environment]["RAILS_ENV"] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Chef::DSL::MethodMissing
Instance Attribute Details
#previous_release_path ⇒ Object (readonly)
Returns the value of attribute previous_release_path.
34 35 36 |
# File 'lib/chef/provider/deploy.rb', line 34 def previous_release_path @previous_release_path end |
#release_path ⇒ Object (readonly)
Returns the value of attribute release_path.
34 35 36 |
# File 'lib/chef/provider/deploy.rb', line 34 def release_path @release_path end |
#scm_provider ⇒ Object (readonly)
Returns the value of attribute scm_provider.
34 35 36 |
# File 'lib/chef/provider/deploy.rb', line 34 def scm_provider @scm_provider end |
#shared_path ⇒ Object (readonly)
Returns the value of attribute shared_path.
34 35 36 |
# File 'lib/chef/provider/deploy.rb', line 34 def shared_path @shared_path end |
Instance Method Details
#action_deploy ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/chef/provider/deploy.rb', line 98 def action_deploy save_release_state if deployed?(release_path ) if current_release?(release_path ) Chef::Log.debug("#{@new_resource} is the latest version") else rollback_to release_path end else with_rollback_on_error do deploy end end end |
#action_force_deploy ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/chef/provider/deploy.rb', line 114 def action_force_deploy if deployed?(release_path) converge_by("delete deployed app at #{release_path} prior to force-deploy") do Chef::Log.info("Already deployed app at #{release_path}, forcing.") FileUtils.rm_rf(release_path) Chef::Log.info("#{@new_resource} forcing deploy of already deployed app at #{release_path}") end end # Alternatives: # * Move release_path directory before deploy and move it back when error occurs # * Rollback to previous commit # * Do nothing - because deploy is force, it will be retried in short time # Because last is simplest, keep it deploy end |
#action_rollback ⇒ Object
131 132 133 |
# File 'lib/chef/provider/deploy.rb', line 131 def action_rollback rollback_to all_releases[-2] end |
#all_releases ⇒ Object
244 245 246 |
# File 'lib/chef/provider/deploy.rb', line 244 def all_releases Dir.glob(Chef::Util::PathHelper.escape_glob_dir(@new_resource.deploy_to) + "/releases/*").sort end |
#callback(what, callback_code = nil) ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/chef/provider/deploy.rb', line 177 def callback(what, callback_code = nil) @collection = Chef::ResourceCollection.new case callback_code when Proc Chef::Log.info "#{@new_resource} running callback #{what}" recipe_eval(&callback_code) when String run_callback_from_file("#{release_path}/#{callback_code}") when nil run_callback_from_file("#{release_path}/deploy/#{what}.rb") end end |
#cleanup! ⇒ Object
229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/chef/provider/deploy.rb', line 229 def cleanup! converge_by("update release history data") do release_created(release_path) end chop = -1 - @new_resource.keep_releases all_releases[0..chop].each do |old_release| converge_by("remove old release #{old_release}") do Chef::Log.info "#{@new_resource} removing old release #{old_release}" FileUtils.rm_rf(old_release) end release_deleted(old_release) end end |
#copy_cached_repo ⇒ Object
266 267 268 269 270 271 272 273 274 |
# File 'lib/chef/provider/deploy.rb', line 266 def copy_cached_repo target_dir_path = @new_resource.deploy_to + "/releases" converge_by("deploy from repo to #{target_dir_path} ") do FileUtils.rm_rf(release_path) if ::File.exist?(release_path) FileUtils.mkdir_p(target_dir_path) FileUtils.cp_r(::File.join(@new_resource.destination, "."), release_path, :preserve => true) Chef::Log.info "#{@new_resource} copied the cached checkout to #{release_path}" end end |
#create_dirs_before_symlink ⇒ Object
339 340 |
# File 'lib/chef/provider/deploy.rb', line 339 def create_dirs_before_symlink end |
#define_resource_requirements ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/chef/provider/deploy.rb', line 74 def define_resource_requirements requirements.assert(:rollback) do |a| a.assertion { all_releases[-2] } a.(RuntimeError, "There is no release to rollback to!") #There is no reason to assume 2 deployments in a single chef run, hence fails in whyrun. end [ @new_resource.before_migrate, @new_resource.before_symlink, @new_resource.before_restart, @new_resource.after_restart ].each do |script| requirements.assert(:deploy, :force_deploy) do |a| callback_file = "#{release_path}/#{script}" a.assertion do if script && script.class == String ::File.exist?(callback_file) else true end end a.(RuntimeError, "Can't find your callback file #{callback_file}") a.whyrun("Would assume callback file #{callback_file} included in release") end end end |
#deploy ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/chef/provider/deploy.rb', line 152 def deploy verify_directories_exist update_cached_repo # no converge-by - scm provider will dothis enforce_ownership copy_cached_repo install_gems enforce_ownership callback(:before_migrate, @new_resource.before_migrate) migrate callback(:before_symlink, @new_resource.before_symlink) symlink callback(:before_restart, @new_resource.before_restart) restart callback(:after_restart, @new_resource.after_restart) cleanup! Chef::Log.info "#{@new_resource} deployed to #{@new_resource.deploy_to}" end |
#enforce_ownership ⇒ Object
276 277 278 279 280 281 282 |
# File 'lib/chef/provider/deploy.rb', line 276 def enforce_ownership converge_by("force ownership of #{@new_resource.deploy_to} to #{@new_resource.group}:#{@new_resource.user}") do FileUtils.chown_R(@new_resource.user, @new_resource.group, @new_resource.deploy_to, :force => true) Chef::Log.info("#{@new_resource} set user to #{@new_resource.user}") if @new_resource.user Chef::Log.info("#{@new_resource} set group to #{@new_resource.group}") if @new_resource.group end end |
#link_current_release_to_production ⇒ Object
289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/chef/provider/deploy.rb', line 289 def link_current_release_to_production converge_by(["remove existing link at #{@new_resource.current_path}", "link release #{release_path} into production at #{@new_resource.current_path}"]) do FileUtils.rm_f(@new_resource.current_path) begin FileUtils.ln_sf(release_path, @new_resource.current_path) rescue => e raise Chef::Exceptions::FileNotFound.new("Cannot symlink current release to production: #{e.}") end Chef::Log.info "#{@new_resource} linked release #{release_path} into production at #{@new_resource.current_path}" end enforce_ownership end |
#link_tempfiles_to_current_release ⇒ Object
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/chef/provider/deploy.rb', line 317 def link_tempfiles_to_current_release dirs_info = @new_resource.create_dirs_before_symlink.join(",") @new_resource.create_dirs_before_symlink.each do |dir| create_dir_unless_exists(release_path + "/#{dir}") end Chef::Log.info("#{@new_resource} created directories before symlinking: #{dirs_info}") links_info = @new_resource.symlinks.map { |src, dst| "#{src} => #{dst}" }.join(", ") converge_by("link shared paths into current release: #{links_info}") do @new_resource.symlinks.each do |src, dest| begin FileUtils.ln_sf(::File.join(@new_resource.shared_path, src), ::File.join(release_path, dest)) rescue => e raise Chef::Exceptions::FileNotFound.new("Cannot symlink shared data #{::File.join(@new_resource.shared_path, src)} to #{::File.join(release_path, dest)}: #{e.}") end end Chef::Log.info("#{@new_resource} linked shared paths into current release: #{links_info}") end run_symlinks_before_migrate enforce_ownership end |
#load_current_resource ⇒ Object
53 54 55 56 57 |
# File 'lib/chef/provider/deploy.rb', line 53 def load_current_resource @scm_provider.load_current_resource @release_path = @new_resource.deploy_to + "/releases/#{release_slug}" @shared_path = @new_resource.shared_path end |
#migrate ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/chef/provider/deploy.rb', line 190 def migrate run_symlinks_before_migrate if @new_resource.migrate enforce_ownership environment = @new_resource.environment env_info = environment && environment.map do |key_and_val| "#{key_and_val.first}='#{key_and_val.last}'" end.join(" ") converge_by("execute migration command #{@new_resource.migration_command}") do Chef::Log.info "#{@new_resource} migrating #{@new_resource.user} with environment #{env_info}" shell_out!(@new_resource.migration_command, (:cwd => release_path, :log_level => :info)) end end end |
#purge_tempfiles_from_current_release ⇒ Object
342 343 344 345 346 347 348 |
# File 'lib/chef/provider/deploy.rb', line 342 def purge_tempfiles_from_current_release log_info = @new_resource.purge_before_symlink.join(", ") converge_by("purge directories in checkout #{log_info}") do @new_resource.purge_before_symlink.each { |dir| FileUtils.rm_rf(release_path + "/#{dir}") } Chef::Log.info("#{@new_resource} purged directories in checkout #{log_info}") end end |
#restart ⇒ Object
215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/chef/provider/deploy.rb', line 215 def restart if restart_cmd = @new_resource.restart_command if restart_cmd.kind_of?(Proc) Chef::Log.info("#{@new_resource} restarting app with embedded recipe") recipe_eval(&restart_cmd) else converge_by("restart app using command #{@new_resource.restart_command}") do Chef::Log.info("#{@new_resource} restarting app") shell_out!(@new_resource.restart_command, (:cwd => @new_resource.current_path)) end end end end |
#rollback ⇒ Object
170 171 172 173 174 175 |
# File 'lib/chef/provider/deploy.rb', line 170 def rollback Chef::Log.info "#{@new_resource} rolling back to previous release #{release_path}" symlink Chef::Log.info "#{@new_resource} restarting with previous release" restart end |
#rollback_to(target_release_path) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/chef/provider/deploy.rb', line 135 def rollback_to(target_release_path) @release_path = target_release_path rp_index = all_releases.index(release_path) releases_to_nuke = all_releases[(rp_index + 1)..-1] rollback releases_to_nuke.each do |i| converge_by("roll back by removing release #{i}") do Chef::Log.info "#{@new_resource} removing release: #{i}" FileUtils.rm_rf i end release_deleted(i) end end |
#run(command, &block) ⇒ Object
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/chef/provider/deploy.rb', line 63 def run(command, &block) exec = execute(command, &block) exec.user(@new_resource.user) if @new_resource.user exec.group(@new_resource.group) if @new_resource.group exec.cwd(release_path) unless exec.cwd exec.environment(@new_resource.environment) unless exec.environment converge_by("execute #{command}") do exec end end |
#run_scm_sync ⇒ Object
257 258 259 |
# File 'lib/chef/provider/deploy.rb', line 257 def run_scm_sync @scm_provider.run_action(:sync) end |
#run_symlinks_before_migrate ⇒ Object
303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/chef/provider/deploy.rb', line 303 def run_symlinks_before_migrate links_info = @new_resource.symlink_before_migrate.map { |src, dst| "#{src} => #{dst}" }.join(", ") converge_by("make pre-migration symlinks: #{links_info}") do @new_resource.symlink_before_migrate.each do |src, dest| begin FileUtils.ln_sf(@new_resource.shared_path + "/#{src}", release_path + "/#{dest}") rescue => e raise Chef::Exceptions::FileNotFound.new("Cannot symlink #{@new_resource.shared_path}/#{src} to #{release_path}/#{dest} before migrate: #{e.}") end end Chef::Log.info "#{@new_resource} made pre-migration symlinks" end end |
#sudo(command, &block) ⇒ Object
59 60 61 |
# File 'lib/chef/provider/deploy.rb', line 59 def sudo(command, &block) execute(command, &block) end |
#svn_force_export ⇒ Object
261 262 263 264 |
# File 'lib/chef/provider/deploy.rb', line 261 def svn_force_export Chef::Log.info "#{@new_resource} exporting source repository" @scm_provider.run_action(:force_export) end |
#symlink ⇒ Object
208 209 210 211 212 213 |
# File 'lib/chef/provider/deploy.rb', line 208 def symlink purge_tempfiles_from_current_release link_tempfiles_to_current_release link_current_release_to_production Chef::Log.info "#{@new_resource} updated symlinks" end |
#update_cached_repo ⇒ Object
248 249 250 251 252 253 254 255 |
# File 'lib/chef/provider/deploy.rb', line 248 def update_cached_repo if @new_resource.svn_force_export # TODO assertion, non-recoverable - @scm_provider must be svn if force_export? svn_force_export else run_scm_sync end end |
#verify_directories_exist ⇒ Object
284 285 286 287 |
# File 'lib/chef/provider/deploy.rb', line 284 def verify_directories_exist create_dir_unless_exists(@new_resource.deploy_to) create_dir_unless_exists(@new_resource.shared_path) end |
#whyrun_supported? ⇒ Boolean
49 50 51 |
# File 'lib/chef/provider/deploy.rb', line 49 def whyrun_supported? true end |