/
command_line.rb
182 lines (156 loc) · 5.82 KB
/
command_line.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# Bundler and rubygems maintain a set of directories from which to
# load gems. If Bundler is loaded, let it determine what can be
# loaded. If it's not loaded, then use rubygems. But do this before
# loading any puppet code, so that our gem loading system is sane.
if not defined? ::Bundler
begin
require 'rubygems'
rescue LoadError
end
end
require 'puppet'
require 'puppet/util'
require "puppet/util/plugins"
require "puppet/util/rubygems"
require "puppet/util/limits"
module Puppet
module Util
# This is the main entry point for all puppet applications / faces; it
# is basically where the bootstrapping process / lifecycle of an app
# begins.
class CommandLine
include Puppet::Util::Limits
OPTION_OR_MANIFEST_FILE = /^-|\.pp$|\.rb$/
# @param zero [String] the name of the executable
# @param argv [Array<String>] the arguments passed on the command line
# @param stdin [IO] (unused)
def initialize(zero = $0, argv = ARGV, stdin = STDIN)
@command = File.basename(zero, '.rb')
@argv = argv
Puppet::Plugins.on_commandline_initialization(:command_line_object => self)
end
# @return [String] name of the subcommand is being executed
# @api public
def subcommand_name
return @command if @command != 'puppet'
if @argv.first =~ OPTION_OR_MANIFEST_FILE
nil
else
@argv.first
end
end
# @return [Array<String>] the command line arguments being passed to the subcommand
# @api public
def args
return @argv if @command != 'puppet'
if subcommand_name.nil?
@argv
else
@argv[1..-1]
end
end
# @api private
# @deprecated
def self.available_subcommands
Puppet.deprecation_warning('Puppet::Util::CommandLine.available_subcommands is deprecated; please use Puppet::Application.available_application_names instead.')
Puppet::Application.available_application_names
end
# available_subcommands was previously an instance method, not a class
# method, and we have an unknown number of user-implemented applications
# that depend on that behaviour. Forwarding allows us to preserve a
# backward compatible API. --daniel 2011-04-11
# @api private
# @deprecated
def available_subcommands
Puppet.deprecation_warning('Puppet::Util::CommandLine#available_subcommands is deprecated; please use Puppet::Application.available_application_names instead.')
Puppet::Application.available_application_names
end
# Run the puppet subcommand. If the subcommand is determined to be an
# external executable, this method will never return and the current
# process will be replaced via {Kernel#exec}.
#
# @return [void]
def execute
Puppet::Util.exit_on_fail("initialize global default settings") do
Puppet.initialize_settings(args)
end
setpriority(Puppet[:priority])
find_subcommand.run
end
# @api private
def external_subcommand
Puppet::Util.which("puppet-#{subcommand_name}")
end
private
def find_subcommand
if subcommand_name.nil?
NilSubcommand.new(self)
elsif Puppet::Application.available_application_names.include?(subcommand_name)
ApplicationSubcommand.new(subcommand_name, self)
elsif path_to_subcommand = external_subcommand
ExternalSubcommand.new(path_to_subcommand, self)
else
UnknownSubcommand.new(subcommand_name, self)
end
end
# @api private
class ApplicationSubcommand
def initialize(subcommand_name, command_line)
@subcommand_name = subcommand_name
@command_line = command_line
end
def run
# For most applications, we want to be able to load code from the modulepath,
# such as apply, describe, resource, and faces.
# For agent, we only want to load pluginsync'ed code from libdir.
# For master, we shouldn't ever be loading per-enviroment code into the master's
# ruby process, but that requires fixing (#17210, #12173, #8750). So for now
# we try to restrict to only code that can be autoloaded from the node's
# environment.
if @subcommand_name != 'master' and @subcommand_name != 'agent'
Puppet.lookup(:environments).get(Puppet[:environment]).each_plugin_directory do |dir|
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
end
end
app = Puppet::Application.find(@subcommand_name).new(@command_line)
Puppet::Plugins.on_application_initialization(:application_object => @command_line)
app.run
end
end
# @api private
class ExternalSubcommand
def initialize(path_to_subcommand, command_line)
@path_to_subcommand = path_to_subcommand
@command_line = command_line
end
def run
Kernel.exec(@path_to_subcommand, *@command_line.args)
end
end
# @api private
class NilSubcommand
def initialize(command_line)
@command_line = command_line
end
def run
if @command_line.args.include? "--version" or @command_line.args.include? "-V"
puts Puppet.version
else
puts "See 'puppet help' for help on available puppet subcommands"
end
end
end
# @api private
class UnknownSubcommand < NilSubcommand
def initialize(subcommand_name, command_line)
@subcommand_name = subcommand_name
super(command_line)
end
def run
puts "Error: Unknown Puppet subcommand '#{@subcommand_name}'"
super
end
end
end
end
end