Class: WhiskeyDisk

Inherits:
Object
  • Object
show all
Defined in:
lib/whiskey_disk.rb,
lib/whiskey_disk/config.rb,
lib/whiskey_disk/config/filter.rb,
lib/whiskey_disk/config/abstract_filter.rb,
lib/whiskey_disk/config/filters/modules/scope_helper.rb,
lib/whiskey_disk/config/filters/project_scope_filter.rb,
lib/whiskey_disk/config/filters/default_domain_filter.rb,
lib/whiskey_disk/config/filters/add_project_name_filter.rb,
lib/whiskey_disk/config/filters/localize_domains_filter.rb,
lib/whiskey_disk/config/filters/environment_scope_filter.rb,
lib/whiskey_disk/config/filters/stringify_hash_keys_filter.rb,
lib/whiskey_disk/config/filters/add_environment_name_filter.rb,
lib/whiskey_disk/config/filters/default_config_target_filter.rb,
lib/whiskey_disk/config/filters/normalize_ssh_options_filter.rb,
lib/whiskey_disk/config/filters/hashify_domain_entries_filter.rb,
lib/whiskey_disk/config/filters/drop_empty_domain_roles_filter.rb,
lib/whiskey_disk/config/filters/check_for_duplicate_domains_filter.rb,
lib/whiskey_disk/config/filters/convert_role_strings_to_list_filter.rb,
lib/whiskey_disk/config/filters/select_project_and_environment_filter.rb

Defined Under Namespace

Classes: Config

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ WhiskeyDisk

Returns a new instance of WhiskeyDisk.


7
8
9
# File 'lib/whiskey_disk.rb', line 7

def initialize(options = {})
  @staleness_checks = true if options[:staleness_checks]
end

Instance Attribute Details

#configObject


15
16
17
# File 'lib/whiskey_disk.rb', line 15

def config
  @config ||= WhiskeyDisk::Config.new
end

#configurationObject


19
20
21
# File 'lib/whiskey_disk.rb', line 19

def configuration
  @configuration ||= config.fetch
end

#resultsObject (readonly)

Returns the value of attribute results


5
6
7
# File 'lib/whiskey_disk.rb', line 5

def results
  @results
end

Instance Method Details

#apply_staleness_check(commands) ⇒ Object


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/whiskey_disk.rb', line 90

def apply_staleness_check(commands)
  needs(:deploy_to, :repository)
  
  check = "cd #{setting(:deploy_to)}; " +
          "ml=\`git log -1 --pretty=format:%H\`; " +
          "mr=\`git ls-remote #{setting(:repository)} refs/heads/#{branch}\`; "
  
  if setting(:deploy_config_to)
    check += "cd #{setting(:deploy_config_to)}; " +
             "cl=\`git log -1 --pretty=format:%H\`; " +
             "cr=\`git ls-remote #{setting(:config_repository)} refs/heads/#{config_branch}\`; "
  end
  
  check += "if [[ $ml != ${mr%%\t*} ]] " +
           (setting(:deploy_config_to) ? "|| [[ $cl != ${cr%%\t*} ]]" : '') +
           "; then #{commands}; else echo \"No changes to deploy.\"; fi"
end

#branchObject


60
61
62
# File 'lib/whiskey_disk.rb', line 60

def branch
  (setting(:branch) and setting(:branch) != '') ? setting(:branch) : 'master'
end

#bufferObject


11
12
13
# File 'lib/whiskey_disk.rb', line 11

def buffer
  @buffer ||= []
end

#build_command(domain, cmd) ⇒ Object


131
132
133
# File 'lib/whiskey_disk.rb', line 131

def build_command(domain, cmd)
  "#{'set -x; ' if debugging?}" + encode_roles(domain['roles']) + cmd
end

#build_path(path) ⇒ Object


232
233
234
235
# File 'lib/whiskey_disk.rb', line 232

def build_path(path)
  return path if path =~ %r{^/}
  File.join(setting(:deploy_to), path)
end

#bundleObject


112
113
114
115
# File 'lib/whiskey_disk.rb', line 112

def bundle
  return '' if buffer.empty?
  (staleness_checks_enabled? and check_staleness?) ? apply_staleness_check(join_commands) : join_commands
end

#capture_git_changesObject


285
286
287
288
# File 'lib/whiskey_disk.rb', line 285

def capture_git_changes
  needs(:deploy_to)
  enqueue "git diff --name-only ${ml}..HEAD > #{setting(:deploy_to)}/.whiskey_disk_git_changes"
end

#check_staleness?Boolean

Returns:

  • (Boolean)

31
32
33
# File 'lib/whiskey_disk.rb', line 31

def check_staleness?
  config.check_staleness?
end

#checkout_configuration_repositoryObject


257
258
259
260
# File 'lib/whiskey_disk.rb', line 257

def checkout_configuration_repository
  needs(:deploy_config_to, :config_repository)
  clone_repository(setting(:config_repository), setting(:deploy_config_to), config_branch)
end

#checkout_main_repositoryObject


252
253
254
255
# File 'lib/whiskey_disk.rb', line 252

def checkout_main_repository
  needs(:deploy_to, :repository)
  clone_repository(setting(:repository), setting(:deploy_to), branch)
end

#clone_repository(repo, path, my_branch) ⇒ Object


212
213
214
215
216
# File 'lib/whiskey_disk.rb', line 212

def clone_repository(repo, path, my_branch)
  enqueue "cd #{parent_path(path)}"
  enqueue("if [ -e #{path} ]; then echo 'Repository already cloned to [#{path}].  Skipping.'; " +
          "else git clone #{repo} #{tail_path(path)} && #{safe_branch_checkout(path, my_branch)}; fi")
end

#config_branchObject


64
65
66
# File 'lib/whiskey_disk.rb', line 64

def config_branch
  (setting(:config_branch) and setting(:config_branch) != '') ? setting(:config_branch) : 'master'
end

#debugging?Boolean

Returns:

  • (Boolean)

23
24
25
# File 'lib/whiskey_disk.rb', line 23

def debugging?
  config.debug?
end

#domain_limit_match?(domain, limit) ⇒ Boolean

Returns:

  • (Boolean)

117
118
119
# File 'lib/whiskey_disk.rb', line 117

def domain_limit_match?(domain, limit)
  domain.sub(%r{^.*@}, '') == limit
end

#domain_of_interest?(domain) ⇒ Boolean

Returns:

  • (Boolean)

121
122
123
124
# File 'lib/whiskey_disk.rb', line 121

def domain_of_interest?(domain)
  return true unless limit = config.domain_limit
  domain_limit_match?(domain, limit)
end

#encode_roles(roles) ⇒ Object


126
127
128
129
# File 'lib/whiskey_disk.rb', line 126

def encode_roles(roles)
  return '' unless roles and !roles.empty?
  "export WD_ROLES='#{roles.join(':')}'; "
end

#enqueue(command) ⇒ Object


39
40
41
# File 'lib/whiskey_disk.rb', line 39

def enqueue(command)
  buffer << command
end

#ensure_config_parent_path_is_presentObject


247
248
249
250
# File 'lib/whiskey_disk.rb', line 247

def ensure_config_parent_path_is_present
  needs(:deploy_config_to)
  enqueue "mkdir -p #{parent_path(setting(:deploy_config_to))}"
end

#ensure_main_parent_path_is_presentObject


242
243
244
245
# File 'lib/whiskey_disk.rb', line 242

def ensure_main_parent_path_is_present
  needs(:deploy_to)
  enqueue "mkdir -p #{parent_path(setting(:deploy_to))}"
end

#env_varsObject


68
69
70
71
72
73
74
# File 'lib/whiskey_disk.rb', line 68

def env_vars
  return '' unless setting(:rake_env)
  setting(:rake_env).keys.inject('') do |buffer,k| 
    buffer += "#{k}='#{setting(:rake_env)[k]}' "
    buffer
  end
end

#flushObject


155
156
157
158
159
160
161
162
163
# File 'lib/whiskey_disk.rb', line 155

def flush
  needs(:domain)
  setting(:domain).each do |domain|
    next unless domain_of_interest?(domain['name'])
    puts "Deploying #{domain['name']}..."
    status = remote?(domain['name']) ? run(domain, bundle) : shell(domain, bundle)
    record_result(domain['name'], status)
  end
end

#has_config_repo?Boolean

Returns:

  • (Boolean)

52
53
54
# File 'lib/whiskey_disk.rb', line 52

def has_config_repo?
  ! (setting(:config_repository).nil? or setting(:config_repository) == '')
end

#if_file_present(path, cmd) ⇒ Object


200
201
202
# File 'lib/whiskey_disk.rb', line 200

def if_file_present(path, cmd)
  "if [ -e #{path} ]; then #{cmd}; fi"
end

#if_task_defined(task, cmd) ⇒ Object


204
205
206
# File 'lib/whiskey_disk.rb', line 204

def if_task_defined(task, cmd)
  %Q(rakep=`#{env_vars} rake -P` && if [[ `echo "${rakep}" | grep #{task}` != "" ]]; then #{cmd}; fi )
end

#initialize_all_changesObject


279
280
281
282
283
# File 'lib/whiskey_disk.rb', line 279

def initialize_all_changes
  needs(:deploy_to)
  initialize_git_changes
  initialize_rsync_changes
end

#initialize_git_changesObject


268
269
270
271
272
# File 'lib/whiskey_disk.rb', line 268

def initialize_git_changes
  needs(:deploy_to)
  enqueue "rm -f #{setting(:deploy_to)}/.whiskey_disk_git_changes"
  snapshot_git_revision
end

#initialize_rsync_changesObject


274
275
276
277
# File 'lib/whiskey_disk.rb', line 274

def initialize_rsync_changes
  needs(:deploy_to)
  enqueue "rm -f #{setting(:deploy_to)}/.whiskey_disk_rsync_changes"
end

#join_commandsObject


108
109
110
# File 'lib/whiskey_disk.rb', line 108

def join_commands
  buffer.collect {|c| "{ #{c} ; }"}.join(' && ')
end

#needs(*keys) ⇒ Object


84
85
86
87
88
# File 'lib/whiskey_disk.rb', line 84

def needs(*keys)
  keys.each do |key|
    raise "No value for '#{key}' declared in configuration files [#{config.configuration_file}]" unless setting(key)
  end
end

#parent_path(path) ⇒ Object


76
77
78
# File 'lib/whiskey_disk.rb', line 76

def parent_path(path)
  File.split(path).first
end

#project_name_specified?Boolean

Returns:

  • (Boolean)

56
57
58
# File 'lib/whiskey_disk.rb', line 56

def project_name_specified?
  setting(:project) != 'unnamed_project'
end

#record_result(domain, status) ⇒ Object


165
166
167
168
# File 'lib/whiskey_disk.rb', line 165

def record_result(domain, status)
  @results ||= []
  @results << { 'domain' => domain, 'status' => status }
end

#refresh_checkout(path, repo_branch) ⇒ Object


218
219
220
221
222
223
# File 'lib/whiskey_disk.rb', line 218

def refresh_checkout(path, repo_branch)
  enqueue "cd #{path}"
  enqueue "git fetch origin +refs/heads/#{repo_branch}:refs/remotes/origin/#{repo_branch} #{'&>/dev/null' unless debugging?}"
  enqueue "git checkout #{repo_branch} #{'&>/dev/null' unless debugging?}"
  enqueue "git reset --hard origin/#{repo_branch} #{'&>/dev/null' unless debugging?}"
end

#refresh_configurationObject


303
304
305
306
307
308
309
310
# File 'lib/whiskey_disk.rb', line 303

def refresh_configuration
  needs(:deploy_to, :deploy_config_to)
  raise "Must specify project name when using a configuration repository." unless project_name_specified?
  enqueue "echo Rsyncing configuration..."
  enqueue("rsync -a#{'v --progress' if debugging?} " + '--log-format="%t [%p] %i %n" ' +
          "#{setting(:deploy_config_to)}/#{setting(:project)}/#{setting(:config_target)}/ #{setting(:deploy_to)}/ " + 
          "> #{setting(:deploy_to)}/.whiskey_disk_rsync_changes")
end

#remote?(domain) ⇒ Boolean

Returns:

  • (Boolean)

43
44
45
46
47
48
49
50
# File 'lib/whiskey_disk.rb', line 43

def remote?(domain)
  return false unless domain
  return false if domain == 'local'
  limit = config.domain_limit 
  return false if limit and domain_limit_match?(domain, limit)

  true
end

#run(domain, cmd) ⇒ Object


135
136
137
# File 'lib/whiskey_disk.rb', line 135

def run(domain, cmd)
  ssh(domain, cmd)
end

#run_post_deploy_hooksObject


318
319
320
321
322
# File 'lib/whiskey_disk.rb', line 318

def run_post_deploy_hooks
  needs(:deploy_to)
  run_script(setting(:post_deploy_script))
  run_rake_task(setting(:deploy_to), "deploy:post_deploy")
end

#run_post_setup_hooksObject


312
313
314
315
316
# File 'lib/whiskey_disk.rb', line 312

def run_post_setup_hooks
  needs(:deploy_to)
  run_script(setting(:post_setup_script))
  run_rake_task(setting(:deploy_to), "deploy:post_setup")
end

#run_rake_task(path, task_name) ⇒ Object


225
226
227
228
229
230
# File 'lib/whiskey_disk.rb', line 225

def run_rake_task(path, task_name)
  enqueue "echo Running rake #{task_name}..."
  enqueue "cd #{path}"
  enqueue(if_file_present("#{setting(:deploy_to)}/Rakefile", 
    if_task_defined(task_name, "#{env_vars} rake #{'--trace' if debugging?} #{task_name} to=#{setting(:environment)}")))
end

#run_script(script) ⇒ Object


237
238
239
240
# File 'lib/whiskey_disk.rb', line 237

def run_script(script)
  return unless script
  enqueue(%Q<cd #{setting(:deploy_to)}; echo "Running post script..."; #{env_vars} bash #{'-x' if debugging?} #{build_path(script)}>)
end

#safe_branch_checkout(path, my_branch) ⇒ Object


208
209
210
# File 'lib/whiskey_disk.rb', line 208

def safe_branch_checkout(path, my_branch)
  %Q(cd #{path} && git checkout -b #{my_branch} origin/#{my_branch} || git checkout #{my_branch} origin/#{my_branch} || git checkout #{my_branch})
end

#setting(key) ⇒ Object


27
28
29
# File 'lib/whiskey_disk.rb', line 27

def setting(key)
  configuration[key.to_s]
end

#shell(domain, cmd) ⇒ Object


150
151
152
153
# File 'lib/whiskey_disk.rb', line 150

def shell(domain, cmd)
  puts "Running command locally: [#{cmd}]" if debugging?
  system('bash', '-c', build_command(domain, cmd))
end

#snapshot_git_revisionObject


262
263
264
265
266
# File 'lib/whiskey_disk.rb', line 262

def snapshot_git_revision
  needs(:deploy_to)
  enqueue "cd #{setting(:deploy_to)}"
  enqueue %Q{ml=\`git log -1 --pretty=format:%H\`}
end

#ssh(domain, cmd) ⇒ Object


139
140
141
142
143
144
145
146
147
148
# File 'lib/whiskey_disk.rb', line 139

def ssh(domain, cmd)
  args = []
  args << domain['name']
  args << '-v' if debugging?
  args += domain['ssh_options'] if domain['ssh_options']
  args << build_command(domain, cmd)

  puts "Running: ssh #{args.join(' ')}" if debugging?
  system('ssh', *args)
end

#staleness_checks_enabled?Boolean

Returns:

  • (Boolean)

35
36
37
# File 'lib/whiskey_disk.rb', line 35

def staleness_checks_enabled?
  !!@staleness_checks
end

#success?Boolean

Returns:

  • (Boolean)

195
196
197
198
# File 'lib/whiskey_disk.rb', line 195

def success?
  return true if !results or results.empty?
  results.all? {|result| result['status'] }
end

#summarizeObject


183
184
185
186
187
188
189
190
191
192
193
# File 'lib/whiskey_disk.rb', line 183

def summarize
  puts "\nResults:"
  if results and not results.empty?
    total, successes, failures = summarize_results(results)
    puts "Total: #{total} deployment#{total == 1 ? '' : 's'}, " +
      "#{successes} success#{successes == 1 ? '' : 'es'}, " +
      "#{failures} failure#{failures == 1 ? '' : 's'}."
  else
    puts "No deployments to report."
  end       
end

#summarize_results(results) ⇒ Object


170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/whiskey_disk.rb', line 170

def summarize_results(results)
  successes = failures = 0
  results.each do |result|
    puts "#{result['domain']} => #{result['status'] ? 'succeeded' : 'failed'}."
    if result['status']
      successes += 1 
    else
      failures += 1
    end
  end
  [successes + failures, successes, failures]
end

#tail_path(path) ⇒ Object


80
81
82
# File 'lib/whiskey_disk.rb', line 80

def tail_path(path)
  File.split(path).last
end

#update_configuration_repository_checkoutObject


297
298
299
300
301
# File 'lib/whiskey_disk.rb', line 297

def update_configuration_repository_checkout
  needs(:deploy_config_to)
  initialize_rsync_changes
  refresh_checkout(setting(:deploy_config_to), config_branch)
end

#update_main_repository_checkoutObject


290
291
292
293
294
295
# File 'lib/whiskey_disk.rb', line 290

def update_main_repository_checkout
  needs(:deploy_to)
  initialize_git_changes
  refresh_checkout(setting(:deploy_to), branch)
  capture_git_changes
end