class Chef::Knife::ConfigListProfiles

Public Instance Methods

run() click to toggle source
# File lib/chef/knife/config_list_profiles.rb, line 32
def run
  credentials_data = self.class.config_loader.parse_credentials_file
  if credentials_data.nil? || credentials_data.empty?
    # Should this just show the ambient knife.rb config as "default" instead?
    ui.fatal("No profiles found, #{self.class.config_loader.credentials_file_path} does not exist or is empty")
    exit 1
  end

  current_profile = self.class.config_loader.credentials_profile(config[:profile])
  profiles = credentials_data.keys.map do |profile|
    if config[:ignore_knife_rb]
      # Don't do any fancy loading nonsense, just the raw data.
      profile_data = credentials_data[profile]
      {
        profile: profile,
        active: profile == current_profile,
        client_name: profile_data["client_name"] || profile_data["node_name"],
        client_key: profile_data["client_key"],
        server_url: profile_data["chef_server_url"],
      }
    else
      # Fancy loading nonsense so we get what the actual config would be.
      # Note that this modifies the global config, after this, all bets are
      # off as to whats in the config.
      Chef::Config.reset
      wcl = Chef::WorkstationConfigLoader.new(nil, Chef::Log, profile: profile)
      wcl.load
      {
        profile: profile,
        active: profile == current_profile,
        client_name: Chef::Config[:node_name],
        client_key: Chef::Config[:client_key],
        server_url: Chef::Config[:chef_server_url],
      }
    end
  end

  # Try to reset the config.
  unless config[:ignore_knife_rb]
    Chef::Config.reset
    Chef::WorkstationConfigLoader.new(config[:config_file], Chef::Log, profile: config[:profile]).load
    apply_computed_config
  end

  if ui.interchange?
    # Machine-readable output.
    ui.output(profiles)
  else
    # Table output.
    ui.output(render_table(profiles))
  end
end

Private Instance Methods

render_table(profiles, padding: 2) click to toggle source
# File lib/chef/knife/config_list_profiles.rb, line 87
def render_table(profiles, padding: 2)
  # Replace the home dir in the client key path with ~.
  profiles.each do |profile|
    profile[:client_key] = profile[:client_key].to_s.gsub(/^#{Regexp.escape(Dir.home)}/, "~") if profile[:client_key]
  end
  # Render the data to a 2D array that will be used for the table.
  table_data = [["", "Profile", "Client", "Key", "Server"]] + profiles.map do |profile|
    [profile[:active] ? "*" : ""] + profile.values_at(:profile, :client_name, :client_key, :server_url).map(&:to_s)
  end
  # Compute column widths.
  column_widths = Array.new(table_data.first.length) do |i|
    table_data.map { |row| row[i].length + padding }.max
  end
  # Special case, the first col gets no padding (because indicator) and last
  # get no padding because last.
  column_widths[0] -= padding
  column_widths[-1] -= padding
  # Build the format string for each row.
  format_string = column_widths.map { |w| "%-#{w}.#{w}s" }.join("")
  format_string << "\n"
  # Print the header row and a separator.
  table = ui.color(format_string % table_data.first, :green)
  table << "-" * column_widths.sum
  table << "\n"
  # Print the rest of the table.
  table_data.drop(1).each do |row|
    table << format_string % row
  end
  # Trim the last newline because ui.output adds one.
  table.chomp!
end