Module: Kennel::Utils

Defined in:
lib/kennel/utils.rb

Defined Under Namespace

Classes: TeeIO

Constant Summary collapse

COLORS =
{ red: 31, green: 32, yellow: 33, cyan: 36, magenta: 35, default: 0 }.freeze

Class Method Summary collapse

Class Method Details

.all_keys(items) ⇒ Object



146
147
148
149
150
151
152
# File 'lib/kennel/utils.rb', line 146

def all_keys(items)
  case items
  when Hash then items.keys + items.values.flat_map { |v| all_keys(v) }
  when Array then items.flat_map { |i| all_keys(i) }
  else []
  end
end

.ask(question) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/kennel/utils.rb', line 45

def ask(question)
  Kennel.err.printf color(:red, "#{question} -  press 'y' to continue: ", force: true)
  begin
    STDIN.gets.chomp == "y"
  rescue Interrupt # do not show a backtrace if user decides to Ctrl+C here
    Kennel.err.print "\n"
    exit 1
  end
end

.capture_sh(command) ⇒ Object



98
99
100
101
102
# File 'lib/kennel/utils.rb', line 98

def capture_sh(command)
  result = `#{command} 2>&1`
  raise "Command failed:\n#{command}\n#{result}" unless $CHILD_STATUS.success?
  result
end

.capture_stderrObject



76
77
78
79
80
81
82
83
# File 'lib/kennel/utils.rb', line 76

def capture_stderr
  old = Kennel.err
  Kennel.err = StringIO.new
  yield
  Kennel.err.string
ensure
  Kennel.err = old
end

.capture_stdoutObject



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

def capture_stdout
  old = Kennel.out
  Kennel.out = StringIO.new
  yield
  Kennel.out.string
ensure
  Kennel.out = old
end

.color(color, text, force: false) ⇒ Object



55
56
57
58
59
# File 'lib/kennel/utils.rb', line 55

def color(color, text, force: false)
  return text unless force || Kennel.out.tty?

  "\e[#{COLORS.fetch(color)}m#{text}\e[0m"
end

.inline_resource_metadata(resource, klass) ⇒ Object



154
155
156
157
# File 'lib/kennel/utils.rb', line 154

def (resource, klass)
  resource[:klass] = klass
  resource[:tracking_id] = klass.parse_tracking_id(resource)
end

.natural_order(name) ⇒ Object



132
133
134
# File 'lib/kennel/utils.rb', line 132

def natural_order(name)
  name.split(/(\d+)/).each_with_index.map { |x, i| i.odd? ? x.to_i : x }
end

.parallel(items, max: 10) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/kennel/utils.rb', line 109

def parallel(items, max: 10)
  threads = [items.size, max].min
  work = items.each_with_index.to_a
  done = Array.new(items.size)
  workers = Array.new(threads).map do
    Thread.new do
      loop do
        item, i = work.pop
        break unless i
        done[i] =
          begin
            yield item
          rescue Exception => e # rubocop:disable Lint/RescueException
            work.clear
            e
          end
      end
    end
  end
  workers.each(&:join)
  done.each { |d| raise d if d.is_a?(Exception) }
end

.parameterize(string) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/kennel/utils.rb', line 33

def parameterize(string)
  string
    .downcase
    .gsub(/[^a-z0-9\-_]+/, "-") # remove unsupported
    .gsub(/-{2,}/, "-") # remove duplicates
    .gsub(/^-|-$/, "") # remove leading/trailing
end

.path_to_url(path, subdomain: nil) ⇒ Object



104
105
106
107
# File 'lib/kennel/utils.rb', line 104

def path_to_url(path, subdomain: nil)
  subdomain ||= (ENV["DATADOG_SUBDOMAIN"] || "app")
  "https://#{subdomain}.datadoghq.com#{path}"
end

.presence(value) ⇒ Object



41
42
43
# File 'lib/kennel/utils.rb', line 41

def presence(value)
  value.nil? || value.empty? ? nil : value
end

.retry(*errors, times:) ⇒ Object



136
137
138
139
140
141
142
143
# File 'lib/kennel/utils.rb', line 136

def retry(*errors, times:)
  yield
rescue *errors => e
  times -= 1
  raise if times < 0
  Kennel.err.puts "Error #{e}, #{times} retries left"
  retry
end

.snake_case(string) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/kennel/utils.rb', line 18

def snake_case(string)
  string
    .gsub(/::/, "_") # Foo::Bar -> foo_bar
    .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') # FOOBar -> foo_bar
    .gsub(/([a-z\d])([A-Z])/, '\1_\2') # fooBar -> foo_bar
    .tr("-", "_") # foo-bar -> foo_bar
    .downcase
end

.tee_outputObject



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/kennel/utils.rb', line 85

def tee_output
  old_stdout = Kennel.out
  old_stderr = Kennel.err
  capture = StringIO.new
  Kennel.out = TeeIO.new([capture, Kennel.out])
  Kennel.err = TeeIO.new([capture, Kennel.err])
  yield
  capture.string
ensure
  Kennel.out = old_stdout
  Kennel.err = old_stderr
end

.title_case(string) ⇒ Object

for child projects, not used internally



28
29
30
# File 'lib/kennel/utils.rb', line 28

def title_case(string)
  string.split(/[\s_]/).map(&:capitalize) * " "
end

.truncate_lines(text, to:, warning:) ⇒ Object



61
62
63
64
65
# File 'lib/kennel/utils.rb', line 61

def truncate_lines(text, to:, warning:)
  lines = text.split(/\n/, to + 1)
  lines[-1] = warning if lines.size > to
  lines.join("\n")
end