class Chef::Knife::UI

The User Interaction class used by knife.

Attributes

config[R]
presenter[R]
stderr[R]
stdin[R]
stdout[R]

Public Class Methods

new(stdout, stderr, stdin, config) click to toggle source
# File lib/chef/knife/core/ui.rb, line 45
def initialize(stdout, stderr, stdin, config)
  @stdout, @stderr, @stdin, @config = stdout, stderr, stdin, config
  @presenter = Chef::Knife::Core::GenericPresenter.new(self, config)
end

Public Instance Methods

ask(*args, &block) click to toggle source
# File lib/chef/knife/core/ui.rb, line 147
def ask(*args, &block)
  highline.ask(*args, &block)
end
ask_question(question, opts = {}) click to toggle source
# File lib/chef/knife/core/ui.rb, line 168
def ask_question(question, opts = {})
  question += "[#{opts[:default]}] " if opts[:default]

  if opts[:default] && config[:defaults]
    opts[:default]
  else
    stdout.print question
    a = stdin.readline.strip

    if opts[:default]
      a.empty? ? opts[:default] : a
    else
      a
    end
  end
end
color(string, *colors) click to toggle source
# File lib/chef/knife/core/ui.rb, line 132
def color(string, *colors)
  if color?
    highline.color(string, *colors)
  else
    string
  end
end
color?() click to toggle source

Should colored output be used? For output to a terminal, this is determined by the value of `config`. When output is not to a terminal, colored output is never used

# File lib/chef/knife/core/ui.rb, line 143
def color?
  Chef::Config[:color] && stdout.tty?
end
confirm(question, append_instructions = true, default_choice = nil) click to toggle source

Not the ideal signature for a function but we need to stick with this for now until we get a chance to break our API in Chef 12.

question => Question to print before asking for confirmation append_instructions => Should print '? (Y/N)' as instructions default_choice => Set to true for 'Y', and false for 'N' as default answer

# File lib/chef/knife/core/ui.rb, line 300
def confirm(question, append_instructions = true, default_choice = nil)
  unless confirm_without_exit(question, append_instructions, default_choice)
    exit 3
  end
  true
end
confirm_without_exit(question, append_instructions = true, default_choice = nil) click to toggle source

See confirm method for argument information

# File lib/chef/knife/core/ui.rb, line 262
def confirm_without_exit(question, append_instructions = true, default_choice = nil)
  return true if config[:yes]

  stdout.print question
  stdout.print confirmation_instructions(default_choice) if append_instructions

  answer = stdin.readline
  answer.chomp!

  case answer
  when "Y", "y"
    true
  when "N", "n"
    msg("You said no, so I'm done here.")
    false
  when ""
    unless default_choice.nil?
      default_choice
    else
      msg("I have no idea what to do with '#{answer}'")
      msg("Just say Y or N, please.")
      confirm_without_exit(question, append_instructions, default_choice)
    end
  else
    msg("I have no idea what to do with '#{answer}'")
    msg("Just say Y or N, please.")
    confirm_without_exit(question, append_instructions, default_choice)
  end
end
confirmation_instructions(default_choice) click to toggle source
# File lib/chef/knife/core/ui.rb, line 250
def confirmation_instructions(default_choice)
  case default_choice
  when true
    "? (Y/n) "
  when false
    "? (y/N) "
  else
    "? (Y/N) "
  end
end
debug(message) click to toggle source

Print a Debug

@param message [String] the text string

# File lib/chef/knife/core/ui.rb, line 107
def debug(message)
  log("#{color('DEBUG:', :blue, :bold)} #{message}")
end
edit_data(data, parse_output = true, object_class: nil) click to toggle source
# File lib/chef/knife/core/ui.rb, line 200
def edit_data(data, parse_output = true, object_class: nil)
  output = Chef::JSONCompat.to_json_pretty(data)
  if !config[:disable_editing]
    Tempfile.open([ "knife-edit-", ".json" ]) do |tf|
      tf.sync = true
      tf.puts output
      tf.close
      raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup.html for details." unless system("#{config[:editor]} #{tf.path}")

      output = IO.read(tf.path)
    end
  end

  if parse_output
    if object_class.nil?
      raise ArgumentError, "Please pass in the object class to hydrate or use #edit_hash"
    else
      object_class.from_hash(Chef::JSONCompat.parse(output))
    end
  else
    output
  end
end
edit_hash(hash) click to toggle source

Hash -> Hash Works the same as edit_data but returns a hash rather than a JSON string/Fully inflated object

# File lib/chef/knife/core/ui.rb, line 195
def edit_hash(hash)
  raw = edit_data(hash, false)
  Chef::JSONCompat.parse(raw)
end
edit_object(klass, name) click to toggle source
# File lib/chef/knife/core/ui.rb, line 224
def edit_object(klass, name)
  object = klass.load(name)

  output = edit_data(object, object_class: klass)

  # Only make the save if the user changed the object.
  #
  # Output JSON for the original (object) and edited (output), then parse
  # them without reconstituting the objects into real classes
  # (create_additions=false). Then, compare the resulting simple objects,
  # which will be Array/Hash/String/etc.
  #
  # We wouldn't have to do these shenanigans if all the editable objects
  # implemented to_hash, or if to_json against a hash returned a string
  # with stable key order.
  object_parsed_again = Chef::JSONCompat.parse(Chef::JSONCompat.to_json(object))
  output_parsed_again = Chef::JSONCompat.parse(Chef::JSONCompat.to_json(output))
  if object_parsed_again != output_parsed_again
    output.save
    msg("Saved #{output}")
  else
    msg("Object unchanged, not saving")
  end
  output(format_for_display(object)) if config[:print_after]
end
err(message)
Alias for: log
error(message) click to toggle source

Print an error message

@param message [String] the text string

# File lib/chef/knife/core/ui.rb, line 121
def error(message)
  log("#{color('ERROR:', :red, :bold)} #{message}")
end
fatal(message) click to toggle source

Print a message describing a fatal error.

@param message [String] the text string

# File lib/chef/knife/core/ui.rb, line 128
def fatal(message)
  log("#{color('FATAL:', :red, :bold)} #{message}")
end
highline() click to toggle source
# File lib/chef/knife/core/ui.rb, line 57
def highline
  @highline ||= begin
    require "highline"
    HighLine.new
  end
end
info(message)
Alias for: log
interchange?() click to toggle source

Determines if the output format is a data interchange format, i.e., JSON or YAML

# File lib/chef/knife/core/ui.rb, line 164
def interchange?
  @presenter.interchange?
end
list(*args) click to toggle source
# File lib/chef/knife/core/ui.rb, line 151
def list(*args)
  highline.list(*args)
end
log(message) click to toggle source

Prints a msg to stderr. Used for info, warn, error, and fatal.

@param message [String] the text string

# File lib/chef/knife/core/ui.rb, line 78
def log(message)
  lines = message.split("\n")
  first_line = lines.shift
  stderr.puts first_line
  # If the message is multiple lines,
  # indent subsequent lines to align with the
  # log type prefix ("ERROR: ", etc)
  unless lines.empty?
    prefix, = first_line.split(":", 2)
    return if prefix.nil?
    prefix_len = prefix.length
    prefix_len -= 9 if color? # prefix includes 9 bytes of color escape sequences
    prefix_len += 2 # include room to align to the ": " following PREFIX
    padding = " " * prefix_len
    lines.each do |line|
      stderr.puts "#{padding}#{line}"
    end
  end
rescue Errno::EPIPE => e
  raise e if @config[:verbosity] >= 2
  exit 0
end
Also aliased as: info, err
msg(message) click to toggle source

Prints a message to stdout. Aliased as info for compatibility with the logger API.

@param message [String] the text string

# File lib/chef/knife/core/ui.rb, line 68
def msg(message)
  stdout.puts message
rescue Errno::EPIPE => e
  raise e if @config[:verbosity] >= 2
  exit 0
end
output(data) click to toggle source

Formats data using the configured presenter and outputs the result via msg. Formatting can be customized by configuring a different presenter. See use_presenter

# File lib/chef/knife/core/ui.rb, line 158
def output(data)
  msg @presenter.format(data)
end
pretty_print(data) click to toggle source
# File lib/chef/knife/core/ui.rb, line 185
def pretty_print(data)
  stdout.puts data
rescue Errno::EPIPE => e
  raise e if @config[:verbosity] >= 2
  exit 0
end
use_presenter(presenter_class) click to toggle source

Creates a new presenter_class object and uses it to format structured data for display. By default, a Chef::Knife::Core::GenericPresenter object is used.

# File lib/chef/knife/core/ui.rb, line 53
def use_presenter(presenter_class)
  @presenter = presenter_class.new(self, config)
end
warn(message) click to toggle source

Print a warning message

@param message [String] the text string

# File lib/chef/knife/core/ui.rb, line 114
def warn(message)
  log("#{color('WARNING:', :yellow, :bold)} #{message}")
end