leap_cli 1.8.1 → 1.9

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/bin/leap +6 -12
  3. data/lib/leap_cli.rb +3 -23
  4. data/lib/leap_cli/bootstrap.rb +36 -12
  5. data/lib/leap_cli/commands/common.rb +88 -46
  6. data/lib/leap_cli/commands/new.rb +24 -17
  7. data/lib/leap_cli/commands/pre.rb +3 -1
  8. data/lib/leap_cli/core_ext/hash.rb +19 -0
  9. data/lib/leap_cli/leapfile.rb +47 -32
  10. data/lib/leap_cli/log.rb +196 -88
  11. data/lib/leap_cli/path.rb +5 -5
  12. data/lib/leap_cli/util.rb +28 -18
  13. data/lib/leap_cli/version.rb +8 -3
  14. data/vendor/acme-client/lib/acme-client.rb +1 -0
  15. data/vendor/acme-client/lib/acme/client.rb +122 -0
  16. data/vendor/acme-client/lib/acme/client/certificate.rb +30 -0
  17. data/vendor/acme-client/lib/acme/client/certificate_request.rb +111 -0
  18. data/vendor/acme-client/lib/acme/client/crypto.rb +98 -0
  19. data/vendor/acme-client/lib/acme/client/error.rb +16 -0
  20. data/vendor/acme-client/lib/acme/client/faraday_middleware.rb +123 -0
  21. data/vendor/acme-client/lib/acme/client/resources.rb +5 -0
  22. data/vendor/acme-client/lib/acme/client/resources/authorization.rb +44 -0
  23. data/vendor/acme-client/lib/acme/client/resources/challenges.rb +6 -0
  24. data/vendor/acme-client/lib/acme/client/resources/challenges/base.rb +43 -0
  25. data/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb +19 -0
  26. data/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb +18 -0
  27. data/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb +24 -0
  28. data/vendor/acme-client/lib/acme/client/resources/registration.rb +37 -0
  29. data/vendor/acme-client/lib/acme/client/self_sign_certificate.rb +60 -0
  30. data/vendor/acme-client/lib/acme/client/version.rb +7 -0
  31. data/vendor/base32/lib/base32.rb +67 -0
  32. data/vendor/certificate_authority/lib/certificate_authority.rb +2 -1
  33. data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +4 -4
  34. data/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +7 -5
  35. data/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb +46 -0
  36. data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +6 -2
  37. data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +10 -3
  38. data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +11 -9
  39. data/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb +3 -3
  40. data/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb +0 -2
  41. data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +8 -2
  42. data/vendor/certificate_authority/lib/certificate_authority/validations.rb +31 -0
  43. data/vendor/rsync_command/lib/rsync_command.rb +49 -12
  44. metadata +50 -91
  45. data/lib/leap/platform.rb +0 -90
  46. data/lib/leap_cli/config/environment.rb +0 -180
  47. data/lib/leap_cli/config/filter.rb +0 -178
  48. data/lib/leap_cli/config/manager.rb +0 -419
  49. data/lib/leap_cli/config/node.rb +0 -77
  50. data/lib/leap_cli/config/object.rb +0 -428
  51. data/lib/leap_cli/config/object_list.rb +0 -209
  52. data/lib/leap_cli/config/provider.rb +0 -22
  53. data/lib/leap_cli/config/secrets.rb +0 -87
  54. data/lib/leap_cli/config/sources.rb +0 -11
  55. data/lib/leap_cli/config/tag.rb +0 -25
  56. data/lib/leap_cli/lib_ext/capistrano_connections.rb +0 -16
  57. data/lib/leap_cli/logger.rb +0 -237
  58. data/lib/leap_cli/remote/leap_plugin.rb +0 -192
  59. data/lib/leap_cli/remote/puppet_plugin.rb +0 -26
  60. data/lib/leap_cli/remote/rsync_plugin.rb +0 -35
  61. data/lib/leap_cli/remote/tasks.rb +0 -51
  62. data/lib/leap_cli/ssh_key.rb +0 -195
  63. data/lib/leap_cli/util/remote_command.rb +0 -158
  64. data/lib/leap_cli/util/secret.rb +0 -55
  65. data/lib/leap_cli/util/x509.rb +0 -33
@@ -32,4 +32,23 @@ class Hash
32
32
  replace(deep_merge(other_hash))
33
33
  end
34
34
 
35
+ #
36
+ # A recursive symbolize_keys
37
+ #
38
+ unless Hash.method_defined?(:symbolize_keys)
39
+ def symbolize_keys
40
+ self.inject({}) {|result, (key, value)|
41
+ new_key = case key
42
+ when String then key.to_sym
43
+ else key
44
+ end
45
+ new_value = case value
46
+ when Hash then symbolize_keys(value)
47
+ else value
48
+ end
49
+ result[new_key] = new_value
50
+ result
51
+ }
52
+ end
53
+ end
35
54
  end
@@ -3,6 +3,8 @@
3
3
  #
4
4
  # It is akin to a Gemfile, Rakefile, or Capfile (e.g. it is a ruby file that gets eval'ed)
5
5
  #
6
+ # Additional configuration options are defined in platform's leapfile_extensions.rb
7
+ #
6
8
 
7
9
  module LeapCli
8
10
  def self.leapfile
@@ -10,17 +12,12 @@ module LeapCli
10
12
  end
11
13
 
12
14
  class Leapfile
13
- attr_accessor :platform_directory_path
14
- attr_accessor :provider_directory_path
15
- attr_accessor :custom_vagrant_vm_line
16
- attr_accessor :leap_version
17
- attr_accessor :log
18
- attr_accessor :vagrant_network
19
- attr_accessor :vagrant_basebox
20
- attr_accessor :environment
15
+ attr_reader :platform_directory_path
16
+ attr_reader :provider_directory_path
17
+ attr_reader :environment
18
+ attr_reader :valid
21
19
 
22
20
  def initialize
23
- @vagrant_network = '10.5.5.0/24'
24
21
  end
25
22
 
26
23
  #
@@ -61,25 +58,44 @@ module LeapCli
61
58
  #
62
59
  # load the platform
63
60
  #
64
- platform_file = "#{@platform_directory_path}/platform.rb"
65
- unless File.exists?(platform_file)
61
+ platform_class = "#{@platform_directory_path}/lib/leap/platform"
62
+ platform_definition = "#{@platform_directory_path}/platform.rb"
63
+ unless File.exist?(platform_definition)
66
64
  Util.bail! "ERROR: The file `#{platform_file}` does not exist. Please check the value of `@platform_directory_path` in `Leapfile` or `~/.leaprc`."
67
65
  end
68
- require "#{@platform_directory_path}/platform.rb"
69
- if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION) ||
70
- !Leap::Platform.version_in_range?(LeapCli::COMPATIBLE_PLATFORM_VERSION)
71
- Util.bail! "This leap command (v#{LeapCli::VERSION}) " +
72
- "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}).\n " +
73
- "You need either leap command #{Leap::Platform.compatible_cli.first} to #{Leap::Platform.compatible_cli.last} or " +
74
- "platform version #{LeapCli::COMPATIBLE_PLATFORM_VERSION.first} to #{LeapCli::COMPATIBLE_PLATFORM_VERSION.last}"
66
+ begin
67
+ require platform_class
68
+ require platform_definition
69
+ rescue LoadError
70
+ Util.log "The leap_platform at #{platform_directory_path} is not compatible with this version of leap_cli"
71
+ Util.log "You can either:" do
72
+ Util.log "Upgrade leap_platform to version " + LeapCli::COMPATIBLE_PLATFORM_VERSION.first
73
+ Util.log "Or, downgrade leap_cli to version 1.8"
74
+ end
75
+ Util.bail!
76
+ rescue StandardError => exc
77
+ Util.bail! exc.to_s
75
78
  end
76
- unless @allow_production_deploy.nil?
77
- Util::log 0, :warning, "in Leapfile: @allow_production_deploy is no longer supported."
79
+ begin
80
+ Leap::Platform.validate!(LeapCli::VERSION, LeapCli::COMPATIBLE_PLATFORM_VERSION, self)
81
+ rescue StandardError => exc
82
+ Util.bail! exc.to_s
78
83
  end
79
- unless @platform_branch.nil?
80
- Util::log 0, :warning, "in Leapfile: @platform_branch is no longer supported."
84
+ leapfile_extensions = "#{@platform_directory_path}/lib/leap_cli/leapfile_extensions.rb"
85
+ if File.exist?(leapfile_extensions)
86
+ require leapfile_extensions
81
87
  end
82
- @valid = true
88
+
89
+ #
90
+ # validate
91
+ #
92
+ instance_variables.each do |var|
93
+ var = var.to_s.sub('@', '')
94
+ if !self.respond_to?(var)
95
+ LeapCli.log :warning, "the variable `#{var}` is set in .leaprc or Leapfile, but it is not supported."
96
+ end
97
+ end
98
+ @valid = validate
83
99
  return @valid
84
100
  end
85
101
  end
@@ -105,7 +121,7 @@ module LeapCli
105
121
  def edit_leaprc(property, value=nil)
106
122
  file_path = leaprc_path
107
123
  lines = []
108
- if File.exists?(file_path)
124
+ if File.exist?(file_path)
109
125
  regexp = /self\.#{Regexp.escape(property)} = .*? if @provider_directory_path == '#{Regexp.escape(@provider_directory_path)}'/
110
126
  File.readlines(file_path).each do |line|
111
127
  unless line =~ regexp
@@ -128,10 +144,9 @@ module LeapCli
128
144
  end
129
145
 
130
146
  def read_settings(file)
131
- if File.exists? file
132
- Util::log 2, :read, file
147
+ if File.exist? file
148
+ LeapCli.log 2, :read, file
133
149
  instance_eval(File.read(file), file)
134
- validate(file)
135
150
  end
136
151
  end
137
152
 
@@ -146,11 +161,11 @@ module LeapCli
146
161
  return search_dir
147
162
  end
148
163
 
149
- PRIVATE_IP_RANGES = /(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)/
150
-
151
- def validate(file)
152
- Util::assert! vagrant_network =~ PRIVATE_IP_RANGES do
153
- Util::log 0, :error, "in #{file}: vagrant_network is not a local private network"
164
+ def method_missing(method, *args)
165
+ if method =~ /=$/
166
+ self.instance_variable_set('@' + method.to_s.sub('=',''), args.first)
167
+ else
168
+ self.instance_variable_get('@' + method.to_s)
154
169
  end
155
170
  end
156
171
 
data/lib/leap_cli/log.rb CHANGED
@@ -1,58 +1,84 @@
1
- require 'paint'
2
-
3
1
  ##
4
2
  ## LOGGING
5
3
  ##
6
- ## Ugh. This class does not work well with multiple threads!
7
- ##
8
4
 
9
5
  module LeapCli
10
- extend self
6
+ module LogCommand
7
+ @@logger = nil
11
8
 
12
- attr_accessor :log_in_color
9
+ def log(*args, &block)
10
+ logger.log(*args, &block)
11
+ end
13
12
 
14
- # logging options
15
- def log_level
16
- @log_level ||= 1
17
- end
18
- def set_log_level(value)
19
- @log_level = value
20
- end
13
+ def log_raw(*args, &block)
14
+ logger.log_raw(*args, &block)
15
+ end
21
16
 
22
- def indent_level
23
- @indent_level ||= 0
24
- end
25
- def indent_level=(value)
26
- @indent_level = value
27
- end
17
+ # global shared logger
18
+ def logger
19
+ @@logger ||= LeapCli::LeapLogger.new
20
+ end
28
21
 
29
- def log_file
30
- @log_file
31
- end
32
- def log_file=(value)
33
- @log_file = value
34
- if @log_file
35
- if !File.directory?(File.dirname(@log_file))
36
- Util.bail!('Invalid log file "%s", directory "%s" does not exist' % [@log_file, File.dirname(@log_file)])
37
- end
38
- @log_output_stream = File.open(@log_file, 'a')
22
+ # thread safe logger
23
+ def new_logger
24
+ logger.dup
39
25
  end
40
- end
41
26
 
42
- def log_output_stream
43
- @log_output_stream
44
- end
27
+ # deprecated
28
+ def log_level
29
+ logger.log_level
30
+ end
31
+
32
+ #
33
+ # These probably should have been part of the logger originally,
34
+ # but they are made available here for convenience:
35
+ #
36
+
37
+ def bail!(*args, &block)
38
+ Util.bail!(*args, &block)
39
+ end
45
40
 
41
+ def assert!(*args, &block)
42
+ Util.assert!(*args, &block)
43
+ end
44
+
45
+ end
46
46
  end
47
47
 
48
48
 
49
49
  module LeapCli
50
- module Log
50
+ class LeapLogger
51
51
  #
52
52
  # these are log titles typically associated with files
53
53
  #
54
- FILE_TITLES = [:updated, :created, :removed, :missing, :nochange, :loading]
54
+ FILE_TITLES = %w(updated created removed missing nochange loading)
55
+
56
+ # TODO: use these
57
+ IMPORTANT = 0
58
+ INFO = 1
59
+ DEBUG = 2
60
+ TRACE = 3
55
61
 
62
+ attr_reader :log_output_stream, :log_file
63
+ attr_accessor :indent_level, :log_level, :log_in_color
64
+
65
+ def initialize()
66
+ @log_level = 1
67
+ @indent_level = 0
68
+ @log_file = nil
69
+ @log_output_stream = nil
70
+ @log_in_color = true
71
+ end
72
+
73
+ def log_file=(value)
74
+ @log_file = value
75
+ if @log_file
76
+ if !File.directory?(File.dirname(@log_file))
77
+ Util.bail!('Invalid log file "%s", directory "%s" does not exist' % [@log_file, File.dirname(@log_file)])
78
+ end
79
+ @log_output_stream = File.open(@log_file, 'a')
80
+ end
81
+ end
56
82
 
57
83
  #
58
84
  # master logging function.
@@ -63,74 +89,95 @@ module LeapCli
63
89
  # * Integer: the log level (0, 1, 2)
64
90
  # * Symbol: the prefix title to colorize. may be one of
65
91
  # [:error, :warning, :info, :updated, :created, :removed, :no_change, :missing]
66
- # * Hash: a hash of options. so far, only :indent is supported.
92
+ # * Hash: a hash of options.
93
+ # :wrap -- if true, appy intend to each line in message.
94
+ # :color -- apply color to message or prefix
95
+ # :style -- apply style to message or prefix
67
96
  #
68
-
69
97
  def log(*args)
70
98
  level = args.grep(Integer).first || 1
71
99
  title = args.grep(Symbol).first
72
100
  message = args.grep(String).first
73
101
  options = args.grep(Hash).first || {}
74
- unless message && LeapCli.log_level >= level
102
+ host = options[:host]
103
+ if title
104
+ title = title.to_s
105
+ end
106
+ if @log_level < level || (title.nil? && message.nil?)
75
107
  return
76
108
  end
77
109
 
78
- # prefix
79
- clear_prefix = colored_prefix = ""
80
- if title
81
- prefix_options = case title
82
- when :error then ['error', :red, :bold]
83
- when :fatal_error then ['fatal error:', :red, :bold]
84
- when :warning then ['warning:', :yellow, :bold]
85
- when :info then ['info', :cyan, :bold]
86
- when :note then ['NOTE:', :cyan, :bold]
87
- when :updated then ['updated', :cyan, :bold]
88
- when :updating then ['updating', :cyan, :bold]
89
- when :created then ['created', :green, :bold]
90
- when :removed then ['removed', :red, :bold]
91
- when :nochange then ['no change', :magenta]
92
- when :loading then ['loading', :magenta]
93
- when :missing then ['missing', :yellow, :bold]
94
- when :skipping then ['skipping', :yellow, :bold]
95
- when :run then ['run', :magenta]
96
- when :failed then ['FAILED', :red, :bold]
97
- when :completed then ['completed', :green, :bold]
98
- when :ran then ['ran', :green, :bold]
99
- when :bail then ['bailing out', :red, :bold]
100
- when :invalid then ['invalid', :red, :bold]
101
- else [title.to_s, :cyan, :bold]
102
- end
103
- if options[:host]
104
- clear_prefix = "[%s] %s " % [options[:host], prefix_options[0]]
105
- colored_prefix = "[%s] %s " % [Paint[options[:host], prefix_options[1], prefix_options[2]], prefix_options[0]]
110
+ #
111
+ # transform absolute path names
112
+ #
113
+ if title && FILE_TITLES.include?(title) && message =~ /^\//
114
+ message = LeapCli::Path.relative_path(message)
115
+ end
116
+
117
+ #
118
+ # apply filters
119
+ # LogFilter will not be defined if no platform was loaded.
120
+ #
121
+ if defined?(LeapCli::LogFilter)
122
+ if title
123
+ title, filter_flags = LogFilter.apply_title_filters(title)
106
124
  else
107
- clear_prefix = "%s " % prefix_options[0]
108
- colored_prefix = "%s " % Paint[prefix_options[0], prefix_options[1], prefix_options[2]]
125
+ message, filter_flags = LogFilter.apply_message_filters(message)
126
+ return if message.nil?
109
127
  end
110
- elsif options[:host]
111
- clear_prefix = colored_prefix = "[%s] " % options[:host]
128
+ options = options.merge(filter_flags)
112
129
  end
113
130
 
114
- # transform absolute path names
115
- if title && FILE_TITLES.include?(title) && message =~ /^\//
116
- message = LeapCli::Path.relative_path(message)
131
+ #
132
+ # set line prefix
133
+ #
134
+ if (host)
135
+ host = host.split('.').first
117
136
  end
137
+ prefix = prefix_str(host, title)
118
138
 
119
- log_raw(:log, nil) { [clear_prefix, message].join }
120
- if LeapCli.log_in_color
121
- log_raw(:stdout, options[:indent]) { [colored_prefix, message].join }
122
- else
123
- log_raw(:stdout, options[:indent]) { [clear_prefix, message].join }
139
+ #
140
+ # write to the log file, always
141
+ #
142
+ log_raw(:log, nil, prefix) { message }
143
+
144
+ #
145
+ # log to stdout, maybe in color
146
+ #
147
+ if @log_in_color
148
+ if options[:wrap]
149
+ message = message.split("\n")
150
+ end
151
+ if options[:color]
152
+ if host
153
+ host = colorize(host, options[:color], options[:style])
154
+ elsif title
155
+ title = colorize(title, options[:color], options[:style])
156
+ else
157
+ message = colorize(message, options[:color], options[:style])
158
+ end
159
+ elsif title
160
+ title = colorize(title, :cyan, :bold)
161
+ end
162
+ # new colorized prefix:
163
+ prefix = prefix_str(host, title)
124
164
  end
165
+ log_raw(:stdout, options[:indent], prefix) { message }
125
166
 
126
- # run block, if given
167
+ #
168
+ # run block indented, if given
169
+ #
127
170
  if block_given?
128
- LeapCli.indent_level += 1
171
+ @indent_level += 1
129
172
  yield
130
- LeapCli.indent_level -= 1
173
+ @indent_level -= 1
131
174
  end
132
175
  end
133
176
 
177
+ def debug(*args)
178
+ self.log(3, *args)
179
+ end
180
+
134
181
  #
135
182
  # Add a raw log entry, without any modifications (other than indent).
136
183
  # Content to be logged is yielded by the block.
@@ -139,23 +186,26 @@ module LeapCli
139
186
  # if mode == :stdout, output is sent to STDOUT.
140
187
  # if mode == :log, output is sent to log file, if present.
141
188
  #
142
- def log_raw(mode, indent=nil, &block)
143
- # NOTE: print message (using 'print' produces better results than 'puts' when multiple threads are logging)
189
+ def log_raw(mode, indent=nil, prefix=nil, &block)
190
+ # NOTE: using 'print' produces better results than 'puts'
191
+ # when multiple threads are logging)
144
192
  if mode == :log
145
- if LeapCli.log_output_stream
193
+ if @log_output_stream
146
194
  messages = [yield].compact.flatten
147
195
  if messages.any?
148
196
  timestamp = Time.now.strftime("%b %d %H:%M:%S")
149
197
  messages.each do |message|
150
- LeapCli.log_output_stream.print("#{timestamp} #{message}\n")
198
+ message = message.rstrip
199
+ next if message.empty?
200
+ @log_output_stream.print("#{timestamp} #{prefix} #{message}\n")
151
201
  end
152
- LeapCli.log_output_stream.flush
202
+ @log_output_stream.flush
153
203
  end
154
204
  end
155
205
  elsif mode == :stdout
156
206
  messages = [yield].compact.flatten
157
207
  if messages.any?
158
- indent ||= LeapCli.indent_level
208
+ indent ||= @indent_level
159
209
  indent_str = ""
160
210
  indent_str += " " * indent.to_i
161
211
  if indent.to_i > 0
@@ -163,12 +213,70 @@ module LeapCli
163
213
  else
164
214
  indent_str += ' = '
165
215
  end
216
+ indent_str += prefix if prefix
166
217
  messages.each do |message|
218
+ message = message.rstrip
219
+ next if message.empty?
167
220
  STDOUT.print("#{indent_str}#{message}\n")
168
221
  end
169
222
  end
170
223
  end
171
224
  end
172
225
 
226
+ def colorize(str, color, style=nil)
227
+ codes = [FG_COLORS[color] || FG_COLORS[:default]]
228
+ if style
229
+ codes << EFFECTS[style] || EFFECTS[:nothing]
230
+ end
231
+ if str.is_a?(String)
232
+ ["\033[%sm" % codes.join(';'), str, NO_COLOR].join
233
+ elsif str.is_a?(Array)
234
+ str.map { |s|
235
+ ["\033[%sm" % codes.join(';'), s, NO_COLOR].join
236
+ }
237
+ end
238
+ end
239
+
240
+ private
241
+
242
+ def prefix_str(host, title)
243
+ prefix = ""
244
+ prefix += "[" + host + "] " if host
245
+ prefix += title + " " if title
246
+ prefix += " " if !prefix.empty? && prefix !~ / $/
247
+ return prefix
248
+ end
249
+
250
+ EFFECTS = {
251
+ :reset => 0, :nothing => 0,
252
+ :bright => 1, :bold => 1,
253
+ :underline => 4,
254
+ :inverse => 7, :swap => 7,
255
+ }
256
+ NO_COLOR = "\033[0m"
257
+ FG_COLORS = {
258
+ :black => 30,
259
+ :red => 31,
260
+ :green => 32,
261
+ :yellow => 33,
262
+ :blue => 34,
263
+ :magenta => 35,
264
+ :cyan => 36,
265
+ :white => 37,
266
+ :default => 39,
267
+ }
268
+ BG_COLORS = {
269
+ :black => 40,
270
+ :red => 41,
271
+ :green => 42,
272
+ :yellow => 43,
273
+ :blue => 44,
274
+ :magenta => 45,
275
+ :cyan => 46,
276
+ :white => 47,
277
+ :default => 49,
278
+ }
279
+
173
280
  end
174
- end
281
+ end
282
+