bolt 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +43 -43
  3. data/lib/bolt/config.rb +25 -5
  4. data/lib/bolt/node.rb +3 -1
  5. data/lib/bolt/node/ssh.rb +15 -2
  6. data/lib/bolt/node/winrm.rb +20 -9
  7. data/lib/bolt/version.rb +1 -1
  8. data/modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
  9. data/modules/boltlib/lib/puppet/functions/run_task.rb +29 -32
  10. data/vendored/puppet/lib/puppet.rb +2 -5
  11. data/vendored/puppet/lib/puppet/application.rb +18 -1
  12. data/vendored/puppet/lib/puppet/application/agent.rb +8 -1
  13. data/vendored/puppet/lib/puppet/application/config.rb +1 -0
  14. data/vendored/puppet/lib/puppet/application/device.rb +1 -2
  15. data/vendored/puppet/lib/puppet/application/filebucket.rb +10 -2
  16. data/vendored/puppet/lib/puppet/application/help.rb +1 -0
  17. data/vendored/puppet/lib/puppet/application_support.rb +6 -1
  18. data/vendored/puppet/lib/puppet/configurer.rb +8 -3
  19. data/vendored/puppet/lib/puppet/defaults.rb +29 -9
  20. data/vendored/puppet/lib/puppet/environments.rb +2 -0
  21. data/vendored/puppet/lib/puppet/face/config.rb +14 -1
  22. data/vendored/puppet/lib/puppet/face/module/list.rb +1 -1
  23. data/vendored/puppet/lib/puppet/face/module/search.rb +4 -1
  24. data/vendored/puppet/lib/puppet/forge.rb +6 -0
  25. data/vendored/puppet/lib/puppet/functions/convert_to.rb +32 -0
  26. data/vendored/puppet/lib/puppet/gettext/config.rb +135 -37
  27. data/vendored/puppet/lib/puppet/gettext/module_translations.rb +42 -0
  28. data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +2 -0
  29. data/vendored/puppet/lib/puppet/module.rb +10 -18
  30. data/vendored/puppet/lib/puppet/network/http/factory.rb +9 -0
  31. data/vendored/puppet/lib/puppet/node/environment.rb +14 -0
  32. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +17 -3
  33. data/vendored/puppet/lib/puppet/parser/scope.rb +11 -0
  34. data/vendored/puppet/lib/puppet/pops.rb +0 -1
  35. data/vendored/puppet/lib/puppet/pops/evaluator/epp_evaluator.rb +13 -0
  36. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +39 -5
  37. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +64 -24
  38. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +1 -1
  39. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +21 -70
  40. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +2 -2
  41. data/vendored/puppet/lib/puppet/pops/parser/parser_support.rb +1 -1
  42. data/vendored/puppet/lib/puppet/pops/pcore.rb +43 -1
  43. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +4 -0
  44. data/vendored/puppet/lib/puppet/pops/types/types.rb +25 -5
  45. data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +5 -3
  46. data/vendored/puppet/lib/puppet/provider/service/smf.rb +2 -0
  47. data/vendored/puppet/lib/puppet/settings/environment_conf.rb +14 -2
  48. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +1 -1
  49. data/vendored/puppet/lib/puppet/ssl/certificate_signer.rb +6 -0
  50. data/vendored/puppet/lib/puppet/ssl/host.rb +1 -1
  51. data/vendored/puppet/lib/puppet/type/file/checksum.rb +1 -1
  52. data/vendored/puppet/lib/puppet/type/file/checksum_value.rb +4 -3
  53. data/vendored/puppet/lib/puppet/type/k5login.rb +101 -0
  54. data/vendored/puppet/lib/puppet/type/tidy.rb +4 -2
  55. data/vendored/puppet/lib/puppet/util/checksums.rb +82 -1
  56. data/vendored/puppet/lib/puppet/util/command_line.rb +5 -0
  57. data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +5 -1
  58. data/vendored/puppet/lib/puppet_pal.rb +272 -11
  59. data/vendored/require_vendored.rb +0 -6
  60. metadata +8 -8
  61. data/vendored/puppet/lib/puppet/bindings.rb +0 -147
  62. data/vendored/puppet/lib/puppet/pops/types/task.rb +0 -116
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4e27492b22291a233b5fb9dfbb8e8648a15ce19
4
- data.tar.gz: 9b2d163aa823b02cd7b6cfc6031846841d7c7b30
3
+ metadata.gz: 4990187d4d2da77d515fdbe3d840b415683d7082
4
+ data.tar.gz: 1eebdfd02969958314e3fa1b4ce0e03b6efc208c
5
5
  SHA512:
6
- metadata.gz: b3d53aafec9ab3aa09d30dd5d45624aa74a20835373c70f174508f4986c33470b5b45350f40014e534b18f59a6267303395f2075cdb1269231b112c8d9ec1765
7
- data.tar.gz: 664b5acf2aa442bf7e24dd76b61723819a4eb0523b34118bd0976f6c696db03319e979ad40521af7334bebf06cdd545b071b3eef87047b0b5ced11988f6e49a5
6
+ metadata.gz: 97ae71fbb805bc96980f1353eebcb458e528c74e9a9c1c94a33ffe0f7c6256058080e6052cee0909dcb06a84fea6cb764a59f47de86e1027df2ff06c9ac3e1f4
7
+ data.tar.gz: 4fa7f06bf895ab837451077997aa05bbc4b0291116a3be254cb9e4c600d5eb35da98b48fa349a32ca902b8f4849fa5d79d9bc44b05754a4dc6b46050d088b87b
data/lib/bolt/cli.rb CHANGED
@@ -139,11 +139,19 @@ HELP
139
139
  "Private ssh key to authenticate with (Optional)") do |key|
140
140
  results[:key] = key
141
141
  end
142
+ opts.on('--tmpdir DIR',
143
+ "The directory to upload and execute temporary files on the target(Optional)") do |tmpdir|
144
+ results[:tmpdir] = tmpdir
145
+ end
142
146
  opts.on('-c', '--concurrency CONCURRENCY', Integer,
143
147
  "Maximum number of simultaneous connections " \
144
148
  "(Optional, defaults to 100)") do |concurrency|
145
149
  results[:concurrency] = concurrency
146
150
  end
151
+ opts.on('--connect-timeout TIMEOUT', Integer,
152
+ "Connection timeout (Optional)") do |timeout|
153
+ results[:connect_timeout] = timeout
154
+ end
147
155
  opts.on('--modulepath MODULES',
148
156
  "List of directories containing modules, " \
149
157
  "separated by #{File::PATH_SEPARATOR}") do |modulepath|
@@ -401,15 +409,7 @@ HELP
401
409
  outputter.print_event(node, event)
402
410
  end
403
411
  when 'task'
404
- task_name = options[:object]
405
-
406
- path, metadata = load_task_data(task_name, @config[:modulepath])
407
- input_method = metadata['input_method']
408
-
409
- input_method ||= 'both'
410
- executor.run_task(
411
- nodes, path, input_method, options[:task_options]
412
- ) do |node, event|
412
+ execute_task(executor, options) do |node, event|
413
413
  outputter.print_event(node, event)
414
414
  end
415
415
  when 'file'
@@ -433,12 +433,26 @@ HELP
433
433
  raise e
434
434
  end
435
435
 
436
+ def with_bolt_executor(executor, &block)
437
+ Puppet.override(bolt_executor: executor, &block)
438
+ end
439
+
440
+ def execute_task(executor, options, &block)
441
+ with_bolt_executor(executor) do
442
+ run_task(options[:object],
443
+ options[:nodes],
444
+ options[:task_options],
445
+ &block)
446
+ end
447
+ rescue Puppet::Error
448
+ raise Bolt::CLIError, "Exiting because of an error in Puppet code"
449
+ end
450
+
436
451
  def execute_plan(executor, options)
437
452
  # Plans return null here?
438
- result = Puppet.override(bolt_executor: executor) do
453
+ result = with_bolt_executor(executor) do
439
454
  run_plan(options[:object],
440
- options[:task_options],
441
- @config[:modulepath])
455
+ options[:task_options])
442
456
  end
443
457
  outputter.print_plan(result)
444
458
  rescue Puppet::Error
@@ -469,48 +483,34 @@ HELP
469
483
  @outputter ||= Bolt::Outputter.for_format(@config[:format])
470
484
  end
471
485
 
472
- def load_task_data(name, modulepath)
473
- module_name, file_name = name.split('::', 2)
474
- file_name ||= 'init'
475
-
476
- begin
477
- env = Puppet::Node::Environment.create('bolt', modulepath)
478
- Puppet.override(environments: Puppet::Environments::Static.new(env)) do
479
- data = Puppet::InfoService::TaskInformationService.task_data(
480
- env.name, module_name, name
481
- )
482
-
483
- file = data[:files].find { |f| File.basename(f, '.*') == file_name }
484
- if file.nil?
485
- raise Bolt::CLIError, "Failed to load task file for '#{name}'"
486
+ def run_task(name, nodes, args, &block)
487
+ parse_error = nil
488
+ Puppet.initialize_settings
489
+ Puppet::Pal.in_tmp_environment('bolt', modulepath: [BOLTLIB_PATH] + @config[:modulepath], facts: {}) do |pal|
490
+ pal.with_script_compiler do |compiler|
491
+ begin
492
+ return compiler.call_function('run_task', name, nodes, args, &block)
493
+ rescue Puppet::ParseError => e
494
+ # we assume that the Puppet::ParseError is due to a problem with
495
+ # the task and/or its parameters, but since the with_script_compiler
496
+ # method rescues these errors and raises different ones instead,
497
+ # we save it in a local variable and raise it as Bolt::CLIError
498
+ # outside of the block
499
+ parse_error = e
486
500
  end
487
-
488
- metadata =
489
- if data[:metadata_file]
490
- JSON.parse(File.read(data[:metadata_file]))
491
- else
492
- {}
493
- end
494
-
495
- [file, metadata]
496
501
  end
497
- rescue Puppet::Module::Task::TaskNotFound
498
- raise Bolt::CLIError,
499
- "Could not find task '#{name}' in module '#{module_name}'"
500
- rescue Puppet::Module::MissingModule
501
- # Generate message so we don't expose "bolt environment"
502
- raise Bolt::CLIError, "Could not find module '#{module_name}'"
503
502
  end
503
+ raise Bolt::CLIError, parse_error.message
504
504
  end
505
505
 
506
- def run_plan(plan, args, modulepath)
506
+ def run_plan(plan, args)
507
507
  Dir.mktmpdir('bolt') do |dir|
508
508
  cli = []
509
509
  Puppet::Settings::REQUIRED_APP_SETTINGS.each do |setting|
510
510
  cli << "--#{setting}" << dir
511
511
  end
512
512
  Puppet.initialize_settings(cli)
513
- Puppet::Pal.in_tmp_environment('bolt', modulepath: [BOLTLIB_PATH] + modulepath, facts: {}) do |pal|
513
+ Puppet::Pal.in_tmp_environment('bolt', modulepath: [BOLTLIB_PATH] + @config[:modulepath], facts: {}) do |pal|
514
514
  pal.with_script_compiler do |compiler|
515
515
  compiler.call_function('run_plan', plan, args)
516
516
  end
data/lib/bolt/config.rb CHANGED
@@ -20,9 +20,10 @@ module Bolt
20
20
  log_destination: STDERR
21
21
  }.freeze
22
22
 
23
- TRANSPORT_OPTIONS = %i[insecure password run_as sudo sudo_password key tty user].freeze
23
+ TRANSPORT_OPTIONS = %i[insecure password run_as sudo sudo_password key tty tmpdir user connect_timeout].freeze
24
24
 
25
25
  TRANSPORT_DEFAULTS = {
26
+ connect_timeout: 10,
26
27
  insecure: false,
27
28
  tty: false
28
29
  }.freeze
@@ -93,11 +94,22 @@ module Bolt
93
94
  if data['ssh']['insecure']
94
95
  self[:transports][:ssh][:insecure] = data['ssh']['insecure']
95
96
  end
97
+ if data['ssh']['connect-timeout']
98
+ self[:transports][:ssh][:connect_timeout] = data['ssh']['connect-timeout']
99
+ end
100
+ if data['ssh']['tmpdir']
101
+ self[:transports][:ssh][:tmpdir] = data['ssh']['tmpdir']
102
+ end
103
+ end
104
+
105
+ if data['winrm']
106
+ if data['winrm']['connect-timeout']
107
+ self[:transports][:winrm][:connect_timeout] = data['winrm']['connect-timeout']
108
+ end
109
+ if data['winrm']['tmpdir']
110
+ self[:transports][:winrm][:tmpdir] = data['winrm']['tmpdir']
111
+ end
96
112
  end
97
- # if data['pcp']
98
- # end
99
- # if data['winrm']
100
- # end
101
113
  end
102
114
 
103
115
  def load_file(path)
@@ -135,6 +147,14 @@ module Bolt
135
147
  unless %w[human json].include? self[:format]
136
148
  raise Bolt::CLIError, "Unsupported format: '#{self[:format]}'"
137
149
  end
150
+
151
+ self[:transports].each_value do |v|
152
+ timeout_value = v[:connect_timeout]
153
+ unless timeout_value.is_a?(Integer) || timeout_value.nil?
154
+ error_msg = "connect-timeout value must be an Integer, received #{timeout_value}:#{timeout_value.class}"
155
+ raise Bolt::CLIError, error_msg
156
+ end
157
+ end
138
158
  end
139
159
  end
140
160
  end
data/lib/bolt/node.rb CHANGED
@@ -29,7 +29,7 @@ module Bolt
29
29
 
30
30
  def self.initialize_transport(_logger); end
31
31
 
32
- attr_reader :logger, :host, :uri, :user, :password
32
+ attr_reader :logger, :host, :uri, :user, :password, :connect_timeout
33
33
 
34
34
  def initialize(host, port = nil, user = nil, password = nil, uri: nil,
35
35
  config: Bolt::Config.new)
@@ -43,9 +43,11 @@ module Bolt
43
43
  @key = transport_conf[:key]
44
44
  @tty = transport_conf[:tty]
45
45
  @insecure = transport_conf[:insecure]
46
+ @connect_timeout = transport_conf[:connect_timeout]
46
47
  @sudo = transport_conf[:sudo]
47
48
  @sudo_password = transport_conf[:sudo_password]
48
49
  @run_as = transport_conf[:run_as]
50
+ @tmpdir = transport_conf[:tmpdir]
49
51
 
50
52
  @logger = init_logger(config[:log_destination], config[:log_level])
51
53
  @transport_logger = init_logger(config[:log_destination], Logger::WARN)
data/lib/bolt/node/ssh.rb CHANGED
@@ -32,6 +32,7 @@ module Bolt
32
32
  else
33
33
  Net::SSH::Verifiers::Secure.new
34
34
  end
35
+ options[:timeout] = @connect_timeout if @connect_timeout
35
36
 
36
37
  @session = Net::SSH.start(@host, @user, options)
37
38
  @logger.debug { "Opened session" }
@@ -45,6 +46,11 @@ module Bolt
45
46
  "Host key verification failed for #{@uri}: #{e.message}",
46
47
  'HOST_KEY_ERROR'
47
48
  )
49
+ rescue Net::SSH::ConnectionTimeout
50
+ raise Bolt::Node::ConnectError.new(
51
+ "Timeout after #{@connect_timeout} seconds connecting to #{@uri}",
52
+ 'CONNECT_ERROR'
53
+ )
48
54
  rescue StandardError => e
49
55
  raise Bolt::Node::ConnectError.new(
50
56
  "Failed to connect to #{@uri}: #{e.message}",
@@ -165,11 +171,18 @@ module Bolt
165
171
  end
166
172
 
167
173
  def make_tempdir
168
- result = execute('mktemp -d')
174
+ tmppath = nil
175
+ if @tmpdir
176
+ tmppath = "#{@tmpdir}/#{SecureRandom.uuid}"
177
+ command = "mkdir -m 700 #{tmppath}"
178
+ else
179
+ command = 'mktemp -d'
180
+ end
181
+ result = execute(command)
169
182
  if result.exit_code != 0
170
183
  raise FileError.new("Could not make tempdir: #{result.stderr.string}", 'TEMPDIR_ERROR')
171
184
  end
172
- result.stdout.string.chomp
185
+ tmppath || result.stdout.string.chomp
173
186
  end
174
187
 
175
188
  def with_remote_tempdir
@@ -17,14 +17,24 @@ module Bolt
17
17
  end
18
18
 
19
19
  def connect
20
- @connection = ::WinRM::Connection.new(endpoint: @endpoint,
21
- user: @user,
22
- password: @password)
23
- @connection.logger = @transport_logger
24
-
25
- @session = @connection.shell(@shell)
26
- @session.run('$PSVersionTable.PSVersion')
27
- @logger.debug { "Opened session" }
20
+ options = { endpoint: @endpoint,
21
+ user: @user,
22
+ password: @password,
23
+ retry_limit: 1 }
24
+
25
+ Timeout.timeout(@connect_timeout) do
26
+ @connection = ::WinRM::Connection.new(options)
27
+ @connection.logger = @transport_logger
28
+
29
+ @session = @connection.shell(@shell)
30
+ @session.run('$PSVersionTable.PSVersion')
31
+ @logger.debug { "Opened session" }
32
+ end
33
+ rescue Timeout::Error
34
+ raise Bolt::Node::ConnectError.new(
35
+ "Timeout after #{@connect_timeout} seconds connecting to #{@endpoint}",
36
+ 'CONNECT_ERROR'
37
+ )
28
38
  rescue ::WinRM::WinRMAuthorizationError
29
39
  raise Bolt::Node::ConnectError.new(
30
40
  "Authentication failed for #{@endpoint}",
@@ -425,8 +435,9 @@ PS
425
435
  end
426
436
 
427
437
  def make_tempdir
438
+ find_parent = @tmpdir ? "\"#{@tmpdir}\"" : '[System.IO.Path]::GetTempPath()'
428
439
  result = execute(<<-PS)
429
- $parent = [System.IO.Path]::GetTempPath()
440
+ $parent = #{find_parent}
430
441
  $name = [System.IO.Path]::GetRandomFileName()
431
442
  $path = Join-Path $parent $name
432
443
  New-Item -ItemType Directory -Path $path | Out-Null
data/lib/bolt/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Bolt
2
- VERSION = '0.10.0'.freeze
2
+ VERSION = '0.11.0'.freeze
3
3
  end
@@ -6,7 +6,7 @@
6
6
  # # do things with tasks
7
7
  # notice "plan done with param x = ${x}"
8
8
  # }
9
- # run_plan('myplan', {x => 'testing' }
9
+ # run_plan('myplan', { x => 'testing' })
10
10
  #
11
11
  Puppet::Functions.create_function(:run_plan, Puppet::Functions::InternalFunction) do
12
12
  dispatch :run_plan do
@@ -10,45 +10,38 @@ Puppet::Functions.create_function(:run_task) do
10
10
  type 'TargetOrTargets = Variant[String[1], Target, Array[TargetOrTargets]]'
11
11
  end
12
12
 
13
- dispatch :run_task_type do
14
- param 'Type[Task]', :task_type
13
+ dispatch :run_task do
14
+ param 'String[1]', :task_name
15
15
  param 'TargetOrTargets', :targets
16
16
  optional_param 'Hash[String[1], Any]', :task_args
17
17
  end
18
18
 
19
- dispatch :run_named_task do
20
- param 'String[1]', :task_type
19
+ # this is used from 'bolt task run'
20
+ dispatch :run_task_raw do
21
+ param 'String[1]', :task_name
21
22
  param 'TargetOrTargets', :targets
22
23
  optional_param 'Hash[String[1], Any]', :task_args
24
+ block_param
23
25
  end
24
26
 
25
- dispatch :run_task_instance do
26
- param 'Task', :task
27
- repeated_param 'TargetOrTargets', :targets
27
+ def run_task(task_name, targets, task_args = nil)
28
+ Puppet::Pops::Types::ExecutionResult.from_bolt(
29
+ run_task_raw(task_name, targets, task_args)
30
+ )
28
31
  end
29
32
 
30
- def run_task_type(task_type, targets, task_args = nil)
31
- use_args = task_args.nil? ? {} : task_args
32
- task_instance = call_function('new', task_type, use_args)
33
- run_task_instance(task_instance, targets)
34
- end
35
-
36
- def run_named_task(task_name, targets, task_args = nil)
37
- task_type = Puppet.lookup(:loaders).private_environment_loader.load(:type, task_name)
38
- if task_type.nil?
33
+ def run_task_raw(task_name, targets, task_args = nil, &block)
34
+ unless Puppet[:tasks]
39
35
  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
40
- Puppet::Pops::Issues::UNKNOWN_TASK, type_name: task_name
36
+ Puppet::Pops::Issues::TASK_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, operation: 'run_task'
41
37
  )
42
38
  end
43
- use_args = task_args.nil? ? {} : task_args
44
- task_instance = call_function('new', task_type, use_args)
45
- run_task_instance(task_instance, targets)
46
- end
47
39
 
48
- def run_task_instance(task, *targets)
49
- unless Puppet[:tasks]
40
+ # TODO: use the compiler injection once PUP-8237 lands
41
+ task_signature = Puppet::Pal::ScriptCompiler.new(closure_scope.compiler).task_signature(task_name)
42
+ if task_signature.nil?
50
43
  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
51
- Puppet::Pops::Issues::TASK_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, operation: 'run_task'
44
+ Puppet::Pops::Issues::UNKNOWN_TASK, type_name: task_name
52
45
  )
53
46
  end
54
47
 
@@ -59,22 +52,26 @@ Puppet::Functions.create_function(:run_task) do
59
52
  )
60
53
  end
61
54
 
55
+ use_args = task_args.nil? ? {} : task_args
56
+ task_signature.runnable_with?(use_args) do |mismatch|
57
+ raise Puppet::ParseError, mismatch
58
+ end || (raise Puppet::ParseError, 'Task parameters did not match')
59
+ task = task_signature.task
60
+
62
61
  # Ensure that that given targets are all Target instances
62
+ targets = [targets] unless targets.is_a?(Array)
63
63
  targets = targets.flatten.map { |t| t.is_a?(String) ? Puppet::Pops::Types::TypeFactory.target.create(t) : t }
64
64
  if targets.empty?
65
- call_function('debug', "Simulating run of task #{task._pcore_type.name} - no targets given - no action taken")
66
- Puppet::Pops::Types::ExecutionResult::EMPTY_RESULT
65
+ call_function('debug', "Simulating run of task #{task.name} - no targets given - no action taken")
66
+ Puppet::Pops::EMPTY_HASH
67
67
  else
68
- # Awaits change in the executor, enabling it receive Target instances
68
+ # TODO: Awaits change in the executor, enabling it receive Target instances
69
69
  hosts = targets.map(&:host)
70
70
 
71
71
  # TODO: separate handling of default since it's platform specific
72
- input_method = task._pcore_type['input_method'].value
72
+ input_method = task.input_method
73
73
 
74
- arguments = task.task_args
75
- Puppet::Pops::Types::ExecutionResult.from_bolt(
76
- executor.run_task(executor.from_uris(hosts), task.executable_path, input_method, arguments)
77
- )
74
+ executor.run_task(executor.from_uris(hosts), task.executable, input_method, use_args, &block)
78
75
  end
79
76
  end
80
77
  end
@@ -42,11 +42,8 @@ module Puppet
42
42
  require 'puppet/environments'
43
43
 
44
44
  class << self
45
- Puppet::GettextConfig.create_text_domain('production')
46
- locale_dir = Puppet::GettextConfig.puppet_locale_path
47
- if Puppet::GettextConfig.load_translations('puppet', locale_dir, Puppet::GettextConfig.translation_mode(locale_dir))
48
- Puppet::GettextConfig.set_locale(Locale.current.language)
49
- end
45
+ Puppet::GettextConfig.setup_locale
46
+ Puppet::GettextConfig.create_default_text_domain
50
47
 
51
48
  include Puppet::Util
52
49
  attr_reader :features
@@ -281,6 +281,23 @@ class Application
281
281
  @run_mode = Puppet::Util::RunMode[ mode_name || Puppet.settings.preferred_run_mode ]
282
282
  end
283
283
 
284
+ # Sets environment_mode name
285
+ # @param mode_name [Symbol] The name of the environment mode to run in. May
286
+ # be one of :local, :remote, or :not_required. This impacts where the
287
+ # application looks for its specified environment. If :not_required or
288
+ # :remote are set, the application will not fail if the environment does
289
+ # not exist on the local filesystem.
290
+ def environment_mode(mode_name)
291
+ raise Puppet::Error, _("Invalid environment mode '%{mode_name}'") % { mode_name: mode_name } unless [:local, :remote, :not_required].include?(mode_name)
292
+ @environment_mode = mode_name
293
+ end
294
+
295
+ # Gets environment_mode name. If none is set with `environment_mode=`,
296
+ # default to :local.
297
+ def get_environment_mode
298
+ @environment_mode || :local
299
+ end
300
+
284
301
  # This is for testing only
285
302
  def clear_everything_for_tests
286
303
  @run_mode = @banner = @run_status = @option_parser_commands = nil
@@ -343,7 +360,7 @@ class Application
343
360
  initialize_app_defaults
344
361
  end
345
362
 
346
- Puppet::ApplicationSupport.push_application_context(self.class.run_mode)
363
+ Puppet::ApplicationSupport.push_application_context(self.class.run_mode, self.class.get_environment_mode)
347
364
 
348
365
  exit_on_fail(_("Could not initialize")) { preinit }
349
366
  exit_on_fail(_("Could not parse application options")) { parse_options }