Class: Bolt::Outputter::Human

Inherits:
Bolt::Outputter show all
Defined in:
lib/bolt/outputter/human.rb

Constant Summary collapse

COLORS =
{ red: "31",
green: "32",
yellow: "33" }.freeze

Instance Method Summary collapse

Methods inherited from Bolt::Outputter

for_format, #initialize, #print_message

Constructor Details

This class inherits a constructor from Bolt::Outputter

Instance Method Details

#colorize(color, string) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/bolt/outputter/human.rb', line 15

def colorize(color, string)
  if @color && @stream.isatty
    "\033[#{COLORS[color]}m#{string}\033[0m"
  else
    string
  end
end

#fatal_error(err) ⇒ Object



251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/bolt/outputter/human.rb', line 251

def fatal_error(err)
  @stream.puts(colorize(:red, err.message))
  if err.is_a? Bolt::RunFailure
    @stream.puts ::JSON.pretty_generate(err.result_set)
  end

  if @trace && err.backtrace
    err.backtrace.each do |line|
      @stream.puts(colorize(:red, "\t#{line}"))
    end
  end
end

#indent(indent, string) ⇒ Object



23
24
25
26
# File 'lib/bolt/outputter/human.rb', line 23

def indent(indent, string)
  indent = ' ' * indent
  string.gsub(/^/, indent.to_s)
end

Parameters:

  • apply_result (Bolt::ResultSet)

    A ResultSet object representing the result of a ‘bolt apply`



223
224
225
226
# File 'lib/bolt/outputter/human.rb', line 223

def print_apply_result(apply_result)
  apply_result.each { |result| print_result(result) }
  print_summary(apply_result)
end


32
33
34
35
36
37
38
39
# File 'lib/bolt/outputter/human.rb', line 32

def print_event(event)
  case event[:type]
  when :node_start
    print_start(event[:target])
  when :node_result
    print_result(event[:result])
  end
end


13
# File 'lib/bolt/outputter/human.rb', line 13

def print_head; end


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/bolt/outputter/human.rb', line 194

def print_module_list(module_list)
  module_list.each do |path, modules|
    if (mod = modules.find { |m| m[:internal_module_group] })
      @stream.puts(mod[:internal_module_group])
    else
      @stream.puts(path)
    end

    if modules.empty?
      @stream.puts('(no modules installed)')
    else
      module_info = modules.map do |m|
        version = if m[:version].nil?
                    m[:internal_module_group].nil? ? '(no metadata)' : '(built-in)'
                  else
                    m[:version]
                  end

        [m[:name], version]
      end

      print_table(module_info)
    end

    @stream.write("\n")
  end
end

Parameters:

  • plan (Hash)

    A hash representing the plan



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/bolt/outputter/human.rb', line 161

def print_plan_info(plan)
  # Building lots of strings...
  pretty_params = +""
  plan_info = +""
  usage = +"bolt plan run #{plan['name']}"

  plan['parameters']&.each do |name, p|
    pretty_params << "- #{name}: #{p['type']}\n"
    usage << (p.include?('default_value') ? " [#{name}=<value>]" : " #{name}=<value>")
  end

  plan_info << "\n#{plan['name']}"
  plan_info << "\n\n"
  plan_info << "USAGE:\n#{usage}\n\n"
  plan_info << "PARAMETERS:\n#{pretty_params}\n" if plan['parameters']
  plan_info << "MODULE:\n"

  path = plan['module']
  plan_info << if path.start_with?(Bolt::PAL::MODULES_PATH)
                 "built-in module"
               else
                 path
               end
  @stream.puts(plan_info)
end

Parameters:



229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/bolt/outputter/human.rb', line 229

def print_plan_result(plan_result)
  value = plan_result.value
  if value.nil?
    @stream.puts("Plan completed successfully with no result")
  elsif value.is_a? Bolt::ApplyFailure
    @stream.puts(colorize(:red, value.message))
  elsif value.is_a? Bolt::ResultSet
    value.each { |result| print_result(result) }
    print_summary(value)
  else
    @stream.puts(::JSON.pretty_generate(plan_result, quirks_mode: true))
  end
end


187
188
189
190
191
192
# File 'lib/bolt/outputter/human.rb', line 187

def print_plans(plans, modulepath)
  print_table(plans)
  print_message("\nMODULEPATH:\n#{modulepath.join(':')}\n"\
                  "\nUse `bolt plan show <plan-name>` to view "\
                  "details and parameters for a specific plan.")
end


243
244
245
246
247
248
249
# File 'lib/bolt/outputter/human.rb', line 243

def print_puppetfile_result(success, puppetfile, moduledir)
  if success
    @stream.puts("Successfully synced modules from #{puppetfile} to #{moduledir}")
  else
    @stream.puts(colorize(:red, "Failed to sync modules from #{puppetfile} to #{moduledir}"))
  end
end


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/bolt/outputter/human.rb', line 45

def print_result(result)
  if result.success?
    @stream.puts(colorize(:green, "Finished on #{result.target.host}:"))
  else
    @stream.puts(colorize(:red, "Failed on #{result.target.host}:"))
  end

  if result.error_hash
    @stream.puts(colorize(:red, remove_trail(indent(2, result.error_hash['msg']))))
  end

  if result.message
    @stream.puts(remove_trail(indent(2, result.message)))
  end

  # There is more information to output
  if result.generic_value
    # Use special handling if the result looks like a command or script result
    if result.generic_value.keys == %w[stdout stderr exit_code]
      unless result['stdout'].strip.empty?
        @stream.puts(indent(2, "STDOUT:"))
        @stream.puts(indent(4, result['stdout']))
      end
      unless result['stderr'].strip.empty?
        @stream.puts(indent(2, "STDERR:"))
        @stream.puts(indent(4, result['stderr']))
      end
    else
      @stream.puts(indent(2, ::JSON.pretty_generate(result.generic_value)))
    end
  end
end


41
42
43
# File 'lib/bolt/outputter/human.rb', line 41

def print_start(target)
  @stream.puts(colorize(:green, "Started on #{target.host}..."))
end


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/bolt/outputter/human.rb', line 78

def print_summary(results, elapsed_time = nil)
  ok_set = results.ok_set
  unless ok_set.empty?
    @stream.puts format('Successful on %<size>d node%<plural>s: %<names>s',
                        size: ok_set.size,
                        plural: ok_set.size == 1 ? '' : 's',
                        names: ok_set.names.join(','))
  end

  error_set = results.error_set
  unless error_set.empty?
    @stream.puts colorize(:red,
                          format('Failed on %<size>d node%<plural>s: %<names>s',
                                 size: error_set.size,
                                 plural: error_set.size == 1 ? '' : 's',
                                 names: error_set.names.join(',')))
  end

  total_msg = format('Ran on %<size>d node%<plural>s',
                     size: results.size,
                     plural: results.size == 1 ? '' : 's')
  total_msg += format(' in %<elapsed>.2f seconds', elapsed: elapsed_time) unless elapsed_time.nil?
  @stream.puts total_msg
end


103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/bolt/outputter/human.rb', line 103

def print_table(results)
  @stream.puts Terminal::Table.new(
    rows: results,
    style: {
      border_x: '',
      border_y: '',
      border_i: '',
      padding_left: 0,
      padding_right: 3,
      border_top: false,
      border_bottom: false
    }
  )
end

Parameters:

  • task (Hash)

    A hash representing the task



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/bolt/outputter/human.rb', line 126

def print_task_info(task)
  # Building lots of strings...
  pretty_params = +""
  task_info = +""
  usage = +"bolt task run --nodes <node-name> #{task['name']}"

  task['metadata']['parameters']&.each do |k, v|
    pretty_params << "- #{k}: #{v['type'] || 'Any'}\n"
    pretty_params << "    #{v['description']}\n" if v['description']
    usage << if v['type'].is_a?(Puppet::Pops::Types::POptionalType)
               " [#{k}=<value>]"
             else
               " #{k}=<value>"
             end
  end

  usage << " [--noop]" if task['metadata']['supports_noop']

  task_info << "\n#{task['name']}"
  task_info << " - #{task['metadata']['description']}" if task['metadata']['description']
  task_info << "\n\n"
  task_info << "USAGE:\n#{usage}\n\n"
  task_info << "PARAMETERS:\n#{pretty_params}\n" unless pretty_params.empty?
  task_info << "MODULE:\n"

  path = task['files'][0]['path'].chomp("/tasks/#{task['files'][0]['name']}")
  task_info << if path.start_with?(Bolt::PAL::MODULES_PATH)
                 "built-in module"
               else
                 path
               end
  @stream.puts(task_info)
end


118
119
120
121
122
123
# File 'lib/bolt/outputter/human.rb', line 118

def print_tasks(tasks, modulepath)
  print_table(tasks)
  print_message("\nMODULEPATH:\n#{modulepath.join(':')}\n"\
                  "\nUse `bolt task show <task-name>` to view "\
                  "details and parameters for a specific task.")
end

#remove_trail(string) ⇒ Object



28
29
30
# File 'lib/bolt/outputter/human.rb', line 28

def remove_trail(string)
  string.sub(/\s\z/, '')
end