Module: Kitchen::Util
- Defined in:
- lib/kitchen/util.rb
Overview
Stateless utility methods used in different contexts. Essentially a mini PassiveSupport library.
Class Attribute Summary collapse
-
.mutex_chdir ⇒ Mutex
A mutex used to serialize the process-global Dir.chdir.
Class Method Summary collapse
-
.camel_case(a_string) ⇒ String
Returns a CamelCase version of a snake_case string.
-
.command_exists?(cmd) ⇒ Boolean
Check if a cmd exists on the PATH.
-
.duration(total) ⇒ String
Returns a formatted string representing a duration in seconds.
-
.from_logger_level(const) ⇒ Symbol
Returns the symbol representation of a logging level for a given standard library Logger::Severity constant.
-
.list_directory(path, include_dot: false, recurse: false) ⇒ Object
Lists the contents of the given directory.
-
.mask_values(string_to_mask, keys) ⇒ String
Returns a string with masked values for specified parameters.
-
.outdent(string) ⇒ String
Returns a copy of a string with each line outdented by the indentation level of its first line.
-
.outdent!(string) ⇒ String
Modifies the given string to strip leading whitespace on each line, the amount which is calculated by using the first line of text.
-
.safe_glob(path, pattern, *flags) ⇒ Object
Similar to Dir.glob.
-
.shell_helpers ⇒ String
Returns a set of Bourne Shell (AKA /bin/sh) compatible helper functions.
-
.snake_case(a_string) ⇒ String
Returns a snake_case version of a CamelCase string.
-
.stringified_hash(obj) ⇒ Object
Returns a new Hash with all key values coerced to strings.
-
.symbolized_hash(obj) ⇒ Object
Returns a new Hash with all key values coerced to symbols.
-
.to_logger_level(symbol) ⇒ Integer
Returns the standard library Logger level constants for a given symbol representation.
-
.wrap_command(cmd) ⇒ String
Generates a command (or series of commands) wrapped so that it can be invoked on a remote instance or locally.
Class Attribute Details
.mutex_chdir ⇒ Mutex
Returns a mutex used to serialize the process-global Dir.chdir.
29 30 31 |
# File 'lib/kitchen/util.rb', line 29 def mutex_chdir @mutex_chdir end |
Class Method Details
.camel_case(a_string) ⇒ String
Returns a CamelCase version of a snake_case string.
255 256 257 |
# File 'lib/kitchen/util.rb', line 255 def self.camel_case(a_string) Thor::Util.camel_case(a_string) end |
.command_exists?(cmd) ⇒ Boolean
Check if a cmd exists on the PATH
268 269 270 271 272 273 274 275 |
# File 'lib/kitchen/util.rb', line 268 def self.command_exists?(cmd) paths = ENV["PATH"].split(File::PATH_SEPARATOR) + [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ] paths.each do |path| filename = File.join(path, cmd) return filename if File.executable?(filename) end false end |
.duration(total) ⇒ String
Returns a formatted string representing a duration in seconds.
119 120 121 122 123 124 |
# File 'lib/kitchen/util.rb', line 119 def self.duration(total) total = 0 if total.nil? minutes = (total / 60).to_i seconds = (total - (minutes * 60)) format("(%dm%.2fs)", minutes, seconds) end |
.from_logger_level(const) ⇒ Symbol
Returns the symbol representation of a logging level for a given standard library Logger::Severity constant.
58 59 60 61 62 63 64 65 66 |
# File 'lib/kitchen/util.rb', line 58 def self.from_logger_level(const) case const when Logger::DEBUG then :debug when Logger::INFO then :info when Logger::WARN then :warn when Logger::ERROR then :error else :fatal end end |
.list_directory(path, include_dot: false, recurse: false) ⇒ Object
You should prefer this method to using Dir.glob directly. The reason is
Dir.chdir is applied to the process, thus it is not thread-safe
Lists the contents of the given directory. path will be prepended to the list returned. '.' and '..' are never returned.
because Dir.glob behaves strangely on Windows. It won't accept '' and doesn't like fake directories (C:Documents and Settings) It also does not do any sort of error checking, so things one would expect to fail just return an empty list
and must be synchronized.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/kitchen/util.rb', line 203 def self.list_directory(path, include_dot: false, recurse: false) # Things (such as tests) are relying on this to not blow up if # the directory does not exist return [] unless Dir.exist?(path) mutex_chdir.synchronize do Dir.chdir(path) do glob_pattern = if recurse "**/*" else "*" end flags = if include_dot [File::FNM_DOTMATCH] else [] end Dir.glob(glob_pattern, *flags) .reject { |f| [".", ".."].include?(f) } .map { |f| File.join(path, f) } end end end |
.mask_values(string_to_mask, keys) ⇒ String
Returns a string with masked values for specified parameters.
107 108 109 110 111 112 113 |
# File 'lib/kitchen/util.rb', line 107 def self.mask_values(string_to_mask, keys) masked_string = string_to_mask keys.each do |key| masked_string.gsub!(/:#{key}=>"([^"]*)"/, %{:#{key}=>"******"}) end masked_string end |
.outdent(string) ⇒ String
Returns a copy of a string with each line outdented by the indentation level of its first line.
Prefer this over outdent! when the input may be a string literal: Ruby 4 freezes literals, and mutating one raises a FrozenError.
172 173 174 |
# File 'lib/kitchen/util.rb', line 172 def self.outdent(string) string.gsub(/^ {#{string.index(/[^ ]/)}}/, "") end |
.outdent!(string) ⇒ String
Modifies the given string to strip leading whitespace on each line, the amount which is calculated by using the first line of text.
156 157 158 |
# File 'lib/kitchen/util.rb', line 156 def self.outdent!(string) string.gsub!(/^ {#{string.index(/[^ ]/)}}/, "") end |
.safe_glob(path, pattern, *flags) ⇒ Object
Dir.chdir is applied to the process, thus it is not thread-safe
Similar to Dir.glob.
The difference is this function forces you to specify where to glob from. You should glob from the path closest to what you want. The reason for this is because if you have symlinks on windows of any kind, Dir.glob will not traverse them.
and must be synchronized.
241 242 243 244 245 246 247 248 249 |
# File 'lib/kitchen/util.rb', line 241 def self.safe_glob(path, pattern, *flags) return [] unless Dir.exist?(path) mutex_chdir.synchronize do Dir.chdir(path) do Dir.glob(pattern, *flags).map { |f| File.join(path, f) } end end end |
.shell_helpers ⇒ String
Returns a set of Bourne Shell (AKA /bin/sh) compatible helper functions. This function is usually called inline in a string that will be executed remotely on a test instance.
181 182 183 184 185 |
# File 'lib/kitchen/util.rb', line 181 def self.shell_helpers File.read(File.join( File.dirname(__FILE__), %w{.. .. support download_helpers.sh} )) end |
.snake_case(a_string) ⇒ String
Returns a snake_case version of a CamelCase string.
263 264 265 |
# File 'lib/kitchen/util.rb', line 263 def self.snake_case(a_string) Thor::Util.snake_case(a_string) end |
.stringified_hash(obj) ⇒ Object
Returns a new Hash with all key values coerced to strings. All keys within a Hash are coerced by calling #to_s and hashes with arrays and other hashes are traversed.
92 93 94 95 96 97 98 99 100 |
# File 'lib/kitchen/util.rb', line 92 def self.stringified_hash(obj) if obj.is_a?(Hash) obj.inject({}) { |h, (k, v)| h[k.to_s] = stringified_hash(v); h } elsif obj.is_a?(Array) obj.inject([]) { |a, e| a << stringified_hash(e); a } else obj end end |
.symbolized_hash(obj) ⇒ Object
Returns a new Hash with all key values coerced to symbols. All keys within a Hash are coerced by calling #to_sym and hashes within arrays and other hashes are traversed.
75 76 77 78 79 80 81 82 83 |
# File 'lib/kitchen/util.rb', line 75 def self.symbolized_hash(obj) if obj.is_a?(Hash) obj.inject({}) { |h, (k, v)| h[k.to_sym] = symbolized_hash(v); h } elsif obj.is_a?(Array) obj.inject([]) { |a, e| a << symbolized_hash(e); a } else obj end end |
.to_logger_level(symbol) ⇒ Integer
Returns the standard library Logger level constants for a given symbol representation.
45 46 47 48 49 |
# File 'lib/kitchen/util.rb', line 45 def self.to_logger_level(symbol) return nil unless %i{debug info warn error fatal}.include?(symbol) Logger.const_get(symbol.to_s.upcase) end |
.wrap_command(cmd) ⇒ String
Generates a command (or series of commands) wrapped so that it can be invoked on a remote instance or locally.
This method uses the Bourne shell (/bin/sh) to maximize the chance of cross platform portability on Unixlike systems.
134 135 136 137 138 139 140 |
# File 'lib/kitchen/util.rb', line 134 def self.wrap_command(cmd) cmd = "false" if cmd.nil? cmd = "true" if cmd.to_s.empty? cmd = cmd.sub(/\n\Z/, "") if /\n\Z/.match?(cmd) "sh -c '\n#{cmd}\n'" end |