diff options
author | Tim Smith <tsmith@chef.io> | 2018-07-13 10:37:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-13 10:37:34 -0700 |
commit | d99bc319e244e4d4fac57bc1853ea82f8b97c0e9 (patch) | |
tree | 77eac01f6baac6486308a30c8c3982f03309fb39 /lib/chef/knife | |
parent | 8baff8ae8f6dc0e88c1a467566b1ac595ceef267 (diff) | |
parent | 6fb425078b5986998c37450445f5b3ded61e02ac (diff) | |
download | chef-d99bc319e244e4d4fac57bc1853ea82f8b97c0e9.tar.gz |
Merge pull request #7455 from coderanger/config-commands
Add knife config get/use-profile commands
Diffstat (limited to 'lib/chef/knife')
-rw-r--r-- | lib/chef/knife/config_get_profile.rb | 37 | ||||
-rw-r--r-- | lib/chef/knife/config_list_profiles.rb | 121 | ||||
-rw-r--r-- | lib/chef/knife/config_use_profile.rb | 50 | ||||
-rw-r--r-- | lib/chef/knife/core/subcommand_loader.rb | 3 |
4 files changed, 210 insertions, 1 deletions
diff --git a/lib/chef/knife/config_get_profile.rb b/lib/chef/knife/config_get_profile.rb new file mode 100644 index 0000000000..309b7f81e8 --- /dev/null +++ b/lib/chef/knife/config_get_profile.rb @@ -0,0 +1,37 @@ +# +# 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 "chef/knife" + +class Chef + class Knife + class ConfigGetProfile < Knife + banner "knife config get-profile" + + # Disable normal config loading since this shouldn't fail if the profile + # doesn't exist of the config is otherwise corrupted. + def configure_chef + apply_computed_config + end + + def run + ui.msg(self.class.config_loader.credentials_profile(config[:profile])) + end + + end + end +end diff --git a/lib/chef/knife/config_list_profiles.rb b/lib/chef/knife/config_list_profiles.rb new file mode 100644 index 0000000000..16b0c5df27 --- /dev/null +++ b/lib/chef/knife/config_list_profiles.rb @@ -0,0 +1,121 @@ +# +# 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 "chef/knife" +require "chef/workstation_config_loader" + +class Chef + class Knife + class ConfigListProfiles < Knife + banner "knife config list-profiles" + + option :ignore_knife_rb, + short: "-i", + long: "--ignore-knife-rb", + description: "Ignore the current knife.rb configuration", + default: false + + 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 + + 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 + + end + end +end diff --git a/lib/chef/knife/config_use_profile.rb b/lib/chef/knife/config_use_profile.rb new file mode 100644 index 0000000000..515c4a5336 --- /dev/null +++ b/lib/chef/knife/config_use_profile.rb @@ -0,0 +1,50 @@ +# +# 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 "fileutils" + +require "chef/knife" + +class Chef + class Knife + class ConfigUseProfile < Knife + banner "knife config use-profile PROFILE" + + # Disable normal config loading since this shouldn't fail if the profile + # doesn't exist of the config is otherwise corrupted. + def configure_chef + apply_computed_config + end + + def run + context_file = ChefConfig::PathHelper.home(".chef", "context").freeze + profile = @name_args[0]&.strip + if profile && !profile.empty? + # Ensure the .chef/ folder exists. + FileUtils.mkdir_p(File.dirname(context_file)) + IO.write(context_file, "#{profile}\n") + ui.msg("Set default profile to #{profile}") + else + show_usage + ui.fatal("You must specify a profile") + exit 1 + end + end + + end + end +end diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb index 026967d6ec..fb3723de50 100644 --- a/lib/chef/knife/core/subcommand_loader.rb +++ b/lib/chef/knife/core/subcommand_loader.rb @@ -139,9 +139,10 @@ class Chef # hash composed of the given words joined by the separator. # def find_longest_key(hash, words, sep = "_") + words = words.dup match = nil until match || words.empty? - candidate = words.join(sep) + candidate = words.join(sep).tr("-", "_") if hash.key?(candidate) match = candidate else |