#
# Copyright:: Copyright (c) 2018, Noah Kantrowitz
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative"../knife"classChefclassKnifeclassConfigList<Knifebanner"knife config list (options)"TABLE_HEADER||=[" Profile","Client","Key","Server"].freezedepsdorequire"chef/workstation_config_loader"unlessdefined?(Chef::WorkstationConfigLoader)require"tty-screen"unlessdefined?(TTY::Screen)require"tty-table"unlessdefined?(TTY::Table)endoption:ignore_knife_rb,short: "-i",long: "--ignore-knife-rb",description: "Ignore the current config.rb/knife.rb configuration.",default: falsedefconfigure_chefapply_computed_configenddefruncredentials_data=self.class.config_loader.parse_credentials_fileifcredentials_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")exit1endcurrent_profile=self.class.config_loader.credentials_profile(config[:profile])profiles=credentials_data.keys.mapdo|profile|ifconfig[: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.resetwcl=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],}endend# Try to reset the config.
unlessconfig[:ignore_knife_rb]Chef::Config.resetapply_computed_configendifui.interchange?# Machine-readable output.
ui.output(profiles)else# Table output.
ui.output(render_table(profiles))endendprivatedefrender_table(profiles,padding: 1)rows=[]# Render the data to a 2D array that will be used for the table.
profiles.eachdo|profile|# Replace the home dir in the client key path with ~.
profile[:client_key]=profile[:client_key].to_s.gsub(/^#{Regexp.escape(Dir.home)}/,"~")ifprofile[:client_key]profile[:profile]="#{profile[:active]?"*":" "}#{profile[:profile]}"rows<<profile.values_at(:profile,:client_name,:client_key,:server_url)endtable=TTY::Table.new(header: TABLE_HEADER,rows: rows)# Rotate the table to vertical if the screen width is less than table width.
iftable.width>TTY::Screen.widthtable.orientation=:verticaltable.rotate# Add a new line after each profile record.
table.renderdo|renderer|renderer.borderdoseparator->(row){(row+1)%TABLE_HEADER.size==0}end# Remove the leading space added of the first column.
renderer.filter=Proc.newdo|val,row_index,col_index|ifcol_index==1||(row_index)%TABLE_HEADER.size==0val.stripelsevalendendendelsetable.renderdo|renderer|renderer.borderdomid"-"endrenderer.padding=[0,padding,0,0]# pad right with 2 characters
endendendendendend