Class: Chef::Knife::SubcommandLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/chef/knife/core/subcommand_loader.rb,
lib/chef/knife/core/gem_glob_loader.rb,
lib/chef/knife/core/hashed_command_loader.rb

Overview

Public Methods of a Subcommand Loader

load_commands - loads all available subcommands load_command(args) - loads subcommands for the given args list_commands(args) - lists all available subcommands, optionally filtering by category subcommand_files - returns an array of all subcommand files that could be loaded commnad_class_from(args) - returns the subcommand class for the user-requested command

Direct Known Subclasses

GemGlobLoader, HashedCommandLoader

Defined Under Namespace

Classes: GemGlobLoader, HashedCommandLoader

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chef_config_dir) ⇒ SubcommandLoader

Returns a new instance of SubcommandLoader


78
79
80
# File 'lib/chef/knife/core/subcommand_loader.rb', line 78

def initialize(chef_config_dir)
  @chef_config_dir = chef_config_dir
end

Instance Attribute Details

#chef_config_dirObject (readonly)

Returns the value of attribute chef_config_dir


39
40
41
# File 'lib/chef/knife/core/subcommand_loader.rb', line 39

def chef_config_dir
  @chef_config_dir
end

Class Method Details

.autogenerated_manifest?Boolean

Returns:

  • (Boolean)

66
67
68
# File 'lib/chef/knife/core/subcommand_loader.rb', line 66

def self.autogenerated_manifest?
  plugin_manifest? && plugin_manifest.key?(HashedCommandLoader::KEY)
end

.for_config(chef_config_dir) ⇒ Object

A small factory method. Eventually, this is the only place where SubcommandLoader should know about its subclasses, but to maintain backwards compatibility many of the instance methods in this base class contain default implementations of the functions sub classes should otherwise provide or directly instantiate the appropriate subclass


47
48
49
50
51
52
53
54
# File 'lib/chef/knife/core/subcommand_loader.rb', line 47

def self.for_config(chef_config_dir)
  if autogenerated_manifest?
    Chef::Log.debug("Using autogenerated hashed command manifest #{plugin_manifest_path}")
    Knife::SubcommandLoader::HashedCommandLoader.new(chef_config_dir, plugin_manifest)
  else
    Knife::SubcommandLoader::GemGlobLoader.new(chef_config_dir)
  end
end

.gem_glob_loader(chef_config_dir) ⇒ Object

There are certain situations where we want to shortcut the loader selection in self.for_config and force using the GemGlobLoader


58
59
60
# File 'lib/chef/knife/core/subcommand_loader.rb', line 58

def self.gem_glob_loader(chef_config_dir)
  Knife::SubcommandLoader::GemGlobLoader.new(chef_config_dir)
end

.plugin_manifestObject


70
71
72
# File 'lib/chef/knife/core/subcommand_loader.rb', line 70

def self.plugin_manifest
  Chef::JSONCompat.from_json(File.read(plugin_manifest_path))
end

.plugin_manifest?Boolean

Returns:

  • (Boolean)

62
63
64
# File 'lib/chef/knife/core/subcommand_loader.rb', line 62

def self.plugin_manifest?
  plugin_manifest_path && File.exist?(plugin_manifest_path)
end

.plugin_manifest_pathObject


74
75
76
# File 'lib/chef/knife/core/subcommand_loader.rb', line 74

def self.plugin_manifest_path
  Chef::Util::PathHelper.home(".chef", "plugin_manifest.json")
end

Instance Method Details

#command_class_from(args) ⇒ Object


107
108
109
110
111
112
113
# File 'lib/chef/knife/core/subcommand_loader.rb', line 107

def command_class_from(args)
  cmd_words = positional_arguments(args)
  load_command(cmd_words)
  result = Chef::Knife.subcommands[find_longest_key(Chef::Knife.subcommands,
                                                    cmd_words, "_")]
  result || Chef::Knife.subcommands[args.first.tr("-", "_")]
end

#find_longest_key(hash, words, sep = "_") ⇒ Object

Utility function for finding an element in a hash given an array of words and a separator. We find the the longest key in the hash composed of the given words joined by the separator.


141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/chef/knife/core/subcommand_loader.rb', line 141

def find_longest_key(hash, words, sep = "_")
  match = nil
  until match || words.empty?
    candidate = words.join(sep)
    if hash.key?(candidate)
      match = candidate
    else
      words.pop
    end
  end
  match
end

#find_subcommands_via_dirglobObject

This is shared between the custom_manifest_loader and the gem_glob_loader


125
126
127
128
129
130
131
132
133
134
# File 'lib/chef/knife/core/subcommand_loader.rb', line 125

def find_subcommands_via_dirglob
  # The "require paths" of the core knife subcommands bundled with chef
  files = Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(File.expand_path("../../../knife", __FILE__)), "*.rb")]
  subcommand_files = {}
  files.each do |knife_file|
    rel_path = knife_file[/#{CHEF_ROOT}#{Regexp.escape(File::SEPARATOR)}(.*)\.rb/, 1]
    subcommand_files[rel_path] = knife_file
  end
  subcommand_files
end

#force_loadObject


89
90
91
92
# File 'lib/chef/knife/core/subcommand_loader.rb', line 89

def force_load
  @loaded = false
  load_commands
end

#guess_category(args) ⇒ Object


115
116
117
118
119
120
# File 'lib/chef/knife/core/subcommand_loader.rb', line 115

def guess_category(args)
  category_words = positional_arguments(args)
  category_words.map! { |w| w.split("-") }.flatten!
  find_longest_key(Chef::Knife.subcommands_by_category,
                   category_words, " ")
end

#list_commands(pref_cat = nil) ⇒ Object


98
99
100
101
102
103
104
105
# File 'lib/chef/knife/core/subcommand_loader.rb', line 98

def list_commands(pref_cat = nil)
  load_commands
  if pref_cat && Chef::Knife.subcommands_by_category.key?(pref_cat)
    { pref_cat => Chef::Knife.subcommands_by_category[pref_cat] }
  else
    Chef::Knife.subcommands_by_category
  end
end

#load_command(_command_args) ⇒ Object


94
95
96
# File 'lib/chef/knife/core/subcommand_loader.rb', line 94

def load_command(_command_args)
  load_commands
end

#load_commandsObject

Load all the sub-commands


83
84
85
86
87
# File 'lib/chef/knife/core/subcommand_loader.rb', line 83

def load_commands
  return true if @loaded
  subcommand_files.each { |subcommand| Kernel.load subcommand }
  @loaded = true
end

#positional_arguments(args) ⇒ Array<String>

The positional arguments from the argument list provided by the users. Used to search for subcommands and categories.

Returns:


160
161
162
# File 'lib/chef/knife/core/subcommand_loader.rb', line 160

def positional_arguments(args)
  args.select { |arg| arg =~ /^(([[:alnum:]])[[:alnum:]\_\-]+)$/ }
end

#site_subcommandsObject

Returns an Array of paths to knife commands located in chef_config_dir/plugins/knife/ and ~/.chef/plugins/knife/


166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/chef/knife/core/subcommand_loader.rb', line 166

def site_subcommands
  user_specific_files = []

  if chef_config_dir
    user_specific_files.concat Dir.glob(File.expand_path("plugins/knife/*.rb", Chef::Util::PathHelper.escape_glob_dir(chef_config_dir)))
  end

  # finally search ~/.chef/plugins/knife/*.rb
  Chef::Util::PathHelper.home(".chef", "plugins", "knife") do |p|
    user_specific_files.concat Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(p), "*.rb"))
  end

  user_specific_files
end