leap_cli 1.6.2 → 1.7.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 36be7f0c765dbd1c64ca36079780ad6f44797fe0
4
+ data.tar.gz: 379a244c172b9a07d0f9b1a1635d47aa16bd68bc
5
+ SHA512:
6
+ metadata.gz: 079ed74cf97faa015438ecf0dbc4ac2e4bc50a0360e48b602597ef9e8a7e7959943872a498554ef38d455ba461ff65e481d444c25bd55d14e92b6f7abd842fed
7
+ data.tar.gz: 1ec35e8f043b0b0b4516a6fa447420f0d1eb0e42c062b40afb9aae9ab939c0ce50b97dcf5989a5aac7fd70d26aa88333a8e77c655dfa76d97d7573a616f77f20
data/bin/leap CHANGED
@@ -3,13 +3,20 @@
3
3
  if ARGV.include?('--debug') || ARGV.include?('-d')
4
4
  DEBUG=true
5
5
  begin
6
- require 'debugger'
6
+ if RUBY_VERSION =~ /^2/
7
+ require 'byebug'
8
+ else
9
+ require 'debugger'
10
+ end
7
11
  rescue LoadError
8
12
  end
9
13
  else
10
14
  DEBUG=false
11
15
  end
12
16
 
17
+ LEAP_CLI_BASE_DIR = File.expand_path('..', File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__))
18
+ ORIGINAL_ARGV = ARGV.dup
19
+
13
20
  begin
14
21
  require 'leap_cli'
15
22
  rescue LoadError
@@ -24,8 +31,7 @@ rescue LoadError
24
31
  # This allows you to run the command directly while developing the gem, and also lets you
25
32
  # run from anywhere (I like to link 'bin/leap' to /usr/local/bin/leap).
26
33
  #
27
- base_dir = File.expand_path('..', File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__))
28
- require File.join(base_dir, 'lib','leap_cli','load_paths')
34
+ require File.join(LEAP_CLI_BASE_DIR, 'lib','leap_cli','load_paths')
29
35
  require 'leap_cli'
30
36
  end
31
37
 
@@ -77,9 +83,16 @@ module LeapCli::Commands
77
83
  program_desc LeapCli::SUMMARY
78
84
  program_long_desc LeapCli::DESCRIPTION
79
85
 
80
- # handle --version ourselves
86
+ # handle --version ourselves (and not GLI)
81
87
  if ARGV.grep(/--version/).any?
82
88
  puts "leap #{LeapCli::VERSION}, ruby #{RUBY_VERSION}"
89
+ begin
90
+ commands_from('leap_cli/commands')
91
+ initialize_leap_cli(false, {:verbose => 2})
92
+ rescue StandardError => exc
93
+ puts exc.to_s
94
+ raise exc if DEBUG
95
+ end
83
96
  exit(0)
84
97
  end
85
98
 
@@ -88,9 +101,10 @@ module LeapCli::Commands
88
101
  def error_message(msg)
89
102
  end
90
103
 
91
- # load commands and run
104
+ # load commands
92
105
  commands_from('leap_cli/commands')
93
- ORIGINAL_ARGV = ARGV.dup
106
+
107
+ # run command
94
108
  begin
95
109
  exit_status = run(ARGV)
96
110
  exit(LeapCli::Util.exit_status || exit_status)
data/lib/leap/platform.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'versionomy'
2
-
3
1
  module Leap
4
2
 
5
3
  class Platform
@@ -34,24 +32,24 @@ module Leap
34
32
 
35
33
  self.instance_eval(&block)
36
34
 
37
- @version ||= Versionomy.parse("0.0")
35
+ @version ||= Gem::Version.new("0.0")
38
36
  end
39
37
 
40
38
  def version=(version)
41
- @version = Versionomy.parse(version)
39
+ @version = Gem::Version.new(version)
42
40
  end
43
41
 
44
42
  def compatible_cli=(range)
45
43
  @compatible_cli = range
46
- @minimum_cli_version = Versionomy.parse(range.first)
47
- @maximum_cli_version = Versionomy.parse(range.last)
44
+ @minimum_cli_version = Gem::Version.new(range.first)
45
+ @maximum_cli_version = Gem::Version.new(range.last)
48
46
  end
49
47
 
50
48
  #
51
49
  # return true if the cli_version is compatible with this platform.
52
50
  #
53
51
  def compatible_with_cli?(cli_version)
54
- cli_version = Versionomy.parse(cli_version)
52
+ cli_version = Gem::Version.new(cli_version)
55
53
  cli_version >= @minimum_cli_version && cli_version <= @maximum_cli_version
56
54
  end
57
55
 
@@ -62,16 +60,16 @@ module Leap
62
60
  if range.is_a? String
63
61
  range = range.split('..')
64
62
  end
65
- minimum_platform_version = Versionomy.parse(range.first)
66
- maximum_platform_version = Versionomy.parse(range.last)
63
+ minimum_platform_version = Gem::Version.new(range.first)
64
+ maximum_platform_version = Gem::Version.new(range.last)
67
65
  @version >= minimum_platform_version && @version <= maximum_platform_version
68
66
  end
69
67
 
70
68
  def major_version
71
- if @version.major == 0
72
- "#{@version.major}.#{@version.minor}"
69
+ if @version.segments.first == 0
70
+ @version.segments[0..1].join('.')
73
71
  else
74
- @version.major
72
+ @version.segments.first
75
73
  end
76
74
  end
77
75
 
data/lib/leap_cli.rb CHANGED
@@ -12,7 +12,7 @@ $:.unshift(File.expand_path('../leap_cli/override',__FILE__))
12
12
  # enforce the compatible versions here:
13
13
  require 'rubygems'
14
14
  gem 'net-ssh', '~> 2.7.0'
15
- gem 'gli', '~> 2.12.0'
15
+ gem 'gli', '~> 2.12', '>= 2.12.0'
16
16
 
17
17
  require 'leap/platform'
18
18
 
@@ -20,11 +20,13 @@ require 'leap_cli/version'
20
20
  require 'leap_cli/exceptions'
21
21
 
22
22
  require 'leap_cli/leapfile'
23
- require 'leap_cli/core_ext/hash'
24
23
  require 'leap_cli/core_ext/boolean'
24
+ require 'leap_cli/core_ext/deep_dup'
25
+ require 'leap_cli/core_ext/hash'
26
+ require 'leap_cli/core_ext/json'
25
27
  require 'leap_cli/core_ext/nil'
26
28
  require 'leap_cli/core_ext/string'
27
- require 'leap_cli/core_ext/json'
29
+ require 'leap_cli/core_ext/time'
28
30
  require 'leap_cli/core_ext/yaml'
29
31
 
30
32
  require 'leap_cli/log'
@@ -28,26 +28,11 @@ module LeapCli; module Commands
28
28
  cert.command :update do |update|
29
29
  update.switch 'force', :desc => 'Always generate new certificates', :negatable => false
30
30
  update.action do |global_options,options,args|
31
- assert_files_exist! :ca_cert, :ca_key, :msg => 'Run `leap cert ca` to create them'
32
- assert_config! 'provider.ca.server_certificates.bit_size'
33
- assert_config! 'provider.ca.server_certificates.digest'
34
- assert_config! 'provider.ca.server_certificates.life_span'
35
- assert_config! 'common.x509.use'
36
-
37
- nodes = manager.filter!(args)
38
- nodes.each_node do |node|
39
- warn_if_commercial_cert_will_soon_expire(node)
40
- if !node.x509.use
41
- remove_file!([:node_x509_key, node.name])
42
- remove_file!([:node_x509_cert, node.name])
43
- elsif options[:force] || cert_needs_updating?(node)
44
- generate_cert_for_node(node)
45
- end
46
- end
31
+ update_certificates(manager.filter!(args), options)
47
32
  end
48
33
  end
49
34
 
50
- cert.desc 'Creates a Diffie-Hellman parameter file.' # (needed for server-side of some TLS connections)
35
+ cert.desc 'Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers.' # (needed for server-side of some TLS connections)
51
36
  cert.command :dh do |dh|
52
37
  dh.action do |global_options,options,args|
53
38
  long_running do
@@ -102,7 +87,11 @@ module LeapCli; module Commands
102
87
  assert_config! 'provider.ca.server_certificates.bit_size'
103
88
  assert_config! 'provider.ca.server_certificates.digest'
104
89
  domain = options[:domain] || provider.domain
105
- assert_files_missing! [:commercial_key, domain], [:commercial_csr, domain], :msg => 'If you really want to create a new key and CSR, remove these files first.'
90
+
91
+ unless global_options[:force]
92
+ assert_files_missing! [:commercial_key, domain], [:commercial_csr, domain],
93
+ :msg => 'If you really want to create a new key and CSR, remove these files first or run with --force.'
94
+ end
106
95
 
107
96
  server_certificates = provider.ca.server_certificates
108
97
 
@@ -139,7 +128,7 @@ module LeapCli; module Commands
139
128
  cert = csr.to_cert
140
129
  cert.serial_number.number = cert_serial_number(domain)
141
130
  cert.not_before = yesterday
142
- cert.not_after = years_from_yesterday(1)
131
+ cert.not_after = yesterday.advance(:years => 1)
143
132
  cert.parent = ca_root
144
133
  cert.sign! domain_test_signing_profile
145
134
  write_file! [:commercial_cert, domain], cert.to_pem
@@ -158,6 +147,29 @@ module LeapCli; module Commands
158
147
  end
159
148
  end
160
149
 
150
+ protected
151
+
152
+ #
153
+ # will generate new certificates for the specified nodes, if needed.
154
+ #
155
+ def update_certificates(nodes, options={})
156
+ assert_files_exist! :ca_cert, :ca_key, :msg => 'Run `leap cert ca` to create them'
157
+ assert_config! 'provider.ca.server_certificates.bit_size'
158
+ assert_config! 'provider.ca.server_certificates.digest'
159
+ assert_config! 'provider.ca.server_certificates.life_span'
160
+ assert_config! 'common.x509.use'
161
+
162
+ nodes.each_node do |node|
163
+ warn_if_commercial_cert_will_soon_expire(node)
164
+ if !node.x509.use
165
+ remove_file!([:node_x509_key, node.name])
166
+ remove_file!([:node_x509_cert, node.name])
167
+ elsif options[:force] || cert_needs_updating?(node)
168
+ generate_cert_for_node(node)
169
+ end
170
+ end
171
+ end
172
+
161
173
  private
162
174
 
163
175
  def generate_new_certificate_authority(key_file, cert_file, common_name)
@@ -179,7 +191,7 @@ module LeapCli; module Commands
179
191
 
180
192
  # set expiration
181
193
  root.not_before = yesterday
182
- root.not_after = years_from_yesterday(provider.ca.life_span.to_i)
194
+ root.not_after = yesterday_advance(provider.ca.life_span)
183
195
 
184
196
  # generate private key
185
197
  root.serial_number.number = 1
@@ -203,12 +215,12 @@ module LeapCli; module Commands
203
215
  return true
204
216
  else
205
217
  cert = load_certificate_file([:node_x509_cert, node.name])
206
- if cert.not_after < months_from_yesterday(2)
218
+ if cert.not_after < Time.now.advance(:months => 2)
207
219
  log :updating, "cert for node '#{node.name}' because it will expire soon"
208
220
  return true
209
221
  end
210
222
  if cert.subject.common_name != node.domain.full
211
- log :updating, "cert for node '#{node.name}' because domain.full has changed"
223
+ log :updating, "cert for node '#{node.name}' because domain.full has changed (was #{cert.subject.common_name}, now #{node.domain.full})"
212
224
  return true
213
225
  end
214
226
  cert.openssl_body.extensions.each do |ext|
@@ -242,7 +254,7 @@ module LeapCli; module Commands
242
254
  if cert.not_after < Time.now.utc
243
255
  log :error, "the commercial certificate '#{path}' has EXPIRED! " +
244
256
  "You should renew it with `leap cert csr --domain #{domain}`."
245
- elsif cert.not_after < months_from_yesterday(2)
257
+ elsif cert.not_after < Time.now.advance(:months => 2)
246
258
  log :warning, "the commercial certificate '#{path}' will expire soon. "+
247
259
  "You should renew it with `leap cert csr --domain #{domain}`."
248
260
  end
@@ -261,7 +273,7 @@ module LeapCli; module Commands
261
273
 
262
274
  # set expiration
263
275
  cert.not_before = yesterday
264
- cert.not_after = years_from_yesterday(provider.ca.server_certificates.life_span.to_i)
276
+ cert.not_after = yesterday_advance(provider.ca.server_certificates.life_span)
265
277
 
266
278
  # generate key
267
279
  cert.key_material.generate_key(provider.ca.server_certificates.bit_size)
@@ -283,7 +295,7 @@ module LeapCli; module Commands
283
295
  cert.serial_number.number = cert_serial_number(provider.domain)
284
296
  cert.subject.common_name = [prefix, random_common_name(provider.domain)].join
285
297
  cert.not_before = yesterday
286
- cert.not_after = years_from_yesterday(1)
298
+ cert.not_after = yesterday.advance(:years => 1)
287
299
  cert.key_material.generate_key(1024) # just for testing, remember!
288
300
  cert.parent = client_ca_root
289
301
  cert.sign! client_test_signing_profile
@@ -492,16 +504,15 @@ module LeapCli; module Commands
492
504
  Time.utc t.year, t.month, t.day
493
505
  end
494
506
 
495
- def years_from_yesterday(num)
496
- t = yesterday
497
- Time.utc t.year + num, t.month, t.day
498
- end
499
-
500
- def months_from_yesterday(num)
501
- t = yesterday
502
- date = Date.new t.year, t.month, t.day
503
- date = date >> num # >> is months in the future operator
504
- Time.utc date.year, date.month, date.day
507
+ def yesterday_advance(string)
508
+ number, unit = string.split(' ')
509
+ unless ['years', 'months', 'days', 'hours', 'minutes'].include? unit
510
+ bail!("The time property '#{string}' is missing a unit (one of: years, months, days, hours, minutes).")
511
+ end
512
+ unless number.to_i.to_s == number
513
+ bail!("The time property '#{string}' is missing a number.")
514
+ end
515
+ yesterday.advance(unit.to_sym => number.to_i)
505
516
  end
506
517
 
507
518
  end; end
@@ -12,8 +12,12 @@ module LeapCli
12
12
  if !LeapCli.leapfile.environment.nil? && !environment.nil? && environment != LeapCli.leapfile.environment
13
13
  bail! "You cannot specify an ENVIRONMENT argument while the environment is pinned."
14
14
  end
15
- if environment && manager.environment_names.include?(environment)
16
- compile_hiera_files(manager.filter([environment]))
15
+ if environment
16
+ if manager.environment_names.include?(environment)
17
+ compile_hiera_files(manager.filter([environment]))
18
+ else
19
+ bail! "There is no environment named `#{environment}`."
20
+ end
17
21
  else
18
22
  compile_hiera_files(manager.filter)
19
23
  end
@@ -2,21 +2,32 @@ module LeapCli; module Commands
2
2
 
3
3
  desc 'Database commands.'
4
4
  command :db do |db|
5
- db.desc 'Destroy all the databases. If present, limit to FILTER nodes.'
5
+ db.desc 'Destroy one or more databases. If present, limit to FILTER nodes. For example `leap db destroy --db sessions,tokens testing`.'
6
6
  db.arg_name 'FILTER', :optional => true
7
7
  db.command :destroy do |destroy|
8
+ destroy.flag :db, :arg_name => "DATABASES", :desc => 'Comma separated list of databases to destroy (no space). Use "--db all" to destroy all databases.', :optional => false
8
9
  destroy.action do |global_options,options,args|
9
- say 'You are about to permanently destroy all database data.'
10
- return unless agree("Continue? ")
10
+ dbs = (options[:db]||"").split(',')
11
+ bail!('No databases specified') if dbs.empty?
11
12
  nodes = manager.filter(args)
12
13
  if nodes.any?
13
14
  nodes = nodes[:services => 'couchdb']
14
15
  end
15
16
  if nodes.any?
16
- ssh_connect(nodes, connect_options(options)) do |ssh|
17
- ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"')
18
- ssh.run('grep ^seq_file /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -v')
17
+ unless global_options[:yes]
18
+ if dbs.include?('all')
19
+ say 'You are about to permanently destroy all database data for nodes [%s].' % nodes.keys.join(', ')
20
+ else
21
+ say 'You are about to permanently destroy databases [%s] for nodes [%s].' % [dbs.join(', '), nodes.keys.join(', ')]
22
+ end
23
+ bail! unless agree("Continue? ")
19
24
  end
25
+ if dbs.include?('all')
26
+ destroy_all_dbs(nodes)
27
+ else
28
+ destroy_dbs(nodes, dbs)
29
+ end
30
+ say 'You must run `leap deploy` in order to create the databases again.'
20
31
  else
21
32
  say 'No nodes'
22
33
  end
@@ -26,4 +37,29 @@ module LeapCli; module Commands
26
37
 
27
38
  private
28
39
 
40
+ def destroy_all_dbs(nodes)
41
+ ssh_connect(nodes) do |ssh|
42
+ ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"')
43
+ ssh.run('grep ^seq_dir /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -rv')
44
+ end
45
+ end
46
+
47
+ def destroy_dbs(nodes, dbs)
48
+ nodes.each_node do |node|
49
+ ssh_connect(node) do |ssh|
50
+ dbs.each do |db|
51
+ ssh.run(DESTROY_DB_COMMAND % {:db => db})
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ DESTROY_DB_COMMAND = %{
58
+ if [ 200 = `curl -ns -w "%%{http_code}" -X GET "127.0.0.1:5984/%{db}" -o /dev/null` ]; then
59
+ echo "Result from DELETE /%{db}:" `curl -ns -X DELETE "127.0.0.1:5984/%{db}"`;
60
+ else
61
+ echo "Skipping db '%{db}': it does not exist or has already been deleted.";
62
+ fi
63
+ }
64
+
29
65
  end; end
@@ -1,3 +1,4 @@
1
+ require 'etc'
1
2
 
2
3
  module LeapCli
3
4
  module Commands
@@ -7,20 +8,17 @@ module LeapCli
7
8
  arg_name 'FILTER'
8
9
  command [:deploy, :d] do |c|
9
10
 
10
- # --fast
11
11
  c.switch :fast, :desc => 'Makes the deploy command faster by skipping some slow steps. A "fast" deploy can be used safely if you recently completed a normal deploy.',
12
12
  :negatable => false
13
13
 
14
- # --sync
15
- c.switch :sync, :desc => "Sync files, but don't actually apply recipes."
14
+ c.switch :sync, :desc => "Sync files, but don't actually apply recipes.", :negatable => false
16
15
 
17
- # --force
18
16
  c.switch :force, :desc => 'Deploy even if there is a lockfile.', :negatable => false
19
17
 
20
- # --dev
18
+ c.switch :downgrade, :desc => 'Allows deploy to run with an older platform version.', :negatable => false
19
+
21
20
  c.switch :dev, :desc => "Development mode: don't run 'git submodule update' before deploy.", :negatable => false
22
21
 
23
- # --tags
24
22
  c.flag :tags, :desc => 'Specify tags to pass through to puppet (overriding the default).',
25
23
  :arg_name => 'TAG[,TAG]'
26
24
 
@@ -49,11 +47,13 @@ module LeapCli
49
47
  environments = [nil]
50
48
  end
51
49
  environments.each do |env|
52
- check_platform_pinning(env)
50
+ check_platform_pinning(env, global)
53
51
  end
54
52
  # compile hiera files for all the nodes in every environment that is
55
53
  # being deployed and only those environments.
56
54
  compile_hiera_files(manager.filter(environments))
55
+ # update server certificates if needed
56
+ update_certificates(nodes)
57
57
 
58
58
  ssh_connect(nodes, connect_options(options)) do |ssh|
59
59
  ssh.leap.log :checking, 'node' do
@@ -69,7 +69,12 @@ module LeapCli
69
69
  end
70
70
  unless options[:sync]
71
71
  ssh.leap.log :applying, "puppet" do
72
- ssh.puppet.apply(:verbosity => [LeapCli.log_level,5].min, :tags => tags(options), :force => options[:force])
72
+ ssh.puppet.apply(:verbosity => [LeapCli.log_level,5].min,
73
+ :tags => tags(options),
74
+ :force => options[:force],
75
+ :info => deploy_info,
76
+ :downgrade => options[:downgrade]
77
+ )
73
78
  end
74
79
  end
75
80
  end
@@ -79,8 +84,34 @@ module LeapCli
79
84
  end
80
85
  end
81
86
 
87
+ desc 'Display recent deployment history for a set of nodes.'
88
+ long_desc 'The FILTER can be the name of a node, service, or tag.'
89
+ arg_name 'FILTER'
90
+ command [:history, :h] do |c|
91
+ c.flag :port, :desc => 'Override the default SSH port.',
92
+ :arg_name => 'PORT'
93
+ c.flag :ip, :desc => 'Override the default SSH IP address.',
94
+ :arg_name => 'IPADDRESS'
95
+ c.action do |global,options,args|
96
+ nodes = manager.filter!(args)
97
+ ssh_connect(nodes, connect_options(options)) do |ssh|
98
+ ssh.leap.history
99
+ end
100
+ end
101
+ end
102
+
82
103
  private
83
104
 
105
+ def forcible_prompt(forced, msg, prompt)
106
+ say(msg)
107
+ if forced
108
+ log :warning, "continuing anyway because of --force"
109
+ else
110
+ say "hint: use --force to skip this prompt."
111
+ quit!("OK. Bye.") unless agree(prompt)
112
+ end
113
+ end
114
+
84
115
  #
85
116
  # The currently activated provider.json could have loaded some pinning
86
117
  # information for the platform. If this is the case, refuse to deploy
@@ -94,7 +125,7 @@ module LeapCli
94
125
  # "commit": "e1d6280e0a8c565b7fb1a4ed3969ea6fea31a5e2..HEAD"
95
126
  # }
96
127
  #
97
- def check_platform_pinning(environment)
128
+ def check_platform_pinning(environment, global_options)
98
129
  provider = manager.env(environment).provider
99
130
  return unless provider['platform']
100
131
 
@@ -112,34 +143,46 @@ module LeapCli
112
143
  # check version
113
144
  if provider.platform['version']
114
145
  if !Leap::Platform.version_in_range?(provider.platform.version)
115
- say("The platform is pinned to a version range of '#{provider.platform.version}' "+
116
- "by the `platform.version` property in #{provider_json}, but the platform "+
117
- "(#{Path.platform}) has version #{Leap::Platform.version}.")
118
- quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong version? ")
146
+ forcible_prompt(
147
+ global_options[:force],
148
+ "The platform is pinned to a version range of '#{provider.platform.version}' "+
149
+ "by the `platform.version` property in #{provider_json}, but the platform "+
150
+ "(#{Path.platform}) has version #{Leap::Platform.version}.",
151
+ "Do you really want to deploy from the wrong version? "
152
+ )
119
153
  end
120
154
  end
121
155
 
122
156
  # check branch
123
157
  if provider.platform['branch']
124
158
  if !is_git_directory?(Path.platform)
125
- say("The platform is pinned to a particular branch by the `platform.branch` property "+
126
- "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.")
127
- quit!("OK. Bye.") unless agree("Do you really want to deploy anyway? ")
159
+ forcible_prompt(
160
+ global_options[:force],
161
+ "The platform is pinned to a particular branch by the `platform.branch` property "+
162
+ "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.",
163
+ "Do you really want to deploy anyway? "
164
+ )
128
165
  end
129
166
  unless provider.platform.branch == current_git_branch(Path.platform)
130
- say("The platform is pinned to branch '#{provider.platform.branch}' by the `platform.branch` property "+
131
- "in #{provider_json}, but the current branch is '#{current_git_branch(Path.platform)}' " +
132
- "(for directory '#{Path.platform}')")
133
- quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong branch? ")
167
+ forcible_prompt(
168
+ global_options[:force],
169
+ "The platform is pinned to branch '#{provider.platform.branch}' by the `platform.branch` property "+
170
+ "in #{provider_json}, but the current branch is '#{current_git_branch(Path.platform)}' " +
171
+ "(for directory '#{Path.platform}')",
172
+ "Do you really want to deploy from the wrong branch? "
173
+ )
134
174
  end
135
175
  end
136
176
 
137
177
  # check commit
138
178
  if provider.platform['commit']
139
179
  if !is_git_directory?(Path.platform)
140
- say("The platform is pinned to a particular commit range by the `platform.commit` property "+
141
- "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.")
142
- quit!("OK. Bye.") unless agree("Do you really want to deploy anyway? ")
180
+ forcible_prompt(
181
+ global_options[:force],
182
+ "The platform is pinned to a particular commit range by the `platform.commit` property "+
183
+ "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.",
184
+ "Do you really want to deploy anyway? "
185
+ )
143
186
  end
144
187
  current_commit = current_git_commit(Path.platform)
145
188
  Dir.chdir(Path.platform) do
@@ -150,10 +193,13 @@ module LeapCli
150
193
  commit_range = commit_range.split("\n")
151
194
  if !commit_range.include?(current_commit) &&
152
195
  provider.platform.commit.split('..').first != current_commit
153
- say("The platform is pinned via the `platform.commit` property in #{provider_json} " +
154
- "to a commit in the range #{provider.platform.commit}, but the current HEAD " +
155
- "(#{current_commit}) is not in that range.")
156
- quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong commit? ")
196
+ forcible_prompt(
197
+ global_options[:force],
198
+ "The platform is pinned via the `platform.commit` property in #{provider_json} " +
199
+ "to a commit in the range #{provider.platform.commit}, but the current HEAD " +
200
+ "(#{current_commit}) is not in that range.",
201
+ "Do you really want to deploy from the wrong commit? "
202
+ )
157
203
  end
158
204
  end
159
205
  end
@@ -177,17 +223,11 @@ module LeapCli
177
223
  #
178
224
  def sync_support_files(ssh)
179
225
  dest_dir = Leap::Platform.files_dir
180
- source_files = []
181
- if Path.defined?(:custom_puppet_dir) && file_exists?(:custom_puppet_dir)
182
- source_files += [:custom_puppet_dir, :custom_puppet_modules_dir, :custom_puppet_manifests_dir].collect{|path|
183
- Path.relative_path(path, Path.provider) + '/' # rsync needs trailing slash
184
- }
185
- ensure_dir :custom_puppet_modules_dir
186
- end
226
+ custom_files = build_custom_file_list
187
227
  ssh.rsync.update do |server|
188
228
  node = manager.node(server.host)
189
229
  files_to_sync = node.file_paths.collect {|path| Path.relative_path(path, Path.provider) }
190
- files_to_sync += source_files
230
+ files_to_sync += custom_files
191
231
  if files_to_sync.any?
192
232
  ssh.leap.log(files_to_sync.join(', ') + ' -> ' + node.name + ':' + dest_dir)
193
233
  {
@@ -282,5 +322,47 @@ module LeapCli
282
322
  tags.join(',')
283
323
  end
284
324
 
325
+ #
326
+ # a provider might have various customization files that should be sync'ed to the server.
327
+ # this method builds that list of files to sync.
328
+ #
329
+ def build_custom_file_list
330
+ custom_files = []
331
+ Leap::Platform.paths.keys.grep(/^custom_/).each do |path|
332
+ if file_exists?(path)
333
+ relative_path = Path.relative_path(path, Path.provider)
334
+ if dir_exists?(path)
335
+ custom_files << relative_path + '/' # rsync needs trailing slash
336
+ else
337
+ custom_files << relative_path
338
+ end
339
+ end
340
+ end
341
+ return custom_files
342
+ end
343
+
344
+ def deploy_info
345
+ info = []
346
+ info << "user: %s" % Etc.getpwuid(Process.euid).name
347
+ if is_git_directory?(Path.platform) && current_git_branch(Path.platform) != 'master'
348
+ info << "platform: %s (%s %s)" % [
349
+ Leap::Platform.version,
350
+ current_git_branch(Path.platform),
351
+ current_git_commit(Path.platform)[0..4]
352
+ ]
353
+ else
354
+ info << "platform: %s" % Leap::Platform.version
355
+ end
356
+ if is_git_directory?(LEAP_CLI_BASE_DIR)
357
+ info << "leap_cli: %s (%s %s)" % [
358
+ LeapCli::VERSION,
359
+ current_git_branch(LEAP_CLI_BASE_DIR),
360
+ current_git_commit(LEAP_CLI_BASE_DIR)[0..4]
361
+ ]
362
+ else
363
+ info << "leap_cli: %s" % LeapCli::VERSION
364
+ end
365
+ info.join(', ')
366
+ end
285
367
  end
286
368
  end