puppet-8.4.0/ 0000755 0052762 0001160 00000000000 14552052637 012741 5 ustar jenkins jenkins puppet-8.4.0/Rakefile 0000644 0052762 0001160 00000005226 14552052437 014411 0 ustar jenkins jenkins # Rakefile for Puppet -*- ruby -*-
RAKE_ROOT = File.dirname(__FILE__)
# We need access to the Puppet.version method
$LOAD_PATH.unshift(File.expand_path("lib"))
require 'puppet/version'
$LOAD_PATH << File.join(RAKE_ROOT, 'tasks')
begin
require 'rubygems'
require 'rubygems/package_task'
rescue LoadError
# Users of older versions of Rake (0.8.7 for example) will not necessarily
# have rubygems installed, or the newer rubygems package_task for that
# matter.
require 'rake/packagetask'
require 'rake/gempackagetask'
end
require 'rake'
require 'open3'
Dir['tasks/**/*.rake'].each { |t| load t }
if Rake.application.top_level_tasks.grep(/^(pl:|package:)/).any?
begin
require 'packaging'
Pkg::Util::RakeUtils.load_packaging_tasks
rescue LoadError => e
puts "Error loading packaging rake tasks: #{e}"
end
end
namespace :package do
task :bootstrap do
puts 'Bootstrap is no longer needed, using packaging-as-a-gem'
end
task :implode do
puts 'Implode is no longer needed, using packaging-as-a-gem'
end
end
task :default do
sh %{rake -T}
end
task :spec do
ENV["LOG_SPEC_ORDER"] = "true"
sh %{rspec #{ENV['TEST'] || ENV['TESTS'] || 'spec'}}
end
desc 'run static analysis with rubocop'
task(:rubocop) do
require 'rubocop'
cli = RuboCop::CLI.new
exit_code = cli.run(%w(--display-cop-names --format simple))
raise "RuboCop detected offenses" if exit_code != 0
end
desc "verify that changed files are clean of Ruby warnings"
task(:warnings) do
# This rake task looks at all files modified in this branch.
commit_range = 'HEAD^..HEAD'
ruby_files_ok = true
puts "Checking modified files #{commit_range}"
%x{git diff --diff-filter=ACM --name-only #{commit_range}}.each_line do |modified_file|
modified_file.chomp!
# Skip racc generated file as it can have many warnings that cannot be manually fixed
next if modified_file.end_with?("pops/parser/eparser.rb")
next if modified_file.start_with?('spec/fixtures/', 'acceptance/fixtures/') || File.extname(modified_file) != '.rb'
puts modified_file
stdout, stderr, _ = Open3.capture3("ruby -wc \"#{modified_file}\"")
unless stderr.empty?
ruby_files_ok = false
puts stderr
end
puts stdout
end
raise "One or more ruby files contain warnings." unless ruby_files_ok
end
if Rake.application.top_level_tasks.grep(/^gettext:/).any?
begin
spec = Gem::Specification.find_by_name 'gettext-setup'
load "#{spec.gem_dir}/lib/tasks/gettext.rake"
GettextSetup.initialize(File.absolute_path('locales', File.dirname(__FILE__)))
rescue LoadError
abort("Run `bundle install --with documentation` to install the `gettext-setup` gem.")
end
end
puppet-8.4.0/Gemfile 0000644 0052762 0001160 00000005327 14552052437 014241 0 ustar jenkins jenkins source ENV['GEM_SOURCE'] || "https://rubygems.org"
gemspec
def location_for(place, fake_version = nil)
if place.is_a?(String) && place =~ /^((?:git[:@]|https:)[^#]*)#(.*)/
[fake_version, { git: $1, branch: $2, require: false }].compact
elsif place.is_a?(String) && place =~ /^file:\/\/(.*)/
['>= 0', { path: File.expand_path($1), require: false }]
else
[place, { require: false }]
end
end
# Make sure these gem requirements are in sync with the gempspec and ext/project_data.yaml
gem "facter", *location_for(ENV['FACTER_LOCATION'] || ["~> 4.3"])
gem "semantic_puppet", *location_for(ENV['SEMANTIC_PUPPET_LOCATION'] || ["~> 1.0"])
gem "puppet-resource_api", *location_for(ENV['RESOURCE_API_LOCATION'] || ["~> 1.5"])
group(:features) do
gem 'diff-lcs', '~> 1.3', require: false
gem "hiera", *location_for(ENV['HIERA_LOCATION']) if ENV.has_key?('HIERA_LOCATION')
gem 'hiera-eyaml', *location_for(ENV['HIERA_EYAML_LOCATION'])
gem 'hocon', '~> 1.0', require: false
# requires native libshadow headers/libs
#gem 'ruby-shadow', '~> 2.5', require: false, platforms: [:ruby]
gem 'minitar', '~> 0.9', require: false
gem 'msgpack', '~> 1.2', require: false
gem 'rdoc', ['~> 6.0', '< 6.4.0'], require: false, platforms: [:ruby]
# requires native augeas headers/libs
# gem 'ruby-augeas', require: false, platforms: [:ruby]
# requires native ldap headers/libs
# gem 'ruby-ldap', '~> 0.9', require: false, platforms: [:ruby]
gem 'puppetserver-ca', '~> 2.0', require: false
end
group(:test) do
gem "ffi", '1.15.5', require: false
gem "json-schema", "~> 2.0", require: false
gem "rake", *location_for(ENV['RAKE_LOCATION'] || '~> 13.0')
gem "rspec", "~> 3.1", require: false
gem "rspec-expectations", ["~> 3.9", "!= 3.9.3"]
gem "rspec-its", "~> 1.1", require: false
gem 'vcr', '~> 6.1', require: false
gem 'webmock', '~> 3.0', require: false
gem 'webrick', '~> 1.7', require: false
gem 'yard', require: false
gem 'rubocop', '1.28.0', require: false, platforms: [:ruby]
gem 'rubocop-i18n', '~> 3.0', require: false, platforms: [:ruby]
end
group(:development, optional: true) do
gem 'memory_profiler', require: false, platforms: [:mri]
gem 'pry', require: false, platforms: [:ruby]
gem "racc", "1.5.2", require: false, platforms: [:ruby]
if RUBY_PLATFORM != 'java'
gem 'ruby-prof', '>= 0.16.0', require: false
end
end
group(:packaging) do
gem 'packaging', *location_for(ENV['PACKAGING_LOCATION'] || '~> 0.99')
end
group(:documentation, optional: true) do
gem 'gettext-setup', '~> 1.0', require: false, platforms: [:ruby]
gem 'ronn', '~> 0.7.3', require: false, platforms: [:ruby]
end
if File.exist? "#{__FILE__}.local"
eval(File.read("#{__FILE__}.local"), binding)
end
# vim:filetype=ruby
puppet-8.4.0/tasks/ 0000755 0052762 0001160 00000000000 14552052637 014066 5 ustar jenkins jenkins puppet-8.4.0/tasks/generate_cert_fixtures.rake 0000644 0052762 0001160 00000020431 14552052437 021470 0 ustar jenkins jenkins # Run this rake task to generate cert fixtures used in unit tests. This should
# be run whenever new fixtures are required that derive from the existing ones
# such as to add an extension to client certs, change expiration, etc. All
# regenerated fixtures should be committed together.
desc "Generate cert test fixtures"
task(:gen_cert_fixtures) do
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '../spec/lib'))
require 'puppet/test_ca'
def save(dir, name, x509)
path = File.join(dir, name)
puts "Generating #{path}"
File.open(path, 'w') do |f|
f.write(x509.to_text)
text = if block_given?
yield x509
else
x509.to_pem
end
f.write(text)
end
end
# This task generates a PKI consisting of a root CA, intermediate CA and
# several leaf certs. A CRL is generated for each CA. The root CA CRL is
# empty, while the intermediate CA CRL contains the revoked cert's serial
# number. A textual representation of each X509 object is included in the
# fixture as a comment.
#
# Certs
# =====
#
# ca.pem /CN=Test CA
# |
# intermediate.pem +- /CN=Test CA Subauthority
# | |
# signed.pem | +- /CN=signed
# revoked.pem | +- /CN=revoked
# tampered-cert.pem | +- /CN=signed (with different public key)
# ec.pem | +- /CN=ec (with EC private key)
# oid.pem | +- /CN=oid (with custom oid)
# |
# 127.0.0.1.pem +- /CN=127.0.0.1 (with dns alt names)
# |
# intermediate-agent.pem +- /CN=Test CA Agent Subauthority
# | |
# pluto.pem | +- /CN=pluto
# |
# bad-int-basic-constraints.pem +- /CN=Test CA Subauthority (bad isCA constraint)
#
# bad-basic-constraints.pem /CN=Test CA (bad isCA constraint)
#
# unknown-ca.pem /CN=Unknown CA
# |
# unknown-127.0.0.1.pem +- /CN=127.0.0.1
#
# Keys
# ====
#
# The RSA private key for each leaf cert is also generated. In addition,
# `encrypted-key.pem` contains the private key for the `signed` cert.
#
# Requests
# ========
#
# `request.pem` contains a valid CSR for /CN=pending, while `tampered_csr.pem`
# is the same as `request.pem`, but it's public key has been replaced.
#
dir = File.join(RAKE_ROOT, 'spec/fixtures/ssl')
# Create self-signed CA & key
unknown_ca = Puppet::TestCa.new('Unknown CA')
save(dir, 'unknown-ca.pem', unknown_ca.ca_cert)
save(dir, 'unknown-ca-key.pem', unknown_ca.key)
# Create an SSL cert for 127.0.0.1
signed = unknown_ca.create_cert('127.0.0.1', unknown_ca.ca_cert, unknown_ca.key, subject_alt_names: 'DNS:127.0.0.1,DNS:127.0.0.2')
save(dir, 'unknown-127.0.0.1.pem', signed[:cert])
save(dir, 'unknown-127.0.0.1-key.pem', signed[:private_key])
# Create Test CA & CRL
ca = Puppet::TestCa.new
save(dir, 'ca.pem', ca.ca_cert)
save(dir, 'crl.pem', ca.ca_crl)
# Create Intermediate CA & CRL "Test CA Subauthority" issued by "Test CA"
inter = ca.create_intermediate_cert('Test CA Subauthority', ca.ca_cert, ca.key)
save(dir, 'intermediate.pem', inter[:cert])
inter_crl = ca.create_crl(inter[:cert], inter[:private_key])
# Create a leaf/entity key and cert for host "signed" and issued by "Test CA Subauthority"
signed = ca.create_cert('signed', inter[:cert], inter[:private_key])
save(dir, 'signed.pem', signed[:cert])
save(dir, 'signed-key.pem', signed[:private_key])
# Create a cert for host "renewed" and issued by "Test CA Subauthority"
renewed = ca.create_cert('renewed', inter[:cert], inter[:private_key], reuse_key: signed[:private_key])
save(dir, 'renewed.pem', renewed[:cert])
# Create an encrypted version of the above private key for host "signed"
save(dir, 'encrypted-key.pem', signed[:private_key]) do |x509|
# private key password was chosen at random
x509.to_pem(OpenSSL::Cipher::AES.new(128, :CBC), '74695716c8b6')
end
# Create an SSL cert for 127.0.0.1 with dns_alt_names
signed = ca.create_cert('127.0.0.1', ca.ca_cert, ca.key, subject_alt_names: 'DNS:127.0.0.1,DNS:127.0.0.2')
save(dir, '127.0.0.1.pem', signed[:cert])
save(dir, '127.0.0.1-key.pem', signed[:private_key])
# Create an SSL cert with extensions containing custom oids
extensions = [
['1.3.6.1.4.1.34380.1.2.1.1', OpenSSL::ASN1::UTF8String.new('somevalue'), false],
]
oid = ca.create_cert('oid', inter[:cert], inter[:private_key], extensions: extensions)
save(dir, 'oid.pem', oid[:cert])
save(dir, 'oid-key.pem', oid[:private_key])
# Create a leaf/entity key and cert for host "revoked", issued by "Test CA Subauthority"
# and revoke the cert
revoked = ca.create_cert('revoked', inter[:cert], inter[:private_key])
ca.revoke(revoked[:cert], inter_crl, inter[:private_key])
save(dir, 'revoked.pem', revoked[:cert])
save(dir, 'revoked-key.pem', revoked[:private_key])
# Create an EC key and cert, issued by "Test CA Subauthority"
ec = ca.create_cert('ec', inter[:cert], inter[:private_key], key_type: :ec)
save(dir, 'ec.pem', ec[:cert])
save(dir, 'ec-key.pem', ec[:private_key])
# Create an encrypted version of the above private key for host "ec"
save(dir, 'encrypted-ec-key.pem', ec[:private_key]) do |x509|
# private key password was chosen at random
x509.to_pem(OpenSSL::Cipher::AES.new(128, :CBC), '74695716c8b6')
end
# Update intermediate CRL now that we've revoked
save(dir, 'intermediate-crl.pem', inter_crl)
# Create a pending request (CSR) and private key for host "pending"
request = ca.create_request('pending')
save(dir, 'request.pem', request[:csr])
save(dir, 'request-key.pem', request[:private_key])
# Create an intermediate for agent certs
inter_agent = ca.create_intermediate_cert('Test CA Agent Subauthority', ca.ca_cert, ca.key)
save(dir, 'intermediate-agent.pem', inter_agent[:cert])
inter_agent_crl = ca.create_crl(inter_agent[:cert], inter_agent[:private_key])
save(dir, 'intermediate-agent-crl.pem', inter_agent_crl)
# Create a leaf/entity key and cert for host "pluto" and issued by "Test CA Agent Subauthority"
pluto = ca.create_cert('pluto', inter_agent[:cert], inter_agent[:private_key])
save(dir, 'pluto.pem', pluto[:cert])
save(dir, 'pluto-key.pem', pluto[:private_key])
# Create a new root CA cert, but change the "isCA" basic constraint.
# It should not be trusted to act as a CA.
badconstraints = ca.create_cacert('Test CA')[:cert]
badconstraints.public_key = ca.ca_cert.public_key
badconstraints.extensions = []
ca.ca_cert.extensions.each do |ext|
if ext.oid == 'basicConstraints'
ef = OpenSSL::X509::ExtensionFactory.new
badconstraints.add_extension(ef.create_extension("basicConstraints","CA:FALSE", true))
else
badconstraints.add_extension(ext)
end
end
badconstraints.sign(ca.key, OpenSSL::Digest::SHA256.new)
save(dir, 'bad-basic-constraints.pem', badconstraints)
# Same as above, but create a new intermediate CA
badintconstraints = inter[:cert].dup
badintconstraints.public_key = inter[:cert].public_key
badintconstraints.extensions = []
inter[:cert].extensions.each do |ext|
if ext.oid == 'basicConstraints'
ef = OpenSSL::X509::ExtensionFactory.new
badintconstraints.add_extension(ef.create_extension("basicConstraints","CA:FALSE", true))
else
badintconstraints.add_extension(ext)
end
end
badintconstraints.sign(ca.key, OpenSSL::Digest::SHA256.new)
save(dir, 'bad-int-basic-constraints.pem', badintconstraints)
# Create a request, but replace its public key after it's signed
tampered_csr = ca.create_request('signed')[:csr]
tampered_csr.public_key = OpenSSL::PKey::RSA.new(2048).public_key
save(dir, 'tampered-csr.pem', tampered_csr)
# Create a cert issued from the real intermediate CA, but replace its
# public key
tampered_cert = ca.create_cert('signed', inter[:cert], inter[:private_key])[:cert]
tampered_cert.public_key = OpenSSL::PKey::RSA.new(2048).public_key
save(dir, 'tampered-cert.pem', tampered_cert)
end
puppet-8.4.0/tasks/manpages.rake 0000644 0052762 0001160 00000004541 14552052437 016527 0 ustar jenkins jenkins desc "Build Puppet manpages"
task :gen_manpages do
require 'puppet/face'
require 'fileutils'
Puppet.initialize_settings
helpface = Puppet::Face[:help, '0.0.1']
bins = Dir.glob(%w{bin/*})
non_face_applications = helpface.legacy_applications
faces = Puppet::Face.faces.map(&:to_s)
apps = non_face_applications + faces
ronn_args = '--manual="Puppet manual" --organization="Puppet, Inc." --roff'
unless ENV['SOURCE_DATE_EPOCH'].nil?
source_date = Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).strftime('%Y-%m-%d')
ronn_args += " --date=#{source_date}"
end
# Locate ronn
begin
require 'ronn'
rescue LoadError
abort("Run `bundle install --with documentation` to install the `ronn` gem.")
end
ronn = %x{which ronn}.chomp
unless File.executable?(ronn)
abort("Ronn does not appear to be installed")
end
%x{mkdir -p ./man/man5 ./man/man8}
%x{RUBYLIB=./lib:$RUBYLIB bin/puppet doc --reference configuration > ./man/man5/puppetconf.5.ronn}
%x{#{ronn} #{ronn_args} ./man/man5/puppetconf.5.ronn}
FileUtils.mv("./man/man5/puppetconf.5", "./man/man5/puppet.conf.5")
FileUtils.rm("./man/man5/puppetconf.5.ronn")
# Create LEGACY binary man pages (i.e. delete me for 2.8.0)
bins.each do |bin|
b = bin.gsub( /^s?bin\//, "")
%x{RUBYLIB=./lib:$RUBYLIB #{bin} --help > ./man/man8/#{b}.8.ronn}
%x{#{ronn} #{ronn_args} ./man/man8/#{b}.8.ronn}
FileUtils.rm("./man/man8/#{b}.8.ronn")
end
apps.each do |app|
%x{RUBYLIB=./lib:$RUBYLIB bin/puppet help #{app} --ronn > ./man/man8/puppet-#{app}.8.ronn}
%x{#{ronn} #{ronn_args} ./man/man8/puppet-#{app}.8.ronn}
FileUtils.rm("./man/man8/puppet-#{app}.8.ronn")
end
# Delete orphaned manpages if binary was deleted
Dir.glob(%w{./man/man8/puppet-*.8}) do |app|
appname = app.match(/puppet-(.*)\.8/)[1]
FileUtils.rm("./man/man8/puppet-#{appname}.8") unless apps.include?(appname)
end
# Vile hack: create puppet resource man page
# Currently, the useless resource face wins against puppet resource in puppet
# man. (And actually, it even gets removed from the list of legacy
# applications.) So we overwrite it with the correct man page at the end.
%x{RUBYLIB=./lib:$RUBYLIB bin/puppet resource --help > ./man/man8/puppet-resource.8.ronn}
%x{#{ronn} #{ronn_args} ./man/man8/puppet-resource.8.ronn}
FileUtils.rm("./man/man8/puppet-resource.8.ronn")
end
puppet-8.4.0/tasks/parallel.rake 0000644 0052762 0001160 00000027501 14552052437 016531 0 ustar jenkins jenkins # encoding: utf-8
require 'rubygems'
require 'thread'
begin
require 'rspec'
require 'rspec/core/formatters/helpers'
require 'etc'
rescue LoadError
# Don't define the task if we don't have rspec present
else
module Parallel
module RSpec
#
# Responsible for buffering the output of RSpec's progress formatter.
#
class ProgressFormatBuffer
attr_reader :pending_lines
attr_reader :failure_lines
attr_reader :examples
attr_reader :failures
attr_reader :pending
attr_reader :failed_example_lines
attr_reader :state
module OutputState
HEADER = 1
PROGRESS = 2
SUMMARY = 3
PENDING = 4
FAILURES = 5
DURATION = 6
COUNTS = 7
FAILED_EXAMPLES = 8
end
def initialize(io, color)
@io = io
@color = color
@state = OutputState::HEADER
@pending_lines = []
@failure_lines = []
@examples = 0
@failures = 0
@pending = 0
@failed_example_lines = []
end
def color?
@color
end
def read
# Parse and ignore the one line header
if @state == OutputState::HEADER
begin
@io.readline
rescue EOFError
return nil
end
@state = OutputState::PROGRESS
return ''
end
# If the progress has been read, parse the summary
if @state == OutputState::SUMMARY
parse_summary
return nil
end
# Read the progress output up to 128 bytes at a time
# 128 is a small enough number to show some progress, but not too small that
# we're constantly writing synchronized output
data = @io.read(128)
return nil unless data
data = @remainder + data if @remainder
# Check for the end of the progress line
if (index = data.index "\n")
@state = OutputState::SUMMARY
@remainder = data[(index+1)..-1]
data = data[0...index]
# Check for partial ANSI escape codes in colorized output
elsif @color && !data.end_with?("\e[0m") && (index = data.rindex("\e[", -6))
@remainder = data[index..-1]
data = data[0...index]
else
@remainder = nil
end
data
end
private
def parse_summary
# If there is a remainder, concat it with the next line and handle each line
unless @remainder.empty?
lines = @remainder
eof = false
begin
lines += @io.readline
rescue EOFError
eof = true
end
lines.each_line do |line|
parse_summary_line line
end
return if eof
end
# Process the rest of the lines
begin
@io.each_line do |line|
parse_summary_line line
end
rescue EOFError
end
end
def parse_summary_line(line)
line.chomp!
return if line.empty?
if line == 'Pending:'
@status = OutputState::PENDING
return
elsif line == 'Failures:'
@status = OutputState::FAILURES
return
elsif line == 'Failed examples:'
@status = OutputState::FAILED_EXAMPLES
return
elsif (line.match /^Finished in ((\d+\.?\d*) minutes?)? ?(\d+\.?\d*) seconds?$/)
@status = OutputState::DURATION
return
elsif (match = line.gsub(/\e\[\d+m/, '').match /^(\d+) examples?, (\d+) failures?(, (\d+) pending)?$/)
@status = OutputState::COUNTS
@examples = match[1].to_i
@failures = match[2].to_i
@pending = (match[4] || 0).to_i
return
end
case @status
when OutputState::PENDING
@pending_lines << line
when OutputState::FAILURES
@failure_lines << line
when OutputState::FAILED_EXAMPLES
@failed_example_lines << line
end
end
end
#
# Responsible for parallelizing spec testing.
# Optional options list will be passed to rspec.
#
class Parallelizer
# Number of processes to use
attr_reader :process_count
# Approximate size of each group of tests
attr_reader :group_size
# Options list for rspec
attr_reader :options
def initialize(process_count, group_size, color, options = [])
@process_count = process_count
@group_size = group_size
@color = color
@options = options
end
def color?
@color
end
def run
@start_time = Time.now
groups = group_specs
fail red('error: no specs were found') if groups.length == 0
begin
run_specs(groups, options)
ensure
groups.each do |file|
File.unlink(file)
end
end
end
private
def group_specs
# Spawn the rspec_grouper utility to perform the test grouping
# We do this in a separate process to limit this processes' long-running footprint
io = IO.popen("ruby util/rspec_grouper #{@group_size}")
header = true
spec_group_files = []
io.each_line do |line|
line.chomp!
header = false if line.empty?
next if header || line.empty?
spec_group_files << line
end
_, status = Process.waitpid2(io.pid)
io.close
fail red('error: no specs were found.') unless status.success?
spec_group_files
end
def run_specs(groups, options)
puts "Processing #{groups.length} spec group(s) with #{@process_count} worker(s)"
interrupted = false
success = true
worker_threads = []
group_index = -1
pids = Array.new(@process_count)
mutex = Mutex.new
# Handle SIGINT by killing child processes
original_handler = Signal.trap :SIGINT do
break if interrupted
interrupted = true
# Can't synchronize in a trap context, so read dirty
pids.each do |pid|
begin
Process.kill(:SIGKILL, pid) if pid
rescue Errno::ESRCH
end
end
puts yellow("\nshutting down...")
end
buffers = []
process_count.times do |thread_id|
worker_threads << Thread.new do
while !interrupted do
# Get the spec file for this rspec run
group = mutex.synchronize { if group_index < groups.length then groups[group_index += 1] else nil end }
break unless group && !interrupted
# Spawn the worker process with redirected output
options_string = options ? options.join(' ') : ''
io = IO.popen("ruby util/rspec_runner #{group} #{options_string}")
pids[thread_id] = io.pid
# TODO: make the buffer pluggable to handle other output formats like documentation
buffer = ProgressFormatBuffer.new(io, @color)
# Process the output
while !interrupted
output = buffer.read
break unless output && !interrupted
next if output.empty?
mutex.synchronize { print output }
end
# Kill the process if we were interrupted, just to be sure
if interrupted
begin
Process.kill(:SIGKILL, pids[thread_id])
rescue Errno::ESRCH
end
end
# Reap the process
result = Process.waitpid2(pids[thread_id])[1].success?
io.close
pids[thread_id] = nil
mutex.synchronize do
buffers << buffer
success &= result
end
end
end
end
# Join all worker threads
worker_threads.each do |thread|
thread.join
end
Signal.trap :SIGINT, original_handler
fail yellow('execution was interrupted') if interrupted
dump_summary buffers
success
end
def colorize(text, color_code)
if @color
"#{color_code}#{text}\e[0m"
else
text
end
end
def red(text)
colorize(text, "\e[31m")
end
def green(text)
colorize(text, "\e[32m")
end
def yellow(text)
colorize(text, "\e[33m")
end
def dump_summary(buffers)
puts
# Print out the pending tests
print_header = true
buffers.each do |buffer|
next if buffer.pending_lines.empty?
if print_header
puts "\nPending:"
print_header = false
end
puts buffer.pending_lines
end
# Print out the failures
print_header = true
buffers.each do |buffer|
next if buffer.failure_lines.empty?
if print_header
puts "\nFailures:"
print_header = false
end
puts
puts buffer.failure_lines
end
# Print out the run time
puts "\nFinished in #{::RSpec::Core::Formatters::Helpers.format_duration(Time.now - @start_time)}"
# Count all of the examples
examples = 0
failures = 0
pending = 0
buffers.each do |buffer|
examples += buffer.examples
failures += buffer.failures
pending += buffer.pending
end
if failures > 0
puts red(summary_count_line(examples, failures, pending))
elsif pending > 0
puts yellow(summary_count_line(examples, failures, pending))
else
puts green(summary_count_line(examples, failures, pending))
end
# Print out the failed examples
print_header = true
buffers.each do |buffer|
next if buffer.failed_example_lines.empty?
if print_header
puts "\nFailed examples:"
print_header = false
end
puts buffer.failed_example_lines
end
end
def summary_count_line(examples, failures, pending)
summary = ::RSpec::Core::Formatters::Helpers.pluralize(examples, "example")
summary << ", " << ::RSpec::Core::Formatters::Helpers.pluralize(failures, "failure")
summary << ", #{pending} pending" if pending > 0
summary
end
end
end
end
namespace 'parallel' do
def color_output?
# Check with RSpec to see if color is enabled
config = ::RSpec::Core::Configuration.new
config.error_stream = $stderr
config.output_stream = $stdout
options = ::RSpec::Core::ConfigurationOptions.new []
options.configure config
config.color
end
desc 'Runs specs in parallel. Extra args are passed to rspec.'
task 'spec', [:process_count, :group_size] do |_, args|
# Default group size in rspec examples
DEFAULT_GROUP_SIZE = 1000
process_count = [(args[:process_count] || Etc.nprocessors).to_i, 1].max
group_size = [(args[:group_size] || DEFAULT_GROUP_SIZE).to_i, 1].max
abort unless Parallel::RSpec::Parallelizer.new(process_count, group_size, color_output?, args.extras).run
end
end
end
puppet-8.4.0/tasks/ci.rake 0000644 0052762 0001160 00000001275 14552052437 015330 0 ustar jenkins jenkins require 'yaml'
require 'time'
namespace "ci" do
desc "Tar up the acceptance/ directory so that package test runs have tests to run against."
task :acceptance_artifacts => :tag_creator do
Dir.chdir("acceptance") do
rm_f "acceptance-artifacts.tar.gz"
sh "tar -czv --exclude .bundle -f acceptance-artifacts.tar.gz *"
end
end
task :tag_creator do
Dir.chdir("acceptance") do
File.open('creator.txt', 'w') do |fh|
YAML.dump({
'creator_id' => ENV['CREATOR'] || ENV['BUILD_URL'] || 'unknown',
'created_on' => Time.now.iso8601,
'commit' => (`git log -1 --oneline` rescue "unknown: #{$!}")
}, fh)
end
end
end
end
puppet-8.4.0/tasks/parser.rake 0000644 0052762 0001160 00000001313 14552052437 016222 0 ustar jenkins jenkins desc "Generate the 4.x 'future' parser"
task :gen_eparser => :require_racc do
%x{racc -olib/puppet/pops/parser/eparser.rb lib/puppet/pops/parser/egrammar.ra}
end
desc "Generate the 4.x 'future' parser with egrammar.output"
task :gen_eparser_output => :require_racc do
%x{racc -v -olib/puppet/pops/parser/eparser.rb lib/puppet/pops/parser/egrammar.ra}
end
desc "Generate the 4.x 'future' parser with debugging output"
task :gen_eparser_debug => :require_racc do
%x{racc -t -olib/puppet/pops/parser/eparser.rb lib/puppet/pops/parser/egrammar.ra}
end
task :require_racc do
begin
require 'racc'
rescue LoadError
abort("Run `bundle install --with development` to install the `racc` gem.")
end
end
puppet-8.4.0/tasks/memwalk.rake 0000644 0052762 0001160 00000013470 14552052437 016372 0 ustar jenkins jenkins # Walks the memory dumped into heap.json, and produces a graph of the memory dumped in diff.json
# If a single argument (a hex address to one object) is given, the graph is limited to this object and what references it
# The heap dumps should be in the format produced by Ruby ObjectSpace in Ruby version 2.1.0 or later.
#
# The command produces a .dot file that can be rendered with graphwiz dot into SVG. If a memwalk is performed for all
# objects in the diff.json, the output file name is memwalk.dot. If it is produced for a single address, the name of the
# output file is memwalk-
.dot
#
# The dot file can be rendered with something like: dot -Tsvg -omemwalk.svg memwalk.dot
#
desc "Process a diff.json of object ids, and a heap.json of a Ruby 2.1.0 ObjectSpace dump and produce a graph"
task :memwalk, [:id] do |t, args|
puts "Memwalk"
puts "Computing for #{args[:id] ? args[:id] : 'all'}"
@single_id = args[:id] ? args[:id].to_i(16) : nil
require 'json'
#require 'debug'
TYPE = "type".freeze
ROOT = "root".freeze
ROOT_UC = "ROOT".freeze
ADDR = "address".freeze
NODE = "NODE".freeze
STRING = "STRING".freeze
DATA = "DATA".freeze
HASH = "HASH".freeze
ARRAY = "ARRAY".freeze
OBJECT = "OBJECT".freeze
CLASS = "CLASS".freeze
allocations = {}
# An array of integer addresses of the objects to trace bindings for
diff_index = {}
puts "Reading data"
begin
puts "Reading diff"
lines = 0;
File.readlines("diff.json").each do | line |
lines += 1
diff = JSON.parse(line)
case diff[ TYPE ]
when STRING, DATA, HASH, ARRAY
# skip the strings
else
diff_index[ diff[ ADDR ].to_i(16) ] = diff
end
end
puts "Read #{lines} number of diffs"
rescue => e
raise "ERROR READING DIFF at line #{lines} #{e.message[0, 200]}"
end
begin
puts "Reading heap"
lines = 0
allocation = nil
File.readlines("heap.json").each do | line |
lines += 1
allocation = JSON.parse(line)
case allocation[ TYPE ]
when ROOT_UC
# Graph for single id must include roots, as it may be a root that holds on to the reference
# a global variable, thread, etc.
#
if @single_id
allocations[ allocation[ ROOT ] ] = allocation
end
when NODE
# skip the NODE objects - they represent the loaded ruby code
when STRING
# skip all strings - they are everywhere
else
allocations[ allocation[ ADDR ].to_i(16) ] = allocation
end
end
puts "Read #{lines} number of entries"
rescue => e
require 'debug'
puts "ERROR READING HEAP #{e.message[0, 200]}"
raise e
end
@heap = allocations
puts "Building reference index"
# References is an index from a referenced object to an array with addresses to the objects that references it
@references = Hash.new { |h, k| h[k] = [] }
REFERENCES = "references".freeze
allocations.each do |k,v|
refs = v[ REFERENCES ]
if refs.is_a?(Array)
refs.each {|addr| @references[ addr.to_i(16) ] << k }
end
end
@printed = Set.new()
def print_object(addr, entry)
# only print each node once
return unless @printed.add?(addr)
begin
if addr.is_a?(String)
@output.write( "x#{node_name(addr)} [label=\"#{node_label(addr, entry)}\\n#{addr}\"];\n")
else
@output.write( "x#{node_name(addr)} [label=\"#{node_label(addr, entry)}\\n#{addr.to_s(16)}\"];\n")
end
rescue => e
require 'debug'
raise e
end
end
def node_label(addr, entry)
if entry[ TYPE ] == OBJECT
class_ref = entry[ "class" ].to_i(16)
@heap[ class_ref ][ "name" ]
elsif entry[ TYPE ] == CLASS
"CLASS #{entry[ "name"]}"
else
entry[TYPE]
end
end
def node_name(addr)
return addr if addr.is_a? String
addr.to_s(16)
end
def print_edge(from_addr, to_addr)
@output.write("x#{node_name(from_addr)}->x#{node_name(to_addr)};\n")
end
def closure_and_edges(diff)
edges = Set.new()
walked = Set.new()
puts "Number of diffs referenced = #{diff.count {|k,_| @references[k].is_a?(Array) && @references[k].size() > 0 }}"
diff.each {|k,_| walk(k, edges, walked) }
edges.each {|e| print_edge(*e) }
end
def walk(addr, edges, walked)
if !@heap[ addr ].nil?
print_object(addr, @heap[addr])
@references [ addr ].each do |r|
walk_to_object(addr, r, edges, walked)
end
end
end
def walk_to_object(to_addr, cursor, edges, walked)
return unless walked
# if walked to an object, or everything if a single_id is the target
if @heap[ cursor ][ TYPE ] == OBJECT || (@single_id && @heap[ cursor ][ TYPE ] == ROOT_UC || @heap[ cursor ][ TYPE ] == CLASS )
# and the edge is unique
if edges.add?( [ cursor, to_addr ] )
# then we may not have visited objects this objects is being referred from
print_object(cursor, @heap[ cursor ])
# Do not follow what binds a class
if @heap[ cursor ][ TYPE ] != CLASS
@references[ cursor ].each do |r|
walk_to_object(cursor, r, edges, walked.add?(r))
walked.delete(r)
end
end
end
else
# continue search until Object
@references[cursor].each do |r|
walk_to_object(to_addr, r, edges, walked.add?(r))
end
end
end
def single_closure_and_edges(the_target)
edges = Set.new()
walked = Set.new()
walk(the_target, edges, walked)
edges.each {|e| print_edge(*e) }
end
puts "creating graph"
if @single_id
@output = File.open("memwalk-#{@single_id.to_s(16)}.dot", "w")
@output.write("digraph root {\n")
single_closure_and_edges(@single_id)
else
@output = File.open("memwalk.dot", "w")
@output.write("digraph root {\n")
closure_and_edges(diff_index)
end
@output.write("}\n")
@output.close
puts "done"
end
puppet-8.4.0/tasks/generate_ast_model.rake 0000644 0052762 0001160 00000010255 14552052437 020554 0 ustar jenkins jenkins begin
require 'puppet'
rescue LoadError
#nothing to see here
else
desc "Generate the Pcore model that represents the AST for the Puppet Language"
task :gen_pcore_ast do
Puppet::Pops.generate_ast
end
module Puppet::Pops
def self.generate_ast
Puppet.initialize_settings
env = Puppet.lookup(:environments).get(Puppet[:environment])
loaders = Loaders.new(env)
ast_pp = Pathname(__FILE__).parent.parent + 'lib/puppet/pops/model/ast.pp'
Puppet.override(:current_environment => env, :loaders => loaders) do
ast_factory = Parser::Parser.new.parse_file(ast_pp.expand_path.to_s)
ast_model = Types::TypeParser.singleton.interpret(
ast_factory.model.body, Loader::PredefinedLoader.new(loaders.find_loader(nil), 'TypeSet loader'))
ruby = Types::RubyGenerator.new.module_definition_from_typeset(ast_model)
# Replace ref() constructs to known Pcore types with directly initialized types. ref() cannot be used
# since it requires a parser (chicken-and-egg problem)
ruby.gsub!(/^module Parser\nmodule Locator\n.*\nend\nend\nmodule Model\n/m, "module Model\n")
# Remove generated RubyMethod annotations. The ruby methods are there now, no need to also have
# the annotations present.
ruby.gsub!(/^\s+'annotations' => \{\n\s+ref\('RubyMethod'\) => \{\n.*\n\s+\}\n\s+\},\n/, '')
ruby.gsub!(/ref\('([A-Za-z]+)'\)/, 'Types::P\1Type::DEFAULT')
ruby.gsub!(/ref\('Optional\[([0-9A-Za-z_]+)\]'\)/, 'Types::POptionalType.new(Types::P\1Type::DEFAULT)')
ruby.gsub!(/ref\('Array\[([0-9A-Za-z_]+)\]'\)/, 'Types::PArrayType.new(Types::P\1Type::DEFAULT)')
ruby.gsub!(/ref\('Optional\[Array\[([0-9A-Za-z_]+)\]\]'\)/,
'Types::POptionalType.new(Types::PArrayType.new(Types::P\1Type::DEFAULT))')
ruby.gsub!(/ref\('Enum(\[[^\]]+\])'\)/) do |match|
params = $1
params.gsub!(/\\'/, '\'')
"Types::PEnumType.new(#{params})"
end
# Replace ref() constructs with references to _pcore_type of the types in the module namespace
ruby.gsub!(/ref\('Puppet::AST::Locator'\)/, 'Parser::Locator::Locator19._pcore_type')
ruby.gsub!(/ref\('Puppet::AST::([0-9A-Za-z_]+)'\)/, '\1._pcore_type')
ruby.gsub!(/ref\('Optional\[Puppet::AST::([0-9A-Za-z_]+)\]'\)/, 'Types::POptionalType.new(\1._pcore_type)')
ruby.gsub!(/ref\('Array\[Puppet::AST::([0-9A-Za-z_]+)\]'\)/, 'Types::PArrayType.new(\1._pcore_type)')
ruby.gsub!(/ref\('Array\[Puppet::AST::([0-9A-Za-z_]+), 1, default\]'\)/,
'Types::PArrayType.new(\1._pcore_type, Types::PCollectionType::NOT_EMPTY_SIZE)')
# Remove the generated ref() method. It's not needed by this model
ruby.gsub!(/ def self\.ref\(type_string\)\n.*\n end\n\n/, '')
# Add Program#current method for backward compatibility
ruby.gsub!(/(attr_reader :body\n attr_reader :definitions\n attr_reader :locator)/, "\\1\n\n def current\n self\n end")
# Replace the generated registration with a registration that uses the static loader. This will
# become part of the Puppet bootstrap code and there will be no other loader until we have a
# parser.
ruby.gsub!(/^Puppet::Pops::Pcore.register_implementations\((\[[^\]]+\])\)/, <<-RUBY)
module Model
@@pcore_ast_initialized = false
def self.register_pcore_types
return if @@pcore_ast_initialized
@@pcore_ast_initialized = true
all_types = \\1
# Create and register a TypeSet that corresponds to all types in the AST model
types_map = {}
all_types.each do |type|
types_map[type._pcore_type.simple_name] = type._pcore_type
end
type_set = Types::PTypeSetType.new({
'name' => 'Puppet::AST',
'pcore_version' => '1.0.0',
'types' => types_map
})
loc = Puppet::Util.path_to_uri("\#{__FILE__}")
Loaders.static_loader.set_entry(Loader::TypedName.new(:type, 'puppet::ast', Pcore::RUNTIME_NAME_AUTHORITY), type_set, URI("\#{loc}?line=1"))
Loaders.register_static_implementations(all_types)
end
end
RUBY
ast_rb = Pathname(__FILE__).parent.parent + 'lib/puppet/pops/model/ast.rb'
File.open(ast_rb.to_s, 'w') { |f| f.write(ruby) }
end
end
end
end
puppet-8.4.0/tasks/yard.rake 0000644 0052762 0001160 00000002661 14552052437 015674 0 ustar jenkins jenkins begin
require 'yard'
namespace :doc do
desc "Clean up generated documentation"
task :clean do
rm_rf "doc"
end
desc "Generate public documentation pages for the API"
YARD::Rake::YardocTask.new(:api) do |t|
t.files = ['lib/**/*.rb']
t.options = %w{
--protected
--private
--verbose
--markup markdown
--readme README.md
--tag status
--transitive-tag status
--tag comment
--hide-tag comment
--tag dsl:"DSL"
--no-transitive-tag api
--template-path yardoc/templates
--files README_DEVELOPER.md,CO*.md,api/**/*.md
--api public
--api private
--hide-void-return
}
end
desc "Generate documentation pages for all of the code"
YARD::Rake::YardocTask.new(:all) do |t|
t.files = ['lib/**/*.rb']
t.options = %w{
--verbose
--markup markdown
--readme README.md
--tag status
--transitive-tag status
--tag comment
--hide-tag comment
--tag dsl:"DSL"
--no-transitive-tag api
--template-path yardoc/templates
--files README_DEVELOPER.md,CO*.md,api/**/*.md
--api public
--api private
--no-api
--hide-void-return
}
end
end
rescue LoadError => e
if verbose
STDERR.puts "Document generation not available without yard. #{e.message}"
end
end
puppet-8.4.0/tasks/cfpropertylist.rake 0000644 0052762 0001160 00000001432 14552052437 020021 0 ustar jenkins jenkins task 'cfpropertylist' do
if defined? Pkg::Config and Pkg::Config.project_root
cfp_version = "2.3.5"
libdir = File.join(Pkg::Config.project_root, "lib")
source = "https://github.com/ckruse/CFPropertyList/archive/cfpropertylist-#{cfp_version}.tar.gz"
target_dir = Pkg::Util::File.mktemp
target = File.join(target_dir, "cfpropertylist")
Pkg::Util::Net.fetch_uri(source, target)
Pkg::Util::File.untar_into(target, target_dir, "--strip-components 1")
mv(Dir.glob("#{File.join(target_dir, "lib")}/cfpropertylist*"), libdir)
mv(Dir.glob("#{target_dir}/{LICENSE,README,THANKS}"), File.join(libdir, "cfpropertylist"))
else
warn "It looks like the packaging tasks have not been loaded. You'll need to `rake package:bootstrap` before using this task"
end
end
puppet-8.4.0/tasks/benchmark.rake 0000644 0052762 0001160 00000012623 14552052437 016666 0 ustar jenkins jenkins require 'benchmark'
require 'tmpdir'
require 'csv'
require 'objspace'
namespace :benchmark do
def generate_scenario_tasks(location, name)
desc File.read(File.join(location, 'description'))
task name => "#{name}:run"
# Load a BenchmarkerTask to handle config of the benchmark
task_handler_file = File.expand_path(File.join(location, 'benchmarker_task.rb'))
if File.exist?(task_handler_file)
require task_handler_file
run_args = BenchmarkerTask.run_args
else
run_args = []
end
namespace name do
task :setup do
ENV['ITERATIONS'] ||= '10'
ENV['SIZE'] ||= '100'
ENV['TARGET'] ||= Dir.mktmpdir(name)
ENV['TARGET'] = File.expand_path(ENV['TARGET'])
mkdir_p(ENV['TARGET'])
require File.expand_path(File.join(location, 'benchmarker.rb'))
@benchmark = Benchmarker.new(ENV['TARGET'], ENV['SIZE'].to_i)
end
task :generate => :setup do
@benchmark.generate
@benchmark.setup
end
desc "Run the #{name} scenario."
task :run, [*run_args] => :generate do |_, args|
report = []
details = []
Benchmark.benchmark(Benchmark::CAPTION, 10, Benchmark::FORMAT, "> total:", "> avg:") do |b|
times = []
ENV['ITERATIONS'].to_i.times do |i|
start_time = Time.now.to_i
times << b.report("Run #{i + 1}") do
details << @benchmark.run(args)
end
report << [to_millis(start_time), to_millis(times.last.real), 200, true, name]
end
sum = times.inject(Benchmark::Tms.new, &:+)
[sum, sum / times.length]
end
write_csv("#{name}.samples",
%w{timestamp elapsed responsecode success name},
report)
# report details, if any were produced
if details[0].is_a?(Array) && details[0][0].is_a?(Benchmark::Tms)
# assume all entries are Tms if the first is
# turn each into a hash of label => tms (since labels are lost when doing arithmetic on Tms)
hashed = details.reduce([]) do |memo, measures|
memo << measures.reduce({}) {|memo2, measure| memo2[measure.label] = measure; memo2}
memo
end
# sum across all hashes
result = {}
hashed_totals = hashed.reduce {|memo, h| memo.merge(h) {|k, old, new| old + new }}
# average the totals
hashed_totals.keys.each {|k| hashed_totals[k] /= details.length }
min_width = 14
max_width = (hashed_totals.keys.map(&:length) << min_width).max
puts "\n"
puts sprintf("%2$*1$s %3$s", -max_width, 'Details (avg)', " user system total real")
puts "-" * (46 + max_width)
hashed_totals.sort.each {|k,v| puts sprintf("%2$*1$s %3$s", -max_width, k, v.format) }
end
end
desc "Profile a single run of the #{name} scenario."
task :profile, [:warm_up_runs, *run_args] => :generate do |_, args|
warm_up_runs = (args[:warm_up_runs] || '0').to_i
warm_up_runs.times do
@benchmark.run(args)
end
require 'ruby-prof'
result = RubyProf.profile do
@benchmark.run(args)
end
printer = RubyProf::CallTreePrinter.new(result)
printer.print(:profile => name, :path => ENV['TARGET'])
path = File.join(ENV['TARGET'], "#{name}.callgrind.out.#{$$}")
puts "Generated callgrind file: #{path}"
end
desc "Print a memory profile of the #{name} scenario."
task :memory_profile, [*run_args] => :generate do |_, args|
begin
require 'memory_profiler'
rescue LoadError
abort("Run `bundle install --with development` to install the 'memory_profiler' gem.")
end
report = MemoryProfiler.report do
@benchmark.run(args)
end
path = "mem_profile_#{$PID}"
report.pretty_print(to_file: path)
puts "Generated memory profile: #{File.absolute_path(path)}"
end
desc "Generate a heap dump with object allocation tracing of the #{name} scenario."
task :heap_dump, [*run_args] => :generate do |_, args|
ObjectSpace.trace_object_allocations_start
if ENV['DISABLE_GC']
GC.disable
end
@benchmark.run(args)
unless ENV['DISABLE_GC']
GC.start
end
path = "heap_#{$PID}.json"
File.open(path, 'w') do |file|
ObjectSpace.dump_all(output: file)
end
puts "Generated heap dump: #{File.absolute_path(path)}"
end
def to_millis(seconds)
(seconds * 1000).round
end
def write_csv(file, header, data)
CSV.open(file, 'w') do |csv|
csv << header
data.each do |line|
csv << line
end
end
end
end
end
scenarios = []
Dir.glob('benchmarks/*') do |location|
name = File.basename(location)
scenarios << name
generate_scenario_tasks(location, File.basename(location))
end
namespace :all do
desc "Profile all of the scenarios. (#{scenarios.join(', ')})"
task :profile do
scenarios.each do |name|
sh "rake benchmark:#{name}:profile"
end
end
desc "Run all of the scenarios. (#{scenarios.join(', ')})"
task :run do
scenarios.each do |name|
sh "rake benchmark:#{name}:run"
end
end
end
end
puppet-8.4.0/locales/ 0000755 0052762 0001160 00000000000 14552052637 014363 5 ustar jenkins jenkins puppet-8.4.0/locales/config.yaml 0000644 0052762 0001160 00000002350 14552052437 016512 0 ustar jenkins jenkins ---
# This is the project-specific configuration file for setting up
# fast_gettext for your project.
gettext:
# This is used for the name of the .pot and .po files; they will be
# called .pot
project_name: 'puppet'
# This is used in comments in the .pot and .po files to indicate what
# project the files belong to and should be a little more descriptive than
#
package_name: Puppet automation framework
# The locale that the default messages in the .pot file are in
default_locale: en
# The address for sending bug reports.
bugs_address: https://tickets.puppetlabs.com
# The holder of the copyright.
copyright_holder: Puppet, Inc.
# Patterns for +Dir.glob+ used to find all files that might contain
# translatable content, relative to the project root directory
source_files:
- 'lib/**/*.rb'
# Patterns for +Dir.glob+ used to find all files contained in
# `source_files` that should be ignored when searching for translatable
# content, relative to the project root directory
exclude_files:
- 'lib/puppet/pops/types/type_formatter.rb'
# The semantic_puppet gem is temporarily vendored (PUP-7114), and it
# handles its own translation.
- 'lib/puppet/vendor/**/*.rb'
puppet-8.4.0/locales/en/ 0000755 0052762 0001160 00000000000 14552052637 014765 5 ustar jenkins jenkins puppet-8.4.0/locales/en/puppet.po 0000644 0052762 0001160 00000001276 14552052437 016646 0 ustar jenkins jenkins # English translations for Puppet automation framework package.
# Copyright (C) 2017 Puppet, Inc.
# This file is distributed under the same license as the Puppet automation framework package.
# Automatically generated, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: Puppet automation framework 5.3.3-51-gc11ddbe\n"
"\n"
"Report-Msgid-Bugs-To: https://tickets.puppetlabs.com\n"
"POT-Creation-Date: 2017-11-17 12:09+0000\n"
"PO-Revision-Date: 2017-11-17 12:09+0000\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
puppet-8.4.0/locales/puppet.pot 0000644 0052762 0001160 00001130504 14552052437 016426 0 ustar jenkins jenkins # SOME DESCRIPTIVE TITLE.
# Copyright (C) 2023 Puppet, Inc.
# This file is distributed under the same license as the Puppet automation framework package.
# FIRST AUTHOR , 2023.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Puppet automation framework 8.3.1-124-gc92197235b\n"
"\n"
"Report-Msgid-Bugs-To: https://tickets.puppetlabs.com\n"
"POT-Creation-Date: 2023-12-05 22:36+0000\n"
"PO-Revision-Date: 2023-12-05 22:36+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#. TRANSLATORS 'lookup' is a puppet function and should not be translated
#: ../lib/hiera/puppet_function.rb:65
msgid "The function '%{class_name}' is deprecated in favor of using 'lookup'."
msgstr ""
#: ../lib/hiera/puppet_function.rb:66
msgid "See https://puppet.com/docs/puppet/%{minor_version}/deprecated_language.html"
msgstr ""
#: ../lib/hiera/scope.rb:47 ../lib/puppet/parser/scope.rb:535 ../lib/puppet/parser/scope.rb:539
msgid "Variable: %{name}"
msgstr ""
#: ../lib/hiera/scope.rb:48 ../lib/hiera/scope.rb:50 ../lib/puppet/parser/scope.rb:536 ../lib/puppet/parser/scope.rb:542
msgid "Undefined variable '%{name}'; %{reason}"
msgstr ""
#: ../lib/hiera_puppet.rb:15
msgid "Could not find data item %{key} in any Hiera data file and no default supplied"
msgstr ""
#: ../lib/hiera_puppet.rb:42
msgid "Please supply a parameter to perform a Hiera lookup"
msgstr ""
#: ../lib/hiera_puppet.rb:73 ../lib/puppet/indirector/hiera.rb:85
msgid "Config file %{hiera_config} not found, using Hiera defaults"
msgstr ""
#: ../lib/puppet.rb:131
msgid "Support for ruby version %{version} is deprecated and will be removed in a future release. See https://puppet.com/docs/puppet/latest/system_requirements.html for a list of supported ruby versions."
msgstr ""
#: ../lib/puppet.rb:217
msgid "The environmentpath setting cannot be empty or nil."
msgstr ""
#: ../lib/puppet/agent.rb:94
msgid "Run of %{client_class} already in progress; skipping (%{lockfile_path} exists)"
msgstr ""
#: ../lib/puppet/agent.rb:97
msgid "Exiting now because the maxwaitforlock timeout has been exceeded."
msgstr ""
#: ../lib/puppet/agent.rb:100
msgid "Another puppet instance is already running; --waitforlock flag used, waiting for running instance to finish."
msgstr ""
#: ../lib/puppet/agent.rb:101 ../lib/puppet/ssl/state_machine.rb:414 ../lib/puppet/ssl/state_machine.rb:445
msgid "Will try again in %{time} seconds."
msgstr ""
#: ../lib/puppet/agent.rb:106
msgid "Execution of %{client_class} did not complete within %{runtimeout} seconds and was terminated."
msgstr ""
#: ../lib/puppet/agent.rb:110
msgid "Could not run %{client_class}: %{detail}"
msgstr ""
#: ../lib/puppet/agent.rb:119
msgid "Shutdown/restart in progress (%{status}); skipping run"
msgstr ""
#: ../lib/puppet/agent.rb:137
msgid "puppet agent: applying configuration"
msgstr ""
#: ../lib/puppet/agent.rb:160
msgid "Could not create instance of %{client_class}: %{detail}"
msgstr ""
#: ../lib/puppet/agent.rb:175
msgid ""
"Skipping run of %{client_class}; administratively disabled (Reason: '%{disable_message}');\n"
"Use 'puppet agent --enable' to re-enable."
msgstr ""
#: ../lib/puppet/agent/disabler.rb:20
msgid "Enabling Puppet."
msgstr ""
#: ../lib/puppet/agent/disabler.rb:27
msgid "Disabling Puppet."
msgstr ""
#: ../lib/puppet/agent/locker.rb:27
msgid "Failed to acquire lock"
msgstr ""
#: ../lib/puppet/application.rb:232
msgid "Unable to find application '%{application_name}'. %{error}"
msgstr ""
#: ../lib/puppet/application.rb:253
msgid "Unable to load application class '%{class_name}' from file 'puppet/application/%{application_name}.rb'"
msgstr ""
#: ../lib/puppet/application.rb:306
msgid "Invalid environment mode '%{mode_name}'"
msgstr ""
#: ../lib/puppet/application.rb:406
msgid "Could not get application-specific default settings"
msgstr ""
#: ../lib/puppet/application.rb:412
msgid "Could not initialize"
msgstr ""
#: ../lib/puppet/application.rb:413
msgid "Could not parse application options"
msgstr ""
#: ../lib/puppet/application.rb:414
msgid "Could not prepare for execution"
msgstr ""
#: ../lib/puppet/application.rb:417
msgid "`puppet %{name}` is deprecated and will be removed in a future release."
msgstr ""
#: ../lib/puppet/application.rb:420
msgid "Could not configure routes from %{route_file}"
msgstr ""
#: ../lib/puppet/application.rb:421
msgid "Could not log runtime debug info"
msgstr ""
#: ../lib/puppet/application.rb:422
msgid "Could not run"
msgstr ""
#: ../lib/puppet/application.rb:431
msgid "No valid command or main"
msgstr ""
#: ../lib/puppet/application.rb:487
msgid "Could not set logdest to %{dest}."
msgstr ""
#: ../lib/puppet/application.rb:585
msgid "No help available for puppet %{app_name}"
msgstr ""
#: ../lib/puppet/application/agent.rb:25 ../lib/puppet/application/device.rb:25
msgid "Cancelling startup"
msgstr ""
#: ../lib/puppet/application/agent.rb:84
msgid "The puppet agent daemon"
msgstr ""
#: ../lib/puppet/application/agent.rb:423
msgid "Fingerprint asked but neither the certificate, nor the certificate request have been issued"
msgstr ""
#: ../lib/puppet/application/agent.rb:428
msgid "Failed to generate fingerprint: %{message}"
msgstr ""
#: ../lib/puppet/application/agent.rb:451
msgid "Starting Puppet client version %{version}"
msgstr ""
#: ../lib/puppet/application/agent.rb:467
msgid "The puppet agent command does not take parameters"
msgstr ""
#: ../lib/puppet/application/apply.rb:38
msgid "Apply Puppet manifests locally"
msgstr ""
#. TRANSLATORS "puppet apply" is a program command and should not be translated
#. TRANSLATORS "puppet apply" is a program command and should not be translated
#: ../lib/puppet/application/apply.rb:213 ../lib/puppet/application/apply.rb:341
msgid "For puppet apply"
msgstr ""
#: ../lib/puppet/application/apply.rb:221
msgid "%{file} is not readable"
msgstr ""
#: ../lib/puppet/application/apply.rb:307 ../lib/puppet/application/script.rb:242
msgid "Exiting"
msgstr ""
#: ../lib/puppet/application/apply.rb:351
msgid "Could not deserialize catalog from %{format}: %{detail}"
msgstr ""
#: ../lib/puppet/application/apply.rb:372 ../lib/puppet/application/script.rb:147
msgid "Could not find facts for %{node}"
msgstr ""
#: ../lib/puppet/application/apply.rb:384 ../lib/puppet/application/script.rb:155
msgid "Could not find node %{node}"
msgstr ""
#: ../lib/puppet/application/apply.rb:397 ../lib/puppet/application/script.rb:140
msgid "Could not find file %{manifest}"
msgstr ""
#: ../lib/puppet/application/apply.rb:398
msgid "Only one file can be applied per run. Skipping %{files}"
msgstr ""
#: ../lib/puppet/application/describe.rb:178
msgid "Display help about resource types"
msgstr ""
#: ../lib/puppet/application/device.rb:84
msgid "Manage remote network devices"
msgstr ""
#: ../lib/puppet/application/device.rb:233
msgid "resource command requires target"
msgstr ""
#: ../lib/puppet/application/device.rb:236
msgid "facts command requires target"
msgstr ""
#: ../lib/puppet/application/device.rb:239
msgid "missing argument: --target is required when using --apply"
msgstr ""
#: ../lib/puppet/application/device.rb:240
msgid "%{file} does not exist, cannot apply"
msgstr ""
#: ../lib/puppet/application/device.rb:258
msgid "Target device / certificate '%{target}' not found in %{config}"
msgstr ""
#: ../lib/puppet/application/device.rb:260
msgid "No device found in %{config}"
msgstr ""
#: ../lib/puppet/application/device.rb:317
msgid "retrieving resource: %{resource} from %{target} at %{scheme}%{url_host}%{port}%{url_path}"
msgstr ""
#: ../lib/puppet/application/device.rb:332
msgid "retrieving facts from %{target} at %{scheme}%{url_host}%{port}%{url_path}"
msgstr ""
#: ../lib/puppet/application/device.rb:355
msgid "starting applying configuration to %{target} at %{scheme}%{url_host}%{port}%{url_path}"
msgstr ""
#: ../lib/puppet/application/device.rb:391 ../lib/puppet/application/resource.rb:202
msgid "You must specify the type to display"
msgstr ""
#: ../lib/puppet/application/device.rb:392 ../lib/puppet/application/resource.rb:203
msgid "Could not find type %{type}"
msgstr ""
#: ../lib/puppet/application/doc.rb:29
msgid "Invalid output format %{arg}"
msgstr ""
#: ../lib/puppet/application/doc.rb:38
msgid "Invalid output mode %{arg}"
msgstr ""
#: ../lib/puppet/application/doc.rb:54
msgid "Generate Puppet references"
msgstr ""
#: ../lib/puppet/application/doc.rb:136
msgid "scanning: %{files}"
msgstr ""
#: ../lib/puppet/application/doc.rb:148
msgid "Could not generate documentation: %{detail}"
msgstr ""
#: ../lib/puppet/application/doc.rb:161
msgid "Could not find reference %{name}"
msgstr ""
#: ../lib/puppet/application/doc.rb:167
msgid "Could not generate reference %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/application/face_base.rb:36
msgid "I don't know how to render '%{format}'"
msgstr ""
#: ../lib/puppet/application/face_base.rb:58
msgid "Cancelling Face"
msgstr ""
#: ../lib/puppet/application/face_base.rb:137
msgid "'%{face}' has no %{action} action. See `puppet help %{face}`."
msgstr ""
#: ../lib/puppet/application/face_base.rb:215
msgid "%{face} does not respond to action %{arg}"
msgstr ""
#: ../lib/puppet/application/face_base.rb:248
msgid "puppet %{face} %{action} takes %{arg_count} argument, but you gave %{given_count}"
msgid_plural "puppet %{face} %{action} takes %{arg_count} arguments, but you gave %{given_count}"
msgstr[0] ""
msgstr[1] ""
#: ../lib/puppet/application/face_base.rb:253
msgid "'puppet %{face}' is deprecated and will be removed in a future release"
msgstr ""
#: ../lib/puppet/application/face_base.rb:272
msgid "Try 'puppet help %{face} %{action}' for usage"
msgstr ""
#: ../lib/puppet/application/filebucket.rb:18
msgid "Store and retrieve files in a filebucket"
msgstr ""
#: ../lib/puppet/application/filebucket.rb:227
msgid "You must specify a file to back up"
msgstr ""
#: ../lib/puppet/application/filebucket.rb:231
msgid "%{file}: no such file"
msgstr ""
#: ../lib/puppet/application/filebucket.rb:235
msgid "%{file}: cannot read file"
msgstr ""
#: ../lib/puppet/application/filebucket.rb:257 ../lib/puppet/application/filebucket.rb:280
msgid "Need exactly two arguments: filebucket diff "
msgstr ""
#: ../lib/puppet/application/filebucket.rb:277
msgid "Comparing %{checksum_a} %{checksum_b} %{file_a} %{file_b}"
msgstr ""
#: ../lib/puppet/application/filebucket.rb:291
msgid "Cancelling"
msgstr ""
#: ../lib/puppet/application/lookup.rb:9
msgid "Run 'puppet lookup --help' for more details"
msgstr ""
#: ../lib/puppet/application/lookup.rb:103
msgid "Interactive Hiera lookup"
msgstr ""
#: ../lib/puppet/application/lookup.rb:280
msgid ""
"The options %{deep_merge_opts} are only available with '--merge deep'\n"
"%{run_help}"
msgstr ""
#: ../lib/puppet/application/lookup.rb:291
msgid ""
"The --merge option only accepts %{strategies}, or %{last_strategy}\n"
"%{run_help}"
msgstr ""
#: ../lib/puppet/application/lookup.rb:316
msgid "No keys were given to lookup."
msgstr ""
#: ../lib/puppet/application/lookup.rb:324
msgid "Unknown rendering format '%{format}'"
msgstr ""
#: ../lib/puppet/application/lookup.rb:365
msgid "Incorrectly formatted data in %{fact_file} given via the --facts flag (only accepts yaml and json files)"
msgstr ""
#: ../lib/puppet/application/lookup.rb:370
msgid "When overriding any of the %{trusted_facts_list} facts with %{fact_file} given via the --facts flag, they must all be overridden."
msgstr ""
#: ../lib/puppet/application/lookup.rb:397
msgid "CA is not available, the operation will continue without using trusted facts."
msgstr ""
#: ../lib/puppet/application/lookup.rb:428
msgid "No facts available for target node: %{node}"
msgstr ""
#: ../lib/puppet/application/resource.rb:35
msgid "The resource abstraction layer shell"
msgstr ""
#: ../lib/puppet/application/resource.rb:146
msgid "Editing with Yaml output is not supported"
msgstr ""
#: ../lib/puppet/application/resource.rb:210
msgid "Invalid parameter setting %{setting}"
msgstr ""
#: ../lib/puppet/application/resource.rb:242
msgid "Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc"
msgstr ""
#: ../lib/puppet/application/script.rb:21
msgid "Run a puppet manifests as a script without compiling a catalog"
msgstr ""
#: ../lib/puppet/application/script.rb:127
msgid "Bolt must be installed to use the script application"
msgstr ""
#: ../lib/puppet/application/script.rb:141
msgid "Only one file can be used per run. Skipping %{files}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:10
msgid "Manage SSL keys and certificates for puppet SSL clients"
msgstr ""
#: ../lib/puppet/application/ssl.rb:112
msgid "An action must be specified."
msgstr ""
#: ../lib/puppet/application/ssl.rb:136 ../lib/puppet/application/ssl.rb:143
msgid "The certificate for '%{name}' has not yet been signed"
msgstr ""
#: ../lib/puppet/application/ssl.rb:166
msgid "Completed SSL initialization"
msgstr ""
#: ../lib/puppet/application/ssl.rb:170
msgid "Unknown action '%{action}'"
msgstr ""
#: ../lib/puppet/application/ssl.rb:191
msgid "Submitted certificate request for '%{name}' to %{url}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:194
msgid "Could not submit certificate request for '%{name}' to %{url} due to a conflict on the server"
msgstr ""
#: ../lib/puppet/application/ssl.rb:196 ../lib/puppet/application/ssl.rb:199
msgid "Failed to submit certificate request: %{message}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:211
msgid "Generated certificate request in '%{path}'"
msgstr ""
#: ../lib/puppet/application/ssl.rb:213
msgid "Failed to generate certificate request: %{message}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:221
msgid "Downloading certificate '%{name}' from %{url}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:225
msgid "Downloaded certificate '%{name}' with fingerprint %{fingerprint}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:238 ../lib/puppet/application/ssl.rb:241
msgid "Failed to download certificate: %{message}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:270 ../lib/puppet/application/ssl.rb:273
msgid "Failed to connect to the CA to determine if certificate %{certname} has been cleaned"
msgstr ""
#: ../lib/puppet/application/ssl.rb:300
msgid "Removed %{label} %{path}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:317 ../lib/puppet/ssl/state_machine.rb:273
msgid "Creating a new EC SSL key for %{name} using curve %{curve}"
msgstr ""
#: ../lib/puppet/application/ssl.rb:320
msgid "Creating a new SSL key for %{name}"
msgstr ""
#: ../lib/puppet/configurer.rb:22
msgid "Puppet configuration client"
msgstr ""
#: ../lib/puppet/configurer.rb:45
msgid "Removing corrupt state file %{file}: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:50
msgid "Cannot remove %{file}: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:81
msgid "Using cached catalog from environment '%{environment}'"
msgstr ""
#: ../lib/puppet/configurer.rb:87
msgid "Not using cache on failed catalog"
msgstr ""
#: ../lib/puppet/configurer.rb:96
msgid "Not using cached catalog because its environment '%{catalog_env}' does not match '%{local_env}'"
msgstr ""
#: ../lib/puppet/configurer.rb:101 ../lib/puppet/configurer.rb:276
msgid "Using cached catalog from environment '%{catalog_env}'"
msgstr ""
#: ../lib/puppet/configurer.rb:134
msgid "The current total number of facts: %{size} exceeds the number of facts limit: %{max_size}"
msgstr ""
#: ../lib/puppet/configurer.rb:138
msgid "Fact %{name} with length: '%{length}' exceeds the length limit: %{limit}"
msgstr ""
#: ../lib/puppet/configurer.rb:142
msgid "The current number of top level facts: %{size} exceeds the top facts limit: %{max_size}"
msgstr ""
#: ../lib/puppet/configurer.rb:146
msgid "Fact value '%{value}' with the value length: '%{length}' exceeds the value length limit: %{max_length}"
msgstr ""
#: ../lib/puppet/configurer.rb:150
msgid "Payload with the current size of: '%{payload}' exceeds the payload size limit: %{max_size}"
msgstr ""
#: ../lib/puppet/configurer.rb:188
msgid "The size of the payload is %{payload}"
msgstr ""
#: ../lib/puppet/configurer.rb:218
msgid "The total number of facts registered is %{number_of_facts}"
msgstr ""
#: ../lib/puppet/configurer.rb:269
msgid "Could not retrieve catalog; skipping run"
msgstr ""
#: ../lib/puppet/configurer.rb:285
msgid "Applied catalog in %{seconds} seconds"
msgstr ""
#: ../lib/puppet/configurer.rb:319
msgid "Could not select a functional puppet server from server_list: '%{server_list}'"
msgstr ""
#. TRANSLATORS 'server_list' is the name of a setting and should not be translated
#: ../lib/puppet/configurer.rb:333
msgid "Selected puppet server from the `server_list` setting: %{server}:%{port}"
msgstr ""
#: ../lib/puppet/configurer.rb:370
msgid "Local environment: '%{local_env}' doesn't match the environment of the cached catalog '%{catalog_env}', switching agent to '%{catalog_env}'."
msgstr ""
#: ../lib/puppet/configurer.rb:393
msgid "Environment not passed via CLI and no catalog was given, attempting to find out the last server-specified environment"
msgstr ""
#: ../lib/puppet/configurer.rb:397
msgid "Requesting environment from the server"
msgstr ""
#: ../lib/puppet/configurer.rb:407
msgid "Could not find a usable environment in the lastrunfile. Either the file does not exist, does not have the required keys, or the values of 'initial_environment' and 'converged_environment' are identical."
msgstr ""
#: ../lib/puppet/configurer.rb:411
msgid "Using environment '%{env}'"
msgstr ""
#: ../lib/puppet/configurer.rb:435
msgid "Not using catalog because its environment '%{catalog_env}' does not match agent specified environment '%{local_env}' and strict_environment_mode is set"
msgstr ""
#: ../lib/puppet/configurer.rb:446
msgid "Catalog environment didn't stabilize after %{tries} fetches, aborting run"
msgstr ""
#: ../lib/puppet/configurer.rb:448
msgid "Local environment: '%{local_env}' doesn't match server specified environment '%{catalog_env}', restarting agent run with environment '%{catalog_env}'"
msgstr ""
#: ../lib/puppet/configurer.rb:504
msgid "Failed to apply catalog: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:536
msgid "Environment '%{environment}' not found on server, aborting run."
msgstr ""
#: ../lib/puppet/configurer.rb:538
msgid "Environment '%{environment}' not found on server, skipping initial pluginsync."
msgstr ""
#: ../lib/puppet/configurer.rb:556 ../lib/puppet/http/resolver/server_list.rb:65 ../lib/puppet/http/resolver/server_list.rb:69
msgid "Puppet server %{host}:%{port} is unavailable: %{code} %{reason}"
msgstr ""
#. TRANSLATORS 'server_list' is the name of a setting and should not be translated
#: ../lib/puppet/configurer.rb:560 ../lib/puppet/http/resolver/server_list.rb:74 ../lib/puppet/http/resolver/server_list.rb:77
msgid "Unable to connect to server from server_list setting: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:585
msgid "Successfully loaded last environment from the lastrunfile"
msgstr ""
#: ../lib/puppet/configurer.rb:589
msgid "Found last server-specified environment: %{environment}"
msgstr ""
#: ../lib/puppet/configurer.rb:592
msgid "Could not find last server-specified environment: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:612
msgid "Local environment: '%{local_env}' doesn't match server specified node environment '%{node_env}', switching agent to '%{node_env}'."
msgstr ""
#: ../lib/puppet/configurer.rb:620
msgid "Unable to fetch my node definition, but the agent run will continue:"
msgstr ""
#: ../lib/puppet/configurer.rb:639 ../lib/puppet/face/report.rb:48
msgid "Could not send report: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:648
msgid "Could not save last run local report: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:667
msgid "Uploading facts for %{node} to %{server}"
msgstr ""
#: ../lib/puppet/configurer.rb:675
msgid "Failed to submit facts: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:690
msgid "Could not run command from %{setting}: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:719
msgid "Could not retrieve catalog from cache: %{detail}"
msgstr ""
#: ../lib/puppet/configurer.rb:741
msgid "Could not retrieve catalog from remote server: %{detail}"
msgstr ""
#: ../lib/puppet/configurer/downloader.rb:10
msgid "Retrieving %{name}"
msgstr ""
#: ../lib/puppet/configurer/downloader.rb:22
msgid "Failed to retrieve %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/configurer/downloader.rb:33
msgid "Could not retrieve %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/configurer/fact_handler.rb:25
msgid "Could not retrieve local facts: %{detail}"
msgstr ""
#: ../lib/puppet/context.rb:78
msgid "Mark for '%{name}' already exists"
msgstr ""
#: ../lib/puppet/context.rb:93
msgid "Unknown mark '%{name}'"
msgstr ""
#: ../lib/puppet/context.rb:112 ../lib/puppet/context.rb:170
msgid "Unable to lookup '%{name}'"
msgstr ""
#: ../lib/puppet/context.rb:121
msgid "Attempted to pop, but already at root of the context stack."
msgstr ""
#: ../lib/puppet/context/trusted_information.rb:54
msgid "TrustedInformation expected a certificate, but none was given."
msgstr ""
#: ../lib/puppet/context/trusted_information.rb:105 ../lib/puppet/parser/scope.rb:841
msgid "Unsupported data type: '%{klass}'"
msgstr ""
#: ../lib/puppet/daemon.rb:27
msgid "Daemons must have an agent"
msgstr ""
#: ../lib/puppet/daemon.rb:82
msgid "Cannot reexec unless ARGV arguments are set"
msgstr ""
#: ../lib/puppet/datatypes.rb:134
msgid "Data Type Load Error for type '%{type_name}': %{message}"
msgstr ""
#: ../lib/puppet/datatypes.rb:157
msgid "a data type must have an interface"
msgstr ""
#: ../lib/puppet/datatypes.rb:196
msgid "a data type can only have one interface"
msgstr ""
#: ../lib/puppet/datatypes.rb:201 ../lib/puppet/datatypes.rb:206
msgid "a data type can only have one implementation"
msgstr ""
#: ../lib/puppet/defaults.rb:169
msgid "Cannot disable unrecognized warning types '%{invalid}'."
msgstr ""
#: ../lib/puppet/defaults.rb:170
msgid "Valid values are '%{values}'."
msgstr ""
#. TRANSLATORS 'data_binding_terminus' is a setting and should not be translated
#: ../lib/puppet/defaults.rb:561
msgid "Setting 'data_binding_terminus' is deprecated."
msgstr ""
#. TRANSLATORS 'hiera' should not be translated
#: ../lib/puppet/defaults.rb:563
msgid "Convert custom terminus to hiera 5 API."
msgstr ""
#. TRANSLATORS 'environment_data_provider' is a setting and should not be translated
#: ../lib/puppet/defaults.rb:757
msgid "Setting 'environment_data_provider' is deprecated."
msgstr ""
#: ../lib/puppet/defaults.rb:848
msgid "Certificate names must be lower case"
msgstr ""
#: ../lib/puppet/defaults.rb:1107 ../lib/puppet/settings/enum_setting.rb:14 ../lib/puppet/settings/symbolic_enum_setting.rb:15
msgid "Invalid value '%{value}' for parameter %{name}. Allowed values are '%{allowed_values}'"
msgstr ""
#. TRANSLATORS 'pluginsync' is a setting and should not be translated
#: ../lib/puppet/defaults.rb:2041
msgid "Setting 'pluginsync' is deprecated."
msgstr ""
#: ../lib/puppet/error.rb:78
msgid "Could not parse for environment %{environment}: %{message}"
msgstr ""
#: ../lib/puppet/error.rb:79 ../lib/puppet/parser/compiler.rb:41
msgid "%{message} on node %{node}"
msgstr ""
#: ../lib/puppet/face/catalog.rb:8
msgid "Compile, save, view, and convert catalogs."
msgstr ""
#: ../lib/puppet/face/catalog.rb:88
msgid "Compile a catalog."
msgstr ""
#: ../lib/puppet/face/catalog/select.rb:5
msgid "Retrieve a catalog and filter it for resources of a given type."
msgstr ""
#: ../lib/puppet/face/catalog/select.rb:6
msgid ""
msgstr ""
#: ../lib/puppet/face/catalog/select.rb:44
msgid "no matching resources found"
msgstr ""
#: ../lib/puppet/face/config.rb:8 ../lib/puppet/face/epp.rb:9 ../lib/puppet/face/facts.rb:7 ../lib/puppet/face/generate.rb:8 ../lib/puppet/face/help.rb:10 ../lib/puppet/face/module.rb:10 ../lib/puppet/face/node.rb:5 ../lib/puppet/face/parser.rb:7 ../lib/puppet/face/plugin.rb:7 ../lib/puppet/face/report.rb:6 ../lib/puppet/face/resource.rb:6
msgid "Apache 2 license; see COPYING"
msgstr ""
#: ../lib/puppet/face/config.rb:10
msgid "Interact with Puppet's settings."
msgstr ""
#: ../lib/puppet/face/config.rb:18
msgid "SECTION_NAME"
msgstr ""
#: ../lib/puppet/face/config.rb:20
msgid "The section of the configuration file to interact with."
msgstr ""
#: ../lib/puppet/face/config.rb:38
msgid "Examine Puppet's current settings."
msgstr ""
#: ../lib/puppet/face/config.rb:39
msgid "all | [ ...]"
msgstr ""
#: ../lib/puppet/face/config.rb:100
msgid "No section specified; defaulting to '%{section_name}'."
msgstr ""
#. TRANSLATORS '--section' is a command line option and should not be translated
#: ../lib/puppet/face/config.rb:103
msgid "Set the config section by using the `--section` flag."
msgstr ""
#. TRANSLATORS `puppet config --section user print foo` is a command line example and should not be translated
#: ../lib/puppet/face/config.rb:105
msgid "For example, `puppet config --section user print foo`."
msgstr ""
#: ../lib/puppet/face/config.rb:106
msgid "For more information, see https://puppet.com/docs/puppet/latest/configuration.html"
msgstr ""
#: ../lib/puppet/face/config.rb:113
msgid "Resolving settings from section '%{section_name}' in environment '%{environment_name}'"
msgstr ""
#: ../lib/puppet/face/config.rb:118
msgid "Set Puppet's settings."
msgstr ""
#: ../lib/puppet/face/config.rb:119
msgid "[setting_name] [setting_value]"
msgstr ""
#: ../lib/puppet/face/config.rb:187
msgid "Deleted setting from '%{section_name}': '%{setting_string}', and adding it to 'server' section"
msgstr ""
#: ../lib/puppet/face/config.rb:202
msgid "Delete a Puppet setting."
msgstr ""
#: ../lib/puppet/face/config.rb:203
msgid ""
msgstr ""
#: ../lib/puppet/face/config.rb:237 ../lib/puppet/face/config.rb:241 ../lib/puppet/face/config.rb:252
msgid "Deleted setting from '%{section_name}': '%{setting_string}'"
msgstr ""
#: ../lib/puppet/face/config.rb:255
msgid "No setting found in configuration file for section '%{section_name}' setting name '%{name}'"
msgstr ""
#. TRANSLATORS the 'puppet.conf' is a specific file and should not be translated
#: ../lib/puppet/face/config.rb:263
msgid "The puppet.conf file does not exist %{puppet_conf}"
msgstr ""
#: ../lib/puppet/face/epp.rb:11
msgid "Interact directly with the EPP template parser/renderer."
msgstr ""
#: ../lib/puppet/face/epp.rb:14
msgid "Validate the syntax of one or more EPP templates."
msgstr ""
#: ../lib/puppet/face/epp.rb:15
msgid "[] [ ...]"
msgstr ""
#: ../lib/puppet/face/epp.rb:16
msgid "Nothing, or encountered syntax errors."
msgstr ""
#: ../lib/puppet/face/epp.rb:35
msgid "Whether or not to continue after errors are reported for a template."
msgstr ""
#: ../lib/puppet/face/epp.rb:79
msgid "No template specified. No action taken"
msgstr ""
#: ../lib/puppet/face/epp.rb:96 ../lib/puppet/face/epp.rb:199
msgid ""
"One or more file(s) specified did not exist:\n"
"%{missing_files_list}"
msgstr ""
#: ../lib/puppet/face/epp.rb:100
msgid "Errors while validating epp"
msgstr ""
#: ../lib/puppet/face/epp.rb:107
msgid "Outputs a dump of the internal template parse tree for debugging"
msgstr ""
#: ../lib/puppet/face/epp.rb:109 ../lib/puppet/face/parser.rb:107
msgid "A dump of the resulting AST model unless there are syntax or validation errors."
msgstr ""
#: ../lib/puppet/face/epp.rb:138 ../lib/puppet/face/epp.rb:310 ../lib/puppet/face/parser.rb:128
msgid ""
msgstr ""
#: ../lib/puppet/face/epp.rb:140
msgid "Dump one epp source expression given on the command line."
msgstr ""
#: ../lib/puppet/face/epp.rb:144
msgid "Whether or not to validate the parsed result, if no-validate only syntax errors are reported."
msgstr ""
#: ../lib/puppet/face/epp.rb:147 ../lib/puppet/face/parser.rb:137
msgid ""
msgstr ""
#: ../lib/puppet/face/epp.rb:148 ../lib/puppet/face/parser.rb:138
msgid "Get result in 'old' (deprecated format), 'pn' (new format), or 'json' (new format in JSON)."
msgstr ""
#: ../lib/puppet/face/epp.rb:152 ../lib/puppet/face/parser.rb:142
msgid "Pretty print output. Only applicable together with --format pn or json"
msgstr ""
#: ../lib/puppet/face/epp.rb:156
msgid "Whether or not to show a file name header between files."
msgstr ""
#: ../lib/puppet/face/epp.rb:180 ../lib/puppet/face/parser.rb:154
msgid "No input to parse given on command line or stdin"
msgstr ""
#: ../lib/puppet/face/epp.rb:208
msgid "Renders an epp template as text"
msgstr ""
#: ../lib/puppet/face/epp.rb:210
msgid "A rendered result of one or more given templates."
msgstr ""
#: ../lib/puppet/face/epp.rb:306
msgid ""
msgstr ""
#: ../lib/puppet/face/epp.rb:307
msgid "The name of the node for which facts are obtained. Defaults to facts for the local node."
msgstr ""
#: ../lib/puppet/face/epp.rb:312
msgid "Render one inline epp template given on the command line."
msgstr ""
#: ../lib/puppet/face/epp.rb:315
msgid ""
msgstr ""
#: ../lib/puppet/face/epp.rb:316
msgid "A Hash in Puppet DSL form given as arguments to the template being rendered."
msgstr ""
#: ../lib/puppet/face/epp.rb:319
msgid ""
msgstr ""
#: ../lib/puppet/face/epp.rb:320
msgid "A .pp or .yaml file that is processed to produce a hash of values for the template."
msgstr ""
#: ../lib/puppet/face/epp.rb:323
msgid ""
msgstr ""
#: ../lib/puppet/face/epp.rb:324
msgid "A .yaml or .json file containing a hash of facts made available in $facts and $trusted"
msgstr ""
#: ../lib/puppet/face/epp.rb:328
msgid "Whether or not to show a file name header between rendered results."
msgstr ""
#: ../lib/puppet/face/epp.rb:349
msgid "No input to process given on command line or stdin"
msgstr ""
#: ../lib/puppet/face/epp.rb:363
msgid "error while rendering epp"
msgstr ""
#: ../lib/puppet/face/epp.rb:415
msgid "Only .yaml or .pp can be used as a --values_file"
msgstr ""
#: ../lib/puppet/face/epp.rb:418
msgid "Could not load --values_file %{error}"
msgstr ""
#: ../lib/puppet/face/epp.rb:421
msgid "--values_file option must evaluate to a Hash or undef/nil, got: '%{template_class}'"
msgstr ""
#: ../lib/puppet/face/epp.rb:435
msgid "--values option must evaluate to a Hash or undef, got: '%{values_class}'"
msgstr ""
#: ../lib/puppet/face/epp.rb:531
msgid "Incorrect formatted data in %{fact_file} given via the --facts flag"
msgstr ""
#: ../lib/puppet/face/facts.rb:9
msgid "Retrieve and store facts."
msgstr ""
#: ../lib/puppet/face/facts.rb:17
msgid "Retrieve a node's facts."
msgstr ""
#: ../lib/puppet/face/facts.rb:18
msgid "[]"
msgstr ""
#: ../lib/puppet/face/facts.rb:40
msgid "Upload local facts to the puppet master."
msgstr ""
#: ../lib/puppet/face/facts.rb:78
msgid "Uploading facts for '%{node}' to '%{server}'"
msgstr ""
#: ../lib/puppet/face/facts.rb:88
msgid "Retrieve current node's facts."
msgstr ""
#: ../lib/puppet/face/facts.rb:89
msgid "[]"
msgstr ""
#: ../lib/puppet/face/facts.rb:105 ../lib/puppet/face/facts.rb:110 ../lib/puppet/face/facts.rb:115 ../lib/puppet/face/module/changes.rb:22
msgid ""
msgstr ""
#: ../lib/puppet/face/facts.rb:107
msgid "The location of the config file for Facter."
msgstr ""
#: ../lib/puppet/face/facts.rb:112
msgid "The path to a directory that contains custom facts."
msgstr ""
#: ../lib/puppet/face/facts.rb:117
msgid "The path to a directory that contains external facts."
msgstr ""
#: ../lib/puppet/face/facts.rb:121
msgid "Disable fact blocking mechanism."
msgstr ""
#: ../lib/puppet/face/facts.rb:125
msgid "Disable fact caching mechanism."
msgstr ""
#: ../lib/puppet/face/facts.rb:129
msgid "Show legacy facts when querying all facts."
msgstr ""
#: ../lib/puppet/face/facts.rb:133
msgid "Show only the value when the action is called with a single query"
msgstr ""
#: ../lib/puppet/face/facts.rb:137
msgid "Show how much time it took to resolve each fact."
msgstr ""
#: ../lib/puppet/face/generate.rb:10
msgid "Generates Puppet code from Ruby definitions."
msgstr ""
#: ../lib/puppet/face/generate.rb:13
msgid "Generates Puppet code for custom types"
msgstr ""
#: ../lib/puppet/face/generate.rb:32
msgid ""
msgstr ""
#: ../lib/puppet/face/generate.rb:33
msgid "The generation output format to use. Supported formats: pcore."
msgstr ""
#: ../lib/puppet/face/generate.rb:37
msgid "'%{format}' is not a supported format for type generation."
msgstr ""
#: ../lib/puppet/face/generate.rb:42
msgid "Forces the generation of output files (skips up-to-date checks)."
msgstr ""
#: ../lib/puppet/face/generate.rb:57
msgid "The output directory '%{outputdir}' exists and is not a directory"
msgstr ""
#: ../lib/puppet/face/help.rb:12
msgid "Display Puppet help."
msgstr ""
#: ../lib/puppet/face/help.rb:15
msgid "Display help about Puppet subcommands and their actions."
msgstr ""
#: ../lib/puppet/face/help.rb:16
msgid "[] []"
msgstr ""
#: ../lib/puppet/face/help.rb:17
msgid "Short help text for the specified subcommand or action."
msgstr ""
#: ../lib/puppet/face/help.rb:24
msgid "VERSION"
msgstr ""
#: ../lib/puppet/face/help.rb:25
msgid "The version of the subcommand for which to show help."
msgstr ""
#: ../lib/puppet/face/help.rb:29
msgid "Whether to render the help text in ronn format."
msgstr ""
#. TRANSLATORS 'puppet help' is a command line and should not be translated
#: ../lib/puppet/face/help.rb:45
msgid "The 'puppet help' command takes two (optional) arguments: a subcommand and an action"
msgstr ""
#. TRANSLATORS '--version' is a command line option and should not be translated
#: ../lib/puppet/face/help.rb:55
msgid "Supplying a '--version' only makes sense when a Faces subcommand is given"
msgstr ""
#: ../lib/puppet/face/help.rb:63
msgid "The legacy subcommand '%{sub_command}' does not support supplying an action"
msgstr ""
#: ../lib/puppet/face/help.rb:103
msgid "Could not load help for the application %{application_name}."
msgstr ""
#: ../lib/puppet/face/help.rb:104 ../lib/puppet/face/help.rb:116
msgid "Please check the error logs for more information."
msgstr ""
#: ../lib/puppet/face/help.rb:106 ../lib/puppet/face/help.rb:118
msgid "Detail: \"%{detail}\""
msgstr ""
#: ../lib/puppet/face/help.rb:115
msgid "Could not load help for the face %{face_name}."
msgstr ""
#: ../lib/puppet/face/help.rb:127
msgid "Unable to load action %{actionname} from %{face}"
msgstr ""
#: ../lib/puppet/face/help.rb:171
msgid "(Deprecated)"
msgstr ""
#: ../lib/puppet/face/help.rb:174 ../lib/puppet/face/help.rb:186
msgid "!%{sub_command}! Subcommand unavailable due to error."
msgstr ""
#: ../lib/puppet/face/help.rb:175 ../lib/puppet/face/help.rb:187
msgid "Check error logs."
msgstr ""
#: ../lib/puppet/face/module.rb:12
msgid "Creates, installs and searches for modules on the Puppet Forge."
msgstr ""
#: ../lib/puppet/face/module/changes.rb:4
msgid "Show modified files of an installed module."
msgstr ""
#: ../lib/puppet/face/module/changes.rb:12
msgid "Array of strings representing paths of modified files."
msgstr ""
#: ../lib/puppet/face/module/changes.rb:28
msgid "Could not find a valid module at %{path}"
msgstr ""
#: ../lib/puppet/face/module/changes.rb:35
msgid "No modified files"
msgstr ""
#: ../lib/puppet/face/module/changes.rb:37
msgid "%{count} files modified"
msgstr ""
#: ../lib/puppet/face/module/install.rb:9
msgid "Install a module from the Puppet Forge or a release archive."
msgstr ""
#: ../lib/puppet/face/module/install.rb:19
msgid "Pathname object representing the path to the installed module."
msgstr ""
#: ../lib/puppet/face/module/install.rb:86 ../lib/puppet/face/module/uninstall.rb:35 ../lib/puppet/face/module/upgrade.rb:34
msgid ""
msgstr ""
#: ../lib/puppet/face/module/install.rb:89
msgid "Force overwrite of existing module, if any. (Implies --ignore-dependencies.)"
msgstr ""
#: ../lib/puppet/face/module/install.rb:97
msgid "The directory into which modules are installed."
msgstr ""
#: ../lib/puppet/face/module/install.rb:110 ../lib/puppet/face/module/upgrade.rb:46
msgid "Do not attempt to install dependencies. (Implied by --force.)"
msgstr ""
#: ../lib/puppet/face/module/install.rb:117
msgid "Module version to install."
msgstr ""
#: ../lib/puppet/face/module/install.rb:126
msgid "Preparing to install into %{dir} ..."
msgstr ""
#: ../lib/puppet/face/module/install.rb:134
msgid "Module %{name} %{version} is already installed."
msgstr ""
#: ../lib/puppet/face/module/list.rb:6
msgid "List installed modules"
msgstr ""
#: ../lib/puppet/face/module/list.rb:15
msgid "hash of paths to module objects"
msgstr ""
#: ../lib/puppet/face/module/list.rb:18
msgid "Whether to show dependencies as a tree view"
msgstr ""
#: ../lib/puppet/face/module/list.rb:83
msgid " (no modules installed)"
msgstr ""
#: ../lib/puppet/face/module/list.rb:136
msgid "'%{parent_name}' (%{parent_version}) requires '%{dependency_name}' (%{dependency_version})"
msgstr ""
#: ../lib/puppet/face/module/list.rb:165
msgid ""
"Module '%{name}' (v%{version}) fails to meet some dependencies:\n"
msgstr ""
#: ../lib/puppet/face/module/list.rb:167
msgid ""
"Non semantic version dependency %{name} (v%{version}):\n"
msgstr ""
#: ../lib/puppet/face/module/list.rb:169
msgid ""
"Missing dependency '%{name}':\n"
msgstr ""
#: ../lib/puppet/face/module/list.rb:227
msgid "UNMET DEPENDENCY"
msgstr ""
#: ../lib/puppet/face/module/list.rb:261 ../lib/puppet/face/module/list.rb:266
msgid "invalid"
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:4
msgid "Uninstall a puppet module."
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:11
msgid "Hash of module objects representing uninstalled modules and related errors."
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:38
msgid "Force uninstall of an installed module."
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:46
msgid "Ignore any local changes made. (Implied by --force.)"
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:53
msgid "The version of the module to uninstall"
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:66
msgid "Preparing to uninstall '%{name}' (%{module_version}) ..."
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:68
msgid "Preparing to uninstall '%{name}' ..."
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:82
msgid "Removed '%{name}' (%{module_version}) from %{path}"
msgstr ""
#: ../lib/puppet/face/module/uninstall.rb:84
msgid "Removed '%{name}' from %{path}"
msgstr ""
#: ../lib/puppet/face/module/upgrade.rb:6
msgid "Upgrade a puppet module."
msgstr ""
#: ../lib/puppet/face/module/upgrade.rb:37
msgid "Force upgrade of an installed module. (Implies --ignore-dependencies.)"
msgstr ""
#: ../lib/puppet/face/module/upgrade.rb:53
msgid "Ignore and overwrite any local changes made. (Implied by --force.)"
msgstr ""
#: ../lib/puppet/face/module/upgrade.rb:60
msgid "The version of the module to upgrade to."
msgstr ""
#: ../lib/puppet/face/module/upgrade.rb:68
msgid "Preparing to upgrade '%{name}' ..."
msgstr ""
#: ../lib/puppet/face/node.rb:7
msgid "View and manage node definitions."
msgstr ""
#: ../lib/puppet/face/node.rb:19
msgid "Retrieve a node object."
msgstr ""
#: ../lib/puppet/face/node.rb:20
msgid ""
msgstr ""
#: ../lib/puppet/face/node/clean.rb:5
msgid "Clean up signed certs, cached facts, node objects, and reports for a node stored by the puppetmaster"
msgstr ""
#: ../lib/puppet/face/node/clean.rb:6
msgid " [ ...]"
msgstr ""
#: ../lib/puppet/face/node/clean.rb:24
msgid "At least one node should be passed"
msgstr ""
#: ../lib/puppet/face/node/clean.rb:73
msgid "Not managing %{node} certs as this host is not a CA"
msgstr ""
#: ../lib/puppet/face/node/clean.rb:80
msgid "%{node}'s facts removed"
msgstr ""
#: ../lib/puppet/face/node/clean.rb:86
msgid "%{node}'s cached node removed"
msgstr ""
#: ../lib/puppet/face/node/clean.rb:92
msgid "%{node}'s reports removed"
msgstr ""
#: ../lib/puppet/face/parser.rb:9
msgid "Interact directly with the parser."
msgstr ""
#: ../lib/puppet/face/parser.rb:12
msgid "Validate the syntax of one or more Puppet manifests."
msgstr ""
#: ../lib/puppet/face/parser.rb:13
msgid "[] [ ...]"
msgstr ""
#: ../lib/puppet/face/parser.rb:14
msgid "Nothing, or the first syntax error encountered."
msgstr ""
#: ../lib/puppet/face/parser.rb:51
msgid "No manifest specified. Validating the default manifest %{manifest}"
msgstr ""
#: ../lib/puppet/face/parser.rb:67
msgid ""
"One or more file(s) specified did not exist:\n"
"%{files}"
msgstr ""
#: ../lib/puppet/face/parser.rb:105
msgid "Outputs a dump of the internal parse tree for debugging"
msgstr ""
#: ../lib/puppet/face/parser.rb:130
msgid "dump one source expression given on the command line."
msgstr ""
#: ../lib/puppet/face/parser.rb:134
msgid "Whether or not to validate the parsed result, if no-validate only syntax errors are reported"
msgstr ""
#: ../lib/puppet/face/parser.rb:170
msgid ""
"One or more file(s) specified did not exist:\n"
msgstr ""
#: ../lib/puppet/face/parser.rb:216
msgid "For puppet parser validate"
msgstr ""
#: ../lib/puppet/face/plugin.rb:9
msgid "Interact with the Puppet plugin system."
msgstr ""
#: ../lib/puppet/face/plugin.rb:21
msgid "Download plugins from the puppet master."
msgstr ""
#: ../lib/puppet/face/plugin.rb:55
msgid "No plugins downloaded."
msgstr ""
#: ../lib/puppet/face/plugin.rb:57
msgid "Downloaded these plugins: %{plugins}"
msgstr ""
#: ../lib/puppet/face/report.rb:8
msgid "Create, display, and submit reports."
msgstr ""
#: ../lib/puppet/face/report.rb:11
msgid "API only: submit a report."
msgstr ""
#: ../lib/puppet/face/report.rb:12 ../lib/puppet/face/report.rb:33
msgid ""
msgstr ""
#: ../lib/puppet/face/report.rb:13
msgid "Nothing."
msgstr ""
#: ../lib/puppet/face/report.rb:27
msgid "API only: submit a report with error handling."
msgstr ""
#: ../lib/puppet/face/report.rb:46
msgid "Uploaded report for %{name}"
msgstr ""
#: ../lib/puppet/face/resource.rb:8
msgid "API only: interact directly with resources via the RAL."
msgstr ""
#: ../lib/puppet/face/resource.rb:17
msgid "API only: get all resources of a single type."
msgstr ""
#: ../lib/puppet/face/resource.rb:18
msgid ""
msgstr ""
#: ../lib/puppet/face/resource.rb:19
msgid "An array of Puppet::Resource objects."
msgstr ""
#: ../lib/puppet/face/resource.rb:27
msgid "API only: get a single resource."
msgstr ""
#: ../lib/puppet/face/resource.rb:28
msgid "/"
msgstr ""
#: ../lib/puppet/face/resource.rb:29
msgid "A Puppet::Resource object."
msgstr ""
#: ../lib/puppet/face/resource.rb:37
msgid "API only: create a new resource."
msgstr ""
#: ../lib/puppet/face/resource.rb:41
msgid ""
msgstr ""
#: ../lib/puppet/face/resource.rb:42
msgid "The same resource object passed as an argument."
msgstr ""
#: ../lib/puppet/feature/base.rb:20
msgid "Cannot determine basic system flavour"
msgstr ""
#: ../lib/puppet/ffi/windows/api_types.rb:87
msgid "Unable to read wide strings with %{null_terminator} terminal nulls"
msgstr ""
#: ../lib/puppet/ffi/windows/api_types.rb:232
msgid "Bad GUID format."
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:40
msgid "File %{file} does not exist"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:55
msgid "Could not back up %{file}: %{detail}"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:63
msgid "Diff is not supported on this platform"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:81
msgid "Please provide a file or checksum to diff with"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:97
msgid "Failed to diff files"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:111 ../lib/puppet/file_bucket/dipper.rb:166
msgid "File not found"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:146
msgid "Could not find file with checksum %{sum}"
msgstr ""
#: ../lib/puppet/file_bucket/dipper.rb:157 ../lib/puppet/indirector/file_bucket_file/file.rb:44
msgid "Listing remote file buckets is not allowed"
msgstr ""
#: ../lib/puppet/file_bucket/file.rb:28
msgid "contents must be a String or Pathname, got a %{contents_class}"
msgstr ""
#: ../lib/puppet/file_bucket/file.rb:33
msgid "Unknown option(s): %{opts}"
msgstr ""
#: ../lib/puppet/file_bucket/file.rb:97
msgid "Computing checksum on string"
msgstr ""
#: ../lib/puppet/file_bucket/file.rb:122
msgid "Computing checksum on file %{path}"
msgstr ""
#. TRANSLATORS ':link', ':manage', ':follow' should not be translated
#: ../lib/puppet/file_serving/base.rb:51
msgid ":links can only be set to :manage or :follow"
msgstr ""
#: ../lib/puppet/file_serving/base.rb:58
msgid "Paths must be fully qualified"
msgstr ""
#: ../lib/puppet/file_serving/base.rb:66
msgid "Relative paths must not be fully qualified"
msgstr ""
#: ../lib/puppet/file_serving/configuration.rb:57
msgid "Cannot find file: Invalid mount '%{mount_name}'"
msgstr ""
#: ../lib/puppet/file_serving/configuration.rb:58
msgid "Cannot find file: Invalid relative path '%{path}'"
msgstr ""
#: ../lib/puppet/file_serving/configuration.rb:107
msgid "Error parsing fileserver configuration: %{detail}; using old configuration"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:11
msgid "File server configuration %{config_file} does not exist"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:12
msgid "Cannot read file server configuration %{config_file}"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:32
msgid "Fileserver configuration file does not use '=' as a separator"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:44 ../lib/puppet/util/network_device/config.rb:102
msgid "Invalid argument '%{var}' at %{error_location}"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:49
msgid "Invalid entry at %{error_location}: '%{file_text}'"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:74
msgid "%{mount} is already mounted at %{name} at %{error_location}"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:101
msgid "Removing mount \"%{mount}\": %{detail}"
msgstr ""
#: ../lib/puppet/file_serving/configuration/parser.rb:105
msgid "The '%{mount}' module can not have a path. Ignoring attempt to set it"
msgstr ""
#: ../lib/puppet/file_serving/content.rb:34
msgid "Cannot read the contents of links unless following links"
msgstr ""
#: ../lib/puppet/file_serving/fileset.rb:35
msgid "Fileset paths must be fully qualified: %{path}"
msgstr ""
#: ../lib/puppet/file_serving/fileset.rb:52
msgid "Fileset paths must exist"
msgstr ""
#. TRANSLATORS "recurse" and "recurselimit" are parameter names and should not be translated
#: ../lib/puppet/file_serving/fileset.rb:54
msgid "Fileset recurse parameter must not be a number anymore, please use recurselimit"
msgstr ""
#: ../lib/puppet/file_serving/fileset.rb:70
msgid "The directory '%{path}' contains %{entries} entries, which exceeds the limit of %{munged_max_files} specified by the max_files parameter for this resource. The limit may be increased, but be aware that large number of file resources can result in excessive resource consumption and degraded performance. Consider using an alternate method to manage large directory trees"
msgstr ""
#: ../lib/puppet/file_serving/fileset.rb:72
msgid "The directory '%{path}' contains %{entries} entries, which exceeds the default soft limit %{soft_max_files} and may cause excessive resource consumption and degraded performance. To remove this warning set a value for `max_files` parameter or consider using an alternate method to manage large directory trees"
msgstr ""
#. TRANSLATORS ":links" is a parameter name and should not be translated
#: ../lib/puppet/file_serving/fileset.rb:93
msgid "Invalid :links value '%{links}'"
msgstr ""
#: ../lib/puppet/file_serving/fileset.rb:106
msgid "Invalid option '%{option}'"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:22
msgid "Unsupported checksum type %{type}"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:28
msgid "Unsupported source_permission %{source_permissions}"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:37
msgid "Could not understand URI %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:39
msgid "Cannot use opaque URLs '%{path}'"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:40
msgid "Must use URLs of type puppet as content URI"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:76
msgid "Unsupported Windows source permissions option %{source_permissions}"
msgstr ""
#: ../lib/puppet/file_serving/metadata.rb:126
msgid "Cannot manage files of type %{file_type}"
msgstr ""
#: ../lib/puppet/file_serving/mount.rb:21
msgid "Invalid mount name format '%{name}'"
msgstr ""
#: ../lib/puppet/file_serving/mount/file.rb:19 ../lib/puppet/file_serving/mount/file.rb:72
msgid "Mounts without paths are not usable"
msgstr ""
#: ../lib/puppet/file_serving/mount/file.rb:27
msgid "File does not exist or is not accessible: %{file}"
msgstr ""
#: ../lib/puppet/file_serving/mount/file.rb:56
msgid "%{path} does not exist or is not a directory"
msgstr ""
#: ../lib/puppet/file_serving/mount/file.rb:57
msgid "%{path} is not readable"
msgstr ""
#: ../lib/puppet/file_serving/mount/file.rb:94
msgid "No client; expanding '%{path}' with local host"
msgstr ""
#: ../lib/puppet/file_serving/mount/modules.rb:9 ../lib/puppet/file_serving/mount/scripts.rb:7
msgid "No module specified"
msgstr ""
#: ../lib/puppet/file_serving/mount/tasks.rb:6
msgid "No task specified"
msgstr ""
#: ../lib/puppet/file_serving/terminus_selector.rb:29
msgid "URI protocol '%{protocol}' is not currently supported for file serving"
msgstr ""
#: ../lib/puppet/file_system/file_impl.rb:18
msgid "FileSystem implementation expected Pathname, got: '%{klass}'"
msgstr ""
#: ../lib/puppet/file_system/file_impl.rb:58
msgid "Locked '%{path}'"
msgstr ""
#: ../lib/puppet/file_system/file_impl.rb:61
msgid "Unlocked '%{path}'"
msgstr ""
#: ../lib/puppet/file_system/file_impl.rb:68
msgid "Timeout waiting for exclusive lock on %{path}"
msgstr ""
#: ../lib/puppet/file_system/jruby.rb:19 ../lib/puppet/file_system/windows.rb:128 ../lib/puppet/util.rb:671
msgid "Is a directory: %{directory}"
msgstr ""
#: ../lib/puppet/file_system/memory_impl.rb:82
msgid "Unable to find registered object for %{path}"
msgstr ""
#: ../lib/puppet/file_system/path_pattern.rb:50
msgid "PathPatterns cannot be created with directory traversals."
msgstr ""
#: ../lib/puppet/file_system/path_pattern.rb:52
msgid "A PathPattern cannot be a Windows current drive relative path."
msgstr ""
#: ../lib/puppet/file_system/path_pattern.rb:61
msgid "PathPatterns cannot be created with a zero byte."
msgstr ""
#: ../lib/puppet/file_system/path_pattern.rb:75
msgid "A relative PathPattern cannot be prefixed with a drive."
msgstr ""
#: ../lib/puppet/file_system/path_pattern.rb:77
msgid "A relative PathPattern cannot be an absolute path."
msgstr ""
#: ../lib/puppet/file_system/path_pattern.rb:90
msgid "An absolute PathPattern cannot be a relative path."
msgstr ""
#: ../lib/puppet/file_system/uniquefile.rb:110
msgid "unexpected prefix_suffix: %{value}"
msgstr ""
#: ../lib/puppet/file_system/uniquefile.rb:137
msgid "cannot generate temporary name using `%{basename}' under `%{tmpdir}'"
msgstr ""
#: ../lib/puppet/file_system/windows.rb:50
msgid "%{dest} already exists and the :force option was not specified"
msgstr ""
#: ../lib/puppet/file_system/windows.rb:205
msgid "This version of Windows does not support symlinks. Windows Vista / 2008 or higher is required."
msgstr ""
#: ../lib/puppet/file_system/windows.rb:210
msgid "The current user does not have the necessary permission to manage symlinks."
msgstr ""
#: ../lib/puppet/forge.rb:140
msgid "Malformed dependency: %{name}."
msgstr ""
#: ../lib/puppet/forge.rb:141
msgid "Exception was: %{detail}"
msgstr ""
#: ../lib/puppet/forge.rb:184
msgid "Forge module is missing SHA256 and MD5 checksums"
msgstr ""
#: ../lib/puppet/forge.rb:218
msgid "Module install using MD5 is prohibited in FIPS mode."
msgstr ""
#: ../lib/puppet/forge.rb:222
msgid "Downloaded release for %{name} did not match expected checksum %{checksum}"
msgstr ""
#: ../lib/puppet/forge.rb:230 ../lib/puppet/module_tool/applications/unpacker.rb:59 ../lib/puppet/module_tool/local_tarball.rb:87
msgid "Could not extract contents of module archive: %{message}"
msgstr ""
#: ../lib/puppet/forge.rb:247
msgid "Cannot consider release %{name}-%{version}: %{error}"
msgstr ""
#: ../lib/puppet/forge/errors.rb:29
msgid "Unable to verify the SSL certificate at %{uri}"
msgstr ""
#: ../lib/puppet/forge/errors.rb:37
msgid "Could not connect via HTTPS to %{uri}"
msgstr ""
#: ../lib/puppet/forge/errors.rb:38
msgid " Unable to verify the SSL certificate"
msgstr ""
#: ../lib/puppet/forge/errors.rb:39
msgid " The certificate may not be signed by a valid CA"
msgstr ""
#: ../lib/puppet/forge/errors.rb:40
msgid " The CA bundle included with OpenSSL may not be valid or up to date"
msgstr ""
#: ../lib/puppet/forge/errors.rb:55
msgid "Unable to connect to the server at %{uri}. Detail: %{detail}."
msgstr ""
#: ../lib/puppet/forge/errors.rb:64
msgid "Could not connect to %{uri}"
msgstr ""
#: ../lib/puppet/forge/errors.rb:65
msgid " There was a network communications problem"
msgstr ""
#: ../lib/puppet/forge/errors.rb:66
msgid " The error we caught said '%{detail}'"
msgstr ""
#: ../lib/puppet/forge/errors.rb:67
msgid " Check your network connection and try again"
msgstr ""
#: ../lib/puppet/forge/errors.rb:94 ../lib/puppet/forge/errors.rb:96 ../lib/puppet/forge/errors.rb:107
msgid "Request to Puppet Forge failed."
msgstr ""
#: ../lib/puppet/forge/errors.rb:94 ../lib/puppet/forge/errors.rb:96
msgid "Detail: %{detail}."
msgstr ""
#: ../lib/puppet/forge/errors.rb:108
msgid " The server being queried was %{uri}"
msgstr ""
#: ../lib/puppet/forge/errors.rb:109
msgid " The HTTP response we received was '%{response}'"
msgstr ""
#: ../lib/puppet/forge/errors.rb:110
msgid " The message we received said '%{message}'"
msgstr ""
#: ../lib/puppet/functions.rb:194
msgid "Function Load Error for function '%{function_name}': %{message}"
msgstr ""
#: ../lib/puppet/functions.rb:213
msgid "Functions must be based on Puppet::Pops::Functions::Function. Got %{function_base}"
msgstr ""
#: ../lib/puppet/functions.rb:273
msgid "Function Creation Error, cannot create a default dispatcher for function '%{func_name}', no method with this name found"
msgstr ""
#: ../lib/puppet/functions.rb:351
msgid "No loader present. Call create_loaded_function(:myname, loader,...), instead of 'create_function' if running tests"
msgstr ""
#: ../lib/puppet/functions.rb:415
msgid "A required parameter cannot be added after an optional parameter"
msgstr ""
#: ../lib/puppet/functions.rb:464
msgid "A required repeated parameter cannot be added after an optional parameter"
msgstr ""
#: ../lib/puppet/functions.rb:486
msgid "block_param accepts max 2 arguments (type, name), got %{size}."
msgstr ""
#: ../lib/puppet/functions.rb:490
msgid "Expected PCallableType or PVariantType thereof, got %{type_class}"
msgstr ""
#: ../lib/puppet/functions.rb:494
msgid "Expected block_param name to be a Symbol, got %{name_class}"
msgstr ""
#: ../lib/puppet/functions.rb:501
msgid "Attempt to redefine block"
msgstr ""
#: ../lib/puppet/functions.rb:523
msgid "Argument to 'return_type' must be a String reference to a Puppet Data Type. Got %{type_class}"
msgstr ""
#: ../lib/puppet/functions.rb:532
msgid "Parameters cannot be added after a block parameter"
msgstr ""
#: ../lib/puppet/functions.rb:533
msgid "Parameters cannot be added after a repeated parameter"
msgstr ""
#: ../lib/puppet/functions.rb:536
msgid "Parameter name argument must be a Symbol. Got %{name_class}"
msgstr ""
#: ../lib/puppet/functions.rb:549
msgid "Parameter 'type' must be a String reference to a Puppet Data Type. Got %{type_class}"
msgstr ""
#: ../lib/puppet/functions.rb:593
msgid ""
"Parsing of type string '\"%{type_string}\"' failed with message: <%{message}>.\n"
msgstr ""
#: ../lib/puppet/functions.rb:635
msgid ""
"Parsing of 'type \"%{assignment_string}\"' failed with message: <%{message}>.\n"
"Called from <%{ruby_file_location}>"
msgstr ""
#: ../lib/puppet/functions.rb:644
msgid ""
"Expected a type alias assignment on the form 'AliasType = T', got '%{assignment_string}'.\n"
"Called from <%{ruby_file_location}>"
msgstr ""
#: ../lib/puppet/functions/abs.rb:49
msgid "The abs() function's auto conversion of String to Numeric is deprecated - change to convert input before calling"
msgstr ""
#. TRANSLATORS the string "binary_file()" should not be translated
#: ../lib/puppet/functions/binary_file.rb:29
msgid "binary_file(): The given file '%{unresolved_path}' does not exist"
msgstr ""
#: ../lib/puppet/functions/ceiling.rb:28
msgid "The ceiling() function's auto conversion of String to Float is deprecated - change to convert input before calling"
msgstr ""
#. TRANSLATORS: 'ceiling' is a name and should not be translated
#: ../lib/puppet/functions/ceiling.rb:34
msgid "ceiling(): cannot convert given value to a floating point value."
msgstr ""
#. TRANSLATORS 'compare' is a name
#: ../lib/puppet/functions/compare.rb:94
msgid "compare(): Non comparable type. Only values of the types Numeric, String, Semver, Timestamp and Timestamp can be compared. Got %{type_a} and %{type_b}"
msgstr ""
#. TRANSLATORS 'compare' is a name
#: ../lib/puppet/functions/compare.rb:103
msgid "compare(): The third argument (ignore case) can only be used when comparing strings"
msgstr ""
#. TRANSLATORS 'compare' is a name
#: ../lib/puppet/functions/compare.rb:107
msgid "compare(): Accepts at most 3 arguments, got %{actual_number}"
msgstr ""
#. TRANSLATORS 'compare' is a name
#: ../lib/puppet/functions/compare.rb:111
msgid "compare(): The third argument (ignore case) must be a Boolean. Got %{type}"
msgstr ""
#. TRANSLATORS 'compare' is a name
#: ../lib/puppet/functions/compare.rb:117
msgid "compare(): Can only compare values of the same type (or for Timestamp/Timespan also against Numeric). Got %{type_a} and %{type_b}"
msgstr ""
#: ../lib/puppet/functions/defined.rb:133
msgid "The given resource type is a reference to all kind of types"
msgstr ""
#: ../lib/puppet/functions/defined.rb:138 ../lib/puppet/functions/defined.rb:152
msgid "The given class type is a reference to all classes"
msgstr ""
#: ../lib/puppet/functions/defined.rb:156
msgid "Invalid argument of type '%{value_class}' to 'defined'"
msgstr ""
#: ../lib/puppet/functions/dig.rb:43
msgid "The given data does not contain a Collection at %{walked_path}, got '%{type}'"
msgstr ""
#: ../lib/puppet/functions/dig.rb:56
msgid "The given data requires an Integer index at %{walked_path}, got '%{type}'"
msgstr ""
#: ../lib/puppet/functions/empty.rb:83
msgid "Calling function empty() with %{arg_type} value is deprecated."
msgstr ""
#. TRANSLATORS 'eyaml_lookup_key':, 'path', 'paths' 'glob', 'globs', 'mapped_paths', and lookup_key should not be translated
#: ../lib/puppet/functions/eyaml_lookup_key.rb:32
msgid "'eyaml_lookup_key': one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this lookup_key function"
msgstr ""
#: ../lib/puppet/functions/eyaml_lookup_key.rb:54 ../lib/puppet/functions/yaml_data.rb:30
msgid "%{path}: file does not contain a valid yaml hash"
msgstr ""
#: ../lib/puppet/functions/eyaml_lookup_key.rb:61 ../lib/puppet/functions/yaml_data.rb:37
msgid "Unable to parse %{message}"
msgstr ""
#: ../lib/puppet/functions/eyaml_lookup_key.rb:94
msgid "hiera-eyaml backend error decrypting %{data} when looking up %{key} in %{path}. Error was %{message}"
msgstr ""
#: ../lib/puppet/functions/floor.rb:28
msgid "The floor() function's auto conversion of String to Float is deprecated - change to convert input before calling"
msgstr ""
#. TRANSLATORS: 'floor' is a name and should not be translated
#: ../lib/puppet/functions/floor.rb:34
msgid "floor(): cannot convert given value to a floating point value."
msgstr ""
#: ../lib/puppet/functions/get.rb:135
msgid "Syntax error in dotted-navigation string"
msgstr ""
#: ../lib/puppet/functions/getvar.rb:61
msgid "The given string does not start with a valid variable name"
msgstr ""
#: ../lib/puppet/functions/getvar.rb:74
msgid "First character after var name in get string must be a '.' - got %{char}"
msgstr ""
#: ../lib/puppet/functions/hiera_include.rb:102
msgid "Could not find data item %{key}"
msgstr ""
#: ../lib/puppet/functions/hocon_data.rb:12
msgid "Lookup using Hocon data_hash function is not supported without hocon library"
msgstr ""
#: ../lib/puppet/functions/hocon_data.rb:34
msgid "Unable to parse (%{path}): %{message}"
msgstr ""
#: ../lib/puppet/functions/match.rb:82
msgid "match() expects pattern of T, where T is String, Regexp, Regexp[r], Pattern[p], or Array[T]. Got %{klass}"
msgstr ""
#: ../lib/puppet/functions/match.rb:106
msgid "Given Regexp Type has no regular expression"
msgstr ""
#: ../lib/puppet/functions/max.rb:151 ../lib/puppet/functions/max.rb:237
msgid "The max() function's auto conversion of String to Numeric is deprecated - change to convert input before calling, or use lambda"
msgstr ""
#: ../lib/puppet/functions/max.rb:241
msgid "The max() function's auto conversion of Any to String is deprecated - change to convert input before calling, or use lambda"
msgstr ""
#: ../lib/puppet/functions/min.rb:150 ../lib/puppet/functions/min.rb:236
msgid "The min() function's auto conversion of String to Numeric is deprecated - change to convert input before calling, or use lambda"
msgstr ""
#: ../lib/puppet/functions/min.rb:240
msgid "The min() function's auto conversion of Any to String is deprecated - change to convert input before calling, or use lambda"
msgstr ""
#: ../lib/puppet/functions/require.rb:71
msgid "Could not find class %{klass}"
msgstr ""
#: ../lib/puppet/functions/slice.rb:117
msgid "slice(): block must define at least one parameter. Block has 0."
msgstr ""
#: ../lib/puppet/functions/slice.rb:120
msgid "slice(): block must define one parameter, or the same number of parameters as the given size of the slice (%{slice_size}). Block has %{serving_size}; %{parameter_names}"
msgstr ""
#: ../lib/puppet/functions/strftime.rb:209
msgid "The argument signature (String format, [String timezone]) is deprecated for #strftime. See #strftime documentation and Timespan type for more info"
msgstr ""
#: ../lib/puppet/generate/models/type/type.rb:47
msgid "title patterns that use procs are not supported."
msgstr ""
#: ../lib/puppet/generate/type.rb:41 ../lib/puppet/generate/type.rb:61 ../lib/puppet/generate/type.rb:73
msgid "unsupported format '%{format}'."
msgstr ""
#: ../lib/puppet/generate/type.rb:160
msgid "Removed output '%{files_to_remove}' for non existing inputs"
msgstr ""
#: ../lib/puppet/generate/type.rb:164
msgid "No custom types were found."
msgstr ""
#: ../lib/puppet/generate/type.rb:170
msgid "template was not found at '%{key}'."
msgstr ""
#: ../lib/puppet/generate/type.rb:179
msgid "Generating Puppet resource types."
msgstr ""
#: ../lib/puppet/generate/type.rb:197
msgid "Failed to load custom type '%{type_name}' from '%{input}': %{message}"
msgstr ""
#: ../lib/puppet/generate/type.rb:207
msgid "Custom type '%{type_name}' was not defined in '%{input}'."
msgstr ""
#: ../lib/puppet/generate/type.rb:233
msgid "Generating '%{effective_output_path}' using '%{format}' format."
msgstr ""
#: ../lib/puppet/generate/type.rb:240
msgid "Failed to generate '%{effective_output_path}': %{message}"
msgstr ""
#: ../lib/puppet/generate/type.rb:246
msgid "No files were generated because all inputs were up-to-date."
msgstr ""
#: ../lib/puppet/graph/relationship_graph.rb:74
msgid "appears to have a negative number of dependencies"
msgstr ""
#: ../lib/puppet/graph/simple_graph.rb:68
msgid "Got an event from invalid vertex %{source}"
msgstr ""
#. TRANSLATORS "negative or zero" refers to the count of paths
#: ../lib/puppet/graph/simple_graph.rb:202
msgid "negative or zero max_paths"
msgstr ""
#: ../lib/puppet/graph/simple_graph.rb:234
msgid ""
"Found %{num} dependency cycle:\n"
msgid_plural ""
"Found %{num} dependency cycles:\n"
msgstr[0] ""
msgstr[1] ""
#: ../lib/puppet/graph/simple_graph.rb:243
msgid "Cycle graph written to %{filename}."
msgstr ""
#. TRANSLATORS '--graph' refers to a command line option and OmniGraffle and GraphViz are program names and should not be translated
#: ../lib/puppet/graph/simple_graph.rb:246
msgid "Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz"
msgstr ""
#: ../lib/puppet/http/client.rb:157
msgid "Request to %{uri} timed out connect operation after %{elapsed} seconds"
msgstr ""
#: ../lib/puppet/http/client.rb:159
msgid "Request to %{uri} timed out read operation after %{elapsed} seconds"
msgstr ""
#: ../lib/puppet/http/client.rb:161
msgid "Request to %{uri} interrupted after %{elapsed} seconds"
msgstr ""
#: ../lib/puppet/http/client.rb:167
msgid "Request to %{uri} failed after %{elapsed} seconds: %{message}"
msgstr ""
#. TRANSLATORS: `message` is an already translated string of why SSL failed to initialize
#: ../lib/puppet/http/client.rb:318
msgid "Failed to initialize SSL: %{message}"
msgstr ""
#. TRANSLATORS: `puppet agent -t` is a command and should not be translated
#: ../lib/puppet/http/client.rb:320
msgid "Run `puppet agent -t`"
msgstr ""
#: ../lib/puppet/http/client.rb:390
msgid "Sleeping for %{interval} seconds before retrying the request"
msgstr ""
#: ../lib/puppet/http/client.rb:445
msgid "HTTP REST queries cannot handle values of type '%{klass}'"
msgstr ""
#: ../lib/puppet/http/errors.rb:38
msgid "Too many HTTP redirections for %{addr}"
msgstr ""
#: ../lib/puppet/http/errors.rb:46
msgid "Too many HTTP retries for %{addr}"
msgstr ""
#: ../lib/puppet/http/pool.rb:85
msgid "Failed to close connection for %{site}: %{detail}"
msgstr ""
#: ../lib/puppet/http/redirector.rb:76
msgid "Location response header is missing"
msgstr ""
#: ../lib/puppet/http/redirector.rb:80
msgid "Location URI is invalid: %{detail}"
msgstr ""
#: ../lib/puppet/http/resolver/server_list.rb:67 ../lib/puppet/http/resolver/server_list.rb:75
msgid "Trying with next server from server_list."
msgstr ""
#: ../lib/puppet/http/retry_after_handler.rb:75
msgid "Failed to parse Retry-After header '%{retry_after}' as an integer or RFC 2822 date"
msgstr ""
#: ../lib/puppet/http/service.rb:108
msgid "Ignoring extra header \"%{name}\" as it was previously set."
msgstr ""
#: ../lib/puppet/http/service.rb:111
msgid "Ignoring extra header \"%{name}\" as it has no value."
msgstr ""
#: ../lib/puppet/http/service.rb:134 ../lib/puppet/indirector/rest.rb:54
msgid "No content type in http response; cannot parse"
msgstr ""
#: ../lib/puppet/http/service/ca.rb:126
msgid "SSL context must contain a client certificate."
msgstr ""
#: ../lib/puppet/indirector.rb:26
msgid "Indirection %{indirection_name} does not exist"
msgstr ""
#: ../lib/puppet/indirector.rb:39
msgid "Already handling indirection for %{current}; cannot also handle %{next}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:27
msgid "Facts but no fact format provided for %{request}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:30
msgid "Found facts"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:35
msgid "Catalog for %{request} was requested with fact definition for the wrong node (%{fact_name})."
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:68
msgid "Requested environment '%{request_env}' did not match server specified environment '%{server_env}'"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:94
msgid "Setup server facts for compiling"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:122
msgid "Unsupported facts format"
msgstr ""
#. TRANSLATORS Inlining refers to adding additional metadata (in this case we are not inlining)
#: ../lib/puppet/indirector/catalog/compiler.rb:163
msgid "Not inlining absent resource"
msgstr ""
#. TRANSLATORS Inlining refers to adding additional metadata (in this case we are not inlining)
#: ../lib/puppet/indirector/catalog/compiler.rb:166
msgid "Not inlining resource without sources"
msgstr ""
#. TRANSLATORS Inlining refers to adding additional metadata (in this case we are not inlining)
#: ../lib/puppet/indirector/catalog/compiler.rb:169
msgid "Not inlining unsupported source scheme"
msgstr ""
#. TRANSLATORS Inlining refers to adding additional metadata (in this case we are not inlining)
#: ../lib/puppet/indirector/catalog/compiler.rb:191
msgid "Not inlining file outside environment"
msgstr ""
#. TRANSLATORS Inlining refers to adding additional metadata
#: ../lib/puppet/indirector/catalog/compiler.rb:197
msgid "Inlining file metadata"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:287
msgid "Could not get metadata for %{resource}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:308
msgid "Unable to find a common checksum type between agent '%{agent_type}' and master '%{master_type}'."
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:315
msgid "Compiled static catalog for %{node} in environment %{environment} in %%{seconds} seconds"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:316
msgid "Compiled static catalog for %{node} in environment %{environment}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:318
msgid "Compiled static catalog for %{node} in %%{seconds} seconds"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:319
msgid "Compiled static catalog for %{node}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:324
msgid "Compiled catalog for %{node} in environment %{environment} in %%{seconds} seconds"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:325
msgid "Compiled catalog for %{node} in environment %{environment}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:327
msgid "Compiled catalog for %{node} in %%{seconds} seconds"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:328
msgid "Compiled catalog for %{node}"
msgstr ""
#. TRANSLATORS Inlined refers to adding additional metadata
#: ../lib/puppet/indirector/catalog/compiler.rb:350
msgid "Inlined resource metadata into static catalog for %{node} in environment %{environment} in %%{seconds} seconds"
msgstr ""
#. TRANSLATORS Inlined refers to adding additional metadata
#: ../lib/puppet/indirector/catalog/compiler.rb:352
msgid "Inlined resource metadata into static catalog for %{node} in environment %{environment}"
msgstr ""
#. TRANSLATORS Inlined refers to adding additional metadata
#: ../lib/puppet/indirector/catalog/compiler.rb:355
msgid "Inlined resource metadata into static catalog for %{node} in %%{seconds} seconds"
msgstr ""
#. TRANSLATORS Inlined refers to adding additional metadata
#: ../lib/puppet/indirector/catalog/compiler.rb:357
msgid "Inlined resource metadata into static catalog for %{node}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:374
msgid "Found node information"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:382
msgid "Failed when searching for node %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:402
msgid "Invalid option use_node for a remote request"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:421
msgid "Could not find node '%{name}'; cannot compile"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:454
msgid "Could not retrieve fact servername"
msgstr ""
#: ../lib/puppet/indirector/catalog/compiler.rb:463
msgid "Could not retrieve either serverip or serverip6 fact"
msgstr ""
#: ../lib/puppet/indirector/catalog/json.rb:14
msgid "Unable to deserialize catalog from json, retrying with pson"
msgstr ""
#: ../lib/puppet/indirector/catalog/json.rb:23
msgid "Unable to serialize catalog to json, retrying with pson. PSON is deprecated and will be removed in a future release"
msgstr ""
#: ../lib/puppet/indirector/catalog/json.rb:27
msgid "Unable to serialize catalog to json, no other acceptable format"
msgstr ""
#: ../lib/puppet/indirector/catalog/rest.rb:42 ../lib/puppet/indirector/facts/rest.rb:21 ../lib/puppet/indirector/file_content/rest.rb:30 ../lib/puppet/indirector/file_metadata/rest.rb:27 ../lib/puppet/indirector/node/rest.rb:24
msgid "Find %{uri} resulted in 404 with the message: %{body}"
msgstr ""
#: ../lib/puppet/indirector/exec.rb:12
msgid "Exec commands must be an array"
msgstr ""
#: ../lib/puppet/indirector/exec.rb:15
msgid "You must set the exec parameter to a fully qualified command"
msgstr ""
#: ../lib/puppet/indirector/exec.rb:22
msgid "Failed to find %{name} via exec: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/face.rb:5
msgid "TERMINUS"
msgstr ""
#: ../lib/puppet/indirector/face.rb:6
msgid "The indirector terminus to use."
msgstr ""
#: ../lib/puppet/indirector/face.rb:50
msgid "Could not call '%{method}' on '%{indirection}': %{detail}"
msgstr ""
#: ../lib/puppet/indirector/face.rb:59
msgid "Delete an object."
msgstr ""
#: ../lib/puppet/indirector/face.rb:60 ../lib/puppet/indirector/face.rb:80
msgid ""
msgstr ""
#: ../lib/puppet/indirector/face.rb:65
msgid "Retrieve an object by name."
msgstr ""
#: ../lib/puppet/indirector/face.rb:66
msgid "[]"
msgstr ""
#: ../lib/puppet/indirector/face.rb:79
msgid "API only: create or overwrite an object."
msgstr ""
#: ../lib/puppet/indirector/face.rb:90
msgid "Search for an object or retrieve multiple objects."
msgstr ""
#: ../lib/puppet/indirector/face.rb:91
msgid ""
msgstr ""
#: ../lib/puppet/indirector/face.rb:97
msgid "Print the default terminus class for this face."
msgstr ""
#: ../lib/puppet/indirector/face.rb:106
msgid "Run mode '%{mode}': %{terminus}"
msgstr ""
#: ../lib/puppet/indirector/face.rb:108
msgid "No default terminus class for run mode '%{mode}'"
msgstr ""
#: ../lib/puppet/indirector/face.rb:130
msgid "Could not find terminus for %{indirection}"
msgstr ""
#: ../lib/puppet/indirector/face.rb:139
msgid "Could not set '%{indirection}' terminus to '%{from}' (%{detail}); valid terminus types are %{types}"
msgstr ""
#: ../lib/puppet/indirector/facts/facter.rb:15
msgid "You cannot destroy facts in the code store; it is only used for getting facts from Facter"
msgstr ""
#: ../lib/puppet/indirector/facts/facter.rb:19
msgid "You cannot save facts to the code store; it is only used for getting facts from Facter"
msgstr ""
#: ../lib/puppet/indirector/facts/facter.rb:37
msgid "puppet facts show requires version 4.0.40 or greater of Facter."
msgstr ""
#: ../lib/puppet/indirector/facts/facter.rb:70
msgid "Loading facts"
msgstr ""
#: ../lib/puppet/indirector/facts/network_device.rb:22
msgid "You cannot destroy facts in the code store; it is only used for getting facts from a remote device"
msgstr ""
#: ../lib/puppet/indirector/facts/network_device.rb:26
msgid "You cannot save facts to the code store; it is only used for getting facts from a remote device"
msgstr ""
#: ../lib/puppet/indirector/facts/rest.rb:29
msgid "PUT does not accept options"
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:29
msgid "could not find diff_with %{diff}"
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:30
msgid "Unable to diff on this platform"
msgstr ""
#. TRANSLATORS "FileBucket" should not be translated
#: ../lib/puppet/indirector/file_bucket_file/file.rb:34
msgid "FileBucket read %{checksum}"
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:52
msgid "Error while parsing 'todate'"
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:57
msgid "Error while parsing 'fromdate'"
msgstr ""
#. TRANSLATORS "FileBucket" should not be translated
#: ../lib/puppet/indirector/file_bucket_file/file.rb:164
msgid "FileBucket got a duplicate file %{file_checksum}"
msgstr ""
#. TRANSLATORS "FileBucket" should not be translated
#: ../lib/puppet/indirector/file_bucket_file/file.rb:178
msgid "Unable to verify existing FileBucket backup at '%{path}'."
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:179
msgid "Existing backup and new file have different content but same checksum, %{value}. Verify existing backup and remove if incorrect."
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:185
msgid "Existing backup does not match its expected sum, %{sum}. Overwriting corrupted backup."
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:205
msgid "Unsupported checksum type %{checksum_type}"
msgstr ""
#: ../lib/puppet/indirector/file_bucket_file/file.rb:207
msgid "Invalid checksum %{checksum}"
msgstr ""
#: ../lib/puppet/indirector/file_metadata/http.rb:33
msgid "cannot lookup multiple files"
msgstr ""
#: ../lib/puppet/indirector/file_server.rb:43
msgid "Could not find filesystem info for file '%{request}' in environment %{env}"
msgstr ""
#. TRANSLATORS "Hiera" is the name of a code library and should not be translated
#: ../lib/puppet/indirector/hiera.rb:13
msgid "Hiera terminus not supported without hiera library"
msgstr ""
#. TRANSLATORS "merge" is a parameter name and should not be translated
#: ../lib/puppet/indirector/hiera.rb:72
msgid "Unrecognized value for request 'merge' parameter: '%{merge}'"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:41
msgid "Tried to cache when no cache class was set"
msgstr ""
#. TRANSLATORS "TTL" stands for "time to live" and refers to a duration of time
#: ../lib/puppet/indirector/indirection.rb:68
msgid "Indirection TTL must be an integer"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:103
msgid "Indirection %{name} is already defined"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:127
msgid "The setting %{setting} is not a valid indirection setting."
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:139
msgid "No terminus specified for %{name}; cannot redirect"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:160
msgid "No terminus class nor terminus setting was provided for indirection %{name}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:179
msgid "Invalid terminus name %{terminus_class}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:182
msgid "Could not find terminus %{terminus_class} for indirection %{name}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:198
msgid "Expiring the %{cache} cache of %{instance}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:228
msgid "Caching %{indirection} for %{request}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:239
msgid "Filtered result for %{indirection} %{request}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:269
msgid "Not using expired %{indirection} for %{request} from cache; expired at %{expiration}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:276
msgid "Cached %{indirection} for %{request} failed: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:302
msgid "Search results from terminus %{terminus_name} are not an array"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:339
msgid "Not authorized to call %{method} on %{description}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:342
msgid "Not authorized to call %{method} on %{description} with %{option}"
msgstr ""
#: ../lib/puppet/indirector/indirection.rb:369
msgid "Could not find terminus %{terminus_class} for indirection %{indirection}"
msgstr ""
#: ../lib/puppet/indirector/json.rb:20
msgid "Could not save %{json} %{request}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/json.rb:27
msgid "Could not destroy %{json} %{request}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/json.rb:41
msgid "directory traversal detected in %{json}: %{name}"
msgstr ""
#: ../lib/puppet/indirector/json.rb:42 ../lib/puppet/indirector/msgpack.rb:49 ../lib/puppet/indirector/yaml.rb:41
msgid "invalid key"
msgstr ""
#: ../lib/puppet/indirector/json.rb:63
msgid "Could not read JSON data for %{name} %{key}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/json.rb:69
msgid "Could not parse JSON data for %{name} %{key}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/memory.rb:15
msgid "Could not find %{request} to destroy"
msgstr ""
#: ../lib/puppet/indirector/msgpack.rb:12
msgid "MessagePack terminus not supported without msgpack library"
msgstr ""
#: ../lib/puppet/indirector/msgpack.rb:27
msgid "Could not save %{name} %{request}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/msgpack.rb:34
msgid "Could not destroy %{name} %{request}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/msgpack.rb:48 ../lib/puppet/indirector/yaml.rb:40
msgid "directory traversal detected in %{indirection}: %{name}"
msgstr ""
#. TRANSLATORS "MessagePack" is a program name and should not be translated
#: ../lib/puppet/indirector/msgpack.rb:67
msgid "Could not read MessagePack data for %{indirection} %{key}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/msgpack.rb:73
msgid "Could not parse MessagePack data for %{indirection} %{key}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/node/exec.rb:12
msgid "You must set the 'external_nodes' parameter to use the external node terminus"
msgstr ""
#: ../lib/puppet/indirector/node/exec.rb:12
msgid "none"
msgstr ""
#: ../lib/puppet/indirector/node/exec.rb:62
msgid "key is a %{klass}, not a string or symbol"
msgstr ""
#: ../lib/puppet/indirector/node/exec.rb:69
msgid "Could not load external node results for %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/report/json.rb:20 ../lib/puppet/indirector/report/yaml.rb:20
msgid "replace_file mode: %{mode} is invalid"
msgstr ""
#: ../lib/puppet/indirector/report/json.rb:32 ../lib/puppet/indirector/report/yaml.rb:32 ../lib/puppet/indirector/yaml.rb:33
msgid "Could not save %{indirection} %{request}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/report/processor.rb:40
msgid "Report %{report} failed: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/report/processor.rb:57
msgid "No report named '%{name}'"
msgstr ""
#: ../lib/puppet/indirector/request.rb:103
msgid "Could not find indirection '%{indirection}'"
msgstr ""
#: ../lib/puppet/indirector/request.rb:166
msgid "Could not understand URL %{key}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/resource/ral.rb:65
msgid "Could not find type %{request_type}"
msgstr ""
#: ../lib/puppet/indirector/resource/validator.rb:6
msgid "Resource instance does not match request key"
msgstr ""
#: ../lib/puppet/indirector/rest.rb:44
msgid "Error %{code} on SERVER: %{returned_message}"
msgstr ""
#: ../lib/puppet/indirector/terminus.rb:38
msgid "Could not find indirection instance %{name} for %{terminus}"
msgstr ""
#: ../lib/puppet/indirector/terminus.rb:53
msgid "Terminus subclasses must have associated constants"
msgstr ""
#: ../lib/puppet/indirector/terminus.rb:78
msgid "Could not discern indirection model from class constant"
msgstr ""
#: ../lib/puppet/indirector/terminus.rb:136
msgid "Cannot create instances of abstract terminus types"
msgstr ""
#: ../lib/puppet/indirector/terminus.rb:168
msgid "Instance name %{name} does not match requested key %{key}"
msgstr ""
#: ../lib/puppet/indirector/terminus.rb:174
msgid "Invalid instance type %{klass}, expected %{model_type}"
msgstr ""
#: ../lib/puppet/indirector/yaml.rb:15
msgid "Could not parse YAML data for %{indirection} %{request}: %{detail}"
msgstr ""
#: ../lib/puppet/indirector/yaml.rb:21
msgid "You can only save objects that respond to :name"
msgstr ""
#: ../lib/puppet/info_service/class_information_service.rb:19
msgid "Given argument must be a Hash"
msgstr ""
#: ../lib/puppet/info_service/class_information_service.rb:56
msgid "The file %{f} does not exist"
msgstr ""
#: ../lib/puppet/info_service/plan_information_service.rb:21 ../lib/puppet/info_service/task_information_service.rb:29
msgid "Module %{module_name} not found in environment %{environment_name}."
msgstr ""
#: ../lib/puppet/interface.rb:154
msgid "Cannot create face %{name} with invalid version number '%{version}'!"
msgstr ""
#: ../lib/puppet/interface/action.rb:79 ../lib/puppet/interface/action.rb:123
msgid "The rendering format must be a symbol, not %{class_name}"
msgstr ""
#. TRANSLATORS 'set_rendering_method_for' and 'Proc' should not be translated
#: ../lib/puppet/interface/action.rb:97
msgid "The second argument to set_rendering_method_for must be a Proc"
msgstr ""
#. TRANSLATORS 'set_rendering_method_for' and 'Proc' should not be translated
#: ../lib/puppet/interface/action.rb:100
msgid "The second argument to set_rendering_method_for must be a Proc, not %{class_name}"
msgstr ""
#. TRANSLATORS 'when_rendering', 'when_invoked' are method names and should not be translated
#: ../lib/puppet/interface/action.rb:109
msgid "The when_rendering method for the %{face} face %{name} action takes either just one argument, the result of when_invoked, or the result plus the %{arg_count} arguments passed to the when_invoked block, not a variable number"
msgstr ""
#. TRANSLATORS 'when_rendering', 'when_invoked' are method names and should not be translated
#: ../lib/puppet/interface/action.rb:115
msgid "The when_rendering method for the %{face} face %{name} action takes either just one argument, the result of when_invoked, or the result plus the %{arg_count} arguments passed to the when_invoked block, not %{string}"
msgstr ""
#: ../lib/puppet/interface/action.rb:126
msgid "You can't define a rendering method for %{type} twice"
msgstr ""
#. TRANSLATORS 'when_invoked' should not be translated
#: ../lib/puppet/interface/action.rb:236
msgid "when_invoked requires at least one argument (options) for action %{name}"
msgstr ""
#: ../lib/puppet/interface/action.rb:285 ../lib/puppet/interface/option_manager.rb:59
msgid "Option %{option} conflicts with existing option %{conflict}"
msgstr ""
#: ../lib/puppet/interface/action.rb:290
msgid "Option %{option} conflicts with existing option %{conflict} on %{face}"
msgstr ""
#. TRANSLATORS 'Puppet.settings' should not be translated
#. TRANSLATORS 'Puppet.settings' references to the Puppet settings options and should not be translated
#: ../lib/puppet/interface/action.rb:318 ../lib/puppet/interface/option_manager.rb:15
msgid "Global option %{option} does not exist in Puppet.settings"
msgstr ""
#: ../lib/puppet/interface/action.rb:367
msgid "Multiple aliases for the same option passed: %{overlap_list}"
msgstr ""
#: ../lib/puppet/interface/action.rb:373
msgid "Unknown options passed: %{unknown_list}"
msgstr ""
#: ../lib/puppet/interface/action.rb:391
msgid "The following options are required: %{missing_list}"
msgstr ""
#. TRANSLATORS 'when_rendering' is a method name and should not be translated
#: ../lib/puppet/interface/action_builder.rb:64
msgid "You must give a rendering format to when_rendering"
msgstr ""
#. TRANSLATORS 'when_rendering' is a method name and should not be translated
#: ../lib/puppet/interface/action_builder.rb:68
msgid "You must give a block to when_rendering"
msgstr ""
#. TRANSLATORS 'render_as' is a method name and should not be translated
#: ../lib/puppet/interface/action_builder.rb:129
msgid "You must give a rendering format to render_as"
msgstr ""
#: ../lib/puppet/interface/action_builder.rb:134
msgid "%{value} is not a valid rendering format: %{formats_list}"
msgstr ""
#. TRANSLATORS 'when_invoked' is a method name and should not be translated and 'block' is a Ruby code block
#: ../lib/puppet/interface/action_builder.rb:159
msgid "actions need to know what to do when_invoked; please add the block"
msgstr ""
#: ../lib/puppet/interface/action_manager.rb:21
msgid "Redefining action %{name} for %{self}"
msgstr ""
#. TRANSLATORS 'Face' refers to a programming API in Puppet, 'summary' and 'description' are specifc attribute names and should not be translated
#: ../lib/puppet/interface/documentation.rb:61
msgid "Face summary should be a single line; put the long text in 'description' instead."
msgstr ""
#. TRANSLATORS 'author' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:206
msgid "author must be a string; use multiple statements for multiple authors"
msgstr ""
#. TRANSLATORS 'author' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:211
msgid "author should be a single line; use multiple statements for multiple authors"
msgstr ""
#. TRANSLATORS 'author' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:231
msgid "author should be a single line; use multiple statements"
msgstr ""
#. TRANSLATORS 'copyright' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:252
msgid "copyright takes the owners names, then the years covered"
msgstr ""
#. TRANSLATORS 'copyright' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:276
msgid "copyright owner must be a string or an array of strings"
msgstr ""
#. TRANSLATORS 'copyright' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:312
msgid "copyright with a year %{value} is very strange; did you accidentally add or subtract two years?"
msgstr ""
#. TRANSLATORS 'copyright' is an attribute name and should not be translated
#. TRANSLATORS 'copyright' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:328 ../lib/puppet/interface/documentation.rb:333
msgid "%{value} is not a good copyright year or range"
msgstr ""
#. TRANSLATORS 'copyright' is an attribute name and should not be translated
#: ../lib/puppet/interface/documentation.rb:352
msgid "%{value} is not a good copyright year, set, or range"
msgstr ""
#: ../lib/puppet/interface/face_collection.rb:120
msgid ""
"Failed to load face %{name}:\n"
"%{detail}"
msgstr ""
#. TRANSLATORS 'face' refers to a programming API in Puppet
#: ../lib/puppet/interface/face_collection.rb:132
msgid "%{name} (%{class_name}) is not a valid face name"
msgstr ""
#: ../lib/puppet/interface/option.rb:22
msgid "%{option}: long options need two dashes (--)"
msgstr ""
#: ../lib/puppet/interface/option.rb:37
msgid "%{option}: already defined in puppet"
msgstr ""
#: ../lib/puppet/interface/option.rb:41
msgid "%{option}: duplicates existing alias %{duplicate} in %{parent}"
msgstr ""
#: ../lib/puppet/interface/option.rb:47
msgid "%{option} is not valid for an option argument"
msgstr ""
#: ../lib/puppet/interface/option.rb:52
msgid "No option declarations found while building"
msgstr ""
#: ../lib/puppet/interface/option.rb:65
msgid "Option %{name} is inconsistent about taking an argument"
msgstr ""
#: ../lib/puppet/interface/option.rb:72
msgid "Options with optional arguments are not supported"
msgstr ""
#: ../lib/puppet/interface/option.rb:75
msgid "Option %{name} is inconsistent about the argument being optional"
msgstr ""
#: ../lib/puppet/interface/option.rb:91
msgid "Can't find a name in the declaration %{declaration}"
msgstr ""
#: ../lib/puppet/interface/option.rb:100
msgid "%{name} is an invalid option name"
msgstr ""
#: ../lib/puppet/interface/option.rb:122 ../lib/puppet/interface/option.rb:139
msgid "%{name} can't be optional and have a default value"
msgstr ""
#. TRANSLATORS 'proc' is a Ruby block of code
#: ../lib/puppet/interface/option.rb:126
msgid "default value for %{name} is a %{class_name}, not a proc"
msgstr ""
#. TRANSLATORS 'proc' is a Ruby block of code
#: ../lib/puppet/interface/option.rb:148
msgid "before action hook for %{name} is a %{class_name}, not a proc"
msgstr ""
#. TRANSLATORS 'proc' is a Ruby block of code
#: ../lib/puppet/interface/option.rb:159
msgid "after action hook for %{name} is a %{class_name}, not a proc"
msgstr ""
#. TRANSLATORS 'before_action' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:45
msgid "%{option} before_action requires a block"
msgstr ""
#. TRANSLATORS 'before_action' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:49
msgid "%{option} already has a before_action set"
msgstr ""
#. TRANSLATORS 'before_action' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:53
msgid "before_action takes three arguments, action, args, and options"
msgstr ""
#. TRANSLATORS 'after_action' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:65
msgid "%{option} after_action requires a block"
msgstr ""
#. TRANSLATORS 'after_action' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:69
msgid "%{option} already has an after_action set"
msgstr ""
#. TRANSLATORS 'after_action' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:73
msgid "after_action takes three arguments, action, args, and options"
msgstr ""
#. TRANSLATORS 'default_to' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:94
msgid "%{option} default_to requires a block"
msgstr ""
#: ../lib/puppet/interface/option_builder.rb:97
msgid "%{option} already has a default value"
msgstr ""
#. TRANSLATORS 'default_to' is a method name and should not be translated
#: ../lib/puppet/interface/option_builder.rb:101
msgid "%{option} default_to block should not take any arguments"
msgstr ""
#: ../lib/puppet/interface/option_manager.rb:67
msgid "Option %{option} conflicts with existing option %{conflict} on %{action}"
msgstr ""
#. TRANSLATORS 'Puppet::Type.newtype' should not be translated
#: ../lib/puppet/metatype/manager.rb:78
msgid "Puppet::Type.newtype(%{name}) now expects a hash as the second argument, not %{argument}"
msgstr ""
#. TRANSLATORS 'new%{method}' will become a method name, do not translate this string
#: ../lib/puppet/metatype/manager.rb:111
msgid "'new%{method}' method already exists; skipping"
msgstr ""
#. TRANSLATORS 'puppet/type/%{name}' should not be translated
#: ../lib/puppet/metatype/manager.rb:174
msgid "Loaded puppet/type/%{name} but no class was created"
msgstr ""
#. TRANSLATORS 'metadata.json' is a specific file name and should not be translated.
#: ../lib/puppet/module.rb:225
msgid "%{name} has an invalid and unparsable metadata.json file. The parse error: %{error}"
msgstr ""
#: ../lib/puppet/module/plan.rb:41
msgid "Plan %{plan_name} not found in module %{module_name}."
msgstr ""
#: ../lib/puppet/module/plan.rb:64
msgid "Plan names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores"
msgstr ""
#: ../lib/puppet/module/plan.rb:66
msgid "Plan name cannot have extension %{ext}, must be .pp or .yaml"
msgstr ""
#: ../lib/puppet/module/plan.rb:69
msgid "Plan name cannot be a reserved word, but was '%{name}'"
msgstr ""
#: ../lib/puppet/module/plan.rb:72
msgid "Plan name cannot be a Puppet data type, but was '%{name}'"
msgstr ""
#: ../lib/puppet/module/task.rb:25 ../lib/puppet/module/task.rb:224
msgid "Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores"
msgstr ""
#: ../lib/puppet/module/task.rb:42
msgid "Task %{task_name} not found in module %{module_name}."
msgstr ""
#: ../lib/puppet/module/task.rb:87 ../lib/puppet/module/task.rb:93
msgid "The 'files' task metadata expects an array, got %{files}."
msgstr ""
#: ../lib/puppet/module/task.rb:108
msgid "Could not find module %{module_name} containing task file %{filename}"
msgstr ""
#: ../lib/puppet/module/task.rb:114
msgid "Files must be saved in module directories that Puppet makes available via mount points: %{mounts}"
msgstr ""
#: ../lib/puppet/module/task.rb:121
msgid "File pathnames cannot include relative paths"
msgstr ""
#: ../lib/puppet/module/task.rb:126
msgid "Could not find %{path} on disk"
msgstr ""
#: ../lib/puppet/module/task.rb:133
msgid "Directories specified in task metadata must include a trailing slash: %{dir}"
msgstr ""
#: ../lib/puppet/module/task.rb:140
msgid "Files specified in task metadata cannot include a trailing slash: %{file}"
msgstr ""
#: ../lib/puppet/module/task.rb:157
msgid "Task metadata for task %{name} does not specify implementations as an array"
msgstr ""
#: ../lib/puppet/module/task.rb:163
msgid "Task metadata for task %{name} does not specify requirements as an array"
msgstr ""
#: ../lib/puppet/module/task.rb:168
msgid "Task metadata for task %{name} specifies missing implementation %{implementation}"
msgstr ""
#: ../lib/puppet/module/task.rb:180
msgid "No source besides task metadata was found in directory %{directory} for task %{name}"
msgstr ""
#: ../lib/puppet/module/task.rb:184
msgid "Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them"
msgstr ""
#: ../lib/puppet/module/task.rb:241
msgid "Error reading metadata: %{message}"
msgstr ""
#: ../lib/puppet/module_tool.rb:39
msgid "Not a valid full name: %{full_module_name}"
msgstr ""
#: ../lib/puppet/module_tool/applications/application.rb:40
msgid "Could not determine module path"
msgstr ""
#: ../lib/puppet/module_tool/applications/application.rb:44
msgid "Unable to find metadata.json in module root at %{path} See https://puppet.com/docs/puppet/latest/modules_publishing.html for required file format."
msgstr ""
#: ../lib/puppet/module_tool/applications/application.rb:54
msgid "Could not parse JSON %{metadata_path}"
msgstr ""
#: ../lib/puppet/module_tool/applications/application.rb:60
msgid "A Modulefile was found in the root directory of the module. This file will be ignored and can safely be removed."
msgstr ""
#: ../lib/puppet/module_tool/applications/application.rb:76
msgid "Could not parse filename to obtain the username, module name and version. (%{release_name})"
msgstr ""
#: ../lib/puppet/module_tool/applications/application.rb:80
msgid "Invalid version format: %{version} (Semantic Versions are acceptable: http://semver.org)"
msgstr ""
#: ../lib/puppet/module_tool/applications/checksummer.rb:48 ../lib/puppet/module_tool/applications/checksummer.rb:50
msgid "No file containing checksums found."
msgstr ""
#: ../lib/puppet/module_tool/applications/installer.rb:89 ../lib/puppet/module_tool/applications/upgrader.rb:103
msgid "Downloading from %{host} ..."
msgstr ""
#: ../lib/puppet/module_tool/applications/installer.rb:137 ../lib/puppet/module_tool/applications/upgrader.rb:141
msgid "Resolving dependencies ..."
msgstr ""
#: ../lib/puppet/module_tool/applications/installer.rb:217
msgid "Preparing to install ..."
msgstr ""
#: ../lib/puppet/module_tool/applications/installer.rb:220
msgid "Installing -- do not interrupt ..."
msgstr ""
#: ../lib/puppet/module_tool/applications/uninstaller.rb:93
msgid "Either the `--ignore_changes` or `--force` argument must be specified to uninstall modules when running in FIPS mode."
msgstr ""
#: ../lib/puppet/module_tool/applications/unpacker.rb:50
msgid "Symlinks in modules are unsupported. Please investigate symlink %{from}->%{to}."
msgstr ""
#: ../lib/puppet/module_tool/applications/unpacker.rb:73
msgid "No valid metadata.json found!"
msgstr ""
#: ../lib/puppet/module_tool/applications/upgrader.rb:31
msgid "Module upgrade is prohibited in FIPS mode."
msgstr ""
#: ../lib/puppet/module_tool/applications/upgrader.rb:77
msgid "Found '%{name}' (%{version}) in %{dir} ..."
msgstr ""
#: ../lib/puppet/module_tool/applications/upgrader.rb:189
msgid "Preparing to upgrade ..."
msgstr ""
#: ../lib/puppet/module_tool/applications/upgrader.rb:192
msgid "Upgrading -- do not interrupt ..."
msgstr ""
#: ../lib/puppet/module_tool/contents_description.rb:57
msgid "Could not find/load type: %{name}"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:12
msgid "'%{module_name}' (%{version}) requested; '%{module_name}' (%{installed_version}) already installed"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:17 ../lib/puppet/module_tool/errors/installer.rb:55 ../lib/puppet/module_tool/errors/installer.rb:73 ../lib/puppet/module_tool/errors/shared.rb:80 ../lib/puppet/module_tool/errors/shared.rb:122
msgid "Could not install module '%{module_name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:18
msgid " Module '%{module_name}' (%{installed_version}) is already installed"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:19
msgid " Installed module has had changes made locally"
msgstr ""
#. TRANSLATORS `puppet module upgrade` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/installer.rb:21
msgid " Use `puppet module upgrade` to install a different version"
msgstr ""
#. TRANSLATORS `puppet module install --force` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/installer.rb:23
msgid " Use `puppet module install --force` to re-install only this module"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:33
msgid "Could not install '%{requested_package}'; no releases are available from %{source}"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:38
msgid "Could not install '%{requested_package}'"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:39 ../lib/puppet/module_tool/errors/shared.rb:59
msgid " No releases are available from %{source}"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:40
msgid " Does '%{requested_package}' have at least one published release?"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:50
msgid "'%{module_name}' (%{version}) requested; Path %{dir} is not a directory."
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:56
msgid " Path '%{directory}' exists but is not a directory."
msgstr ""
#. TRANSLATORS "mkdir -p '%{directory}'" is a command line example and should not be translated
#: ../lib/puppet/module_tool/errors/installer.rb:58
msgid " A potential solution is to rename the path and then \"mkdir -p '%{directory}'\""
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:68
msgid "'%{module_name}' (%{version}) requested; Permission is denied to create %{dir}."
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:74
msgid " Permission is denied when trying to create directory '%{directory}'."
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:75
msgid " A potential solution is to check the ownership and permissions of parent directories."
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:84
msgid "Attempt to install file with an invalid path into %{path} under %{dir}"
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:89
msgid "Could not install package with an invalid path."
msgstr ""
#: ../lib/puppet/module_tool/errors/installer.rb:90
msgid " Package attempted to install file into %{path} under %{directory}."
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:13
msgid "Could not %{action} '%{module_name}' (%{version}); no version satisfies all dependencies"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:18 ../lib/puppet/module_tool/errors/shared.rb:204 ../lib/puppet/module_tool/errors/upgrader.rb:59
msgid "Could not %{action} module '%{module_name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:21
msgid " The requested version cannot satisfy one or more of the following installed modules:"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:23
msgid " %{name}, installed: %{current_version}, expected: %{constraints}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:26
msgid " %{mod}, expects '%{name}': %{range}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:31
msgid " The requested version cannot satisfy all dependencies"
msgstr ""
#. TRANSLATORS `puppet module %{action} --ignore-dependencies` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:35
msgid " Use `puppet module %{action} '%{module_name}' --ignore-dependencies` to %{action} only this module"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:49
msgid "Could not %{action} '%{module_name}'; no releases are available from %{source}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:51
msgid "Could not %{action} '%{module_name}'; no releases matching '%{version}' are available from %{source}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:57
msgid "Could not %{action} '%{module_name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:60
msgid " Does '%{module_name}' have at least one published release?"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:62
msgid " No releases matching '%{requested_version}' are available from %{source}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:75
msgid "'%{module_name}' (%{version}) requested; installation conflict"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:83
msgid " Dependency '%{name}' (%{version}) would overwrite %{directory}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:85
msgid " Installation would overwrite %{directory}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:89
msgid " Currently, '%{current_name}' (%{current_version}) is installed to that directory"
msgstr ""
#. TRANSLATORS `puppet module install --ignore-dependencies` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:94
msgid " Use `puppet module install --ignore-dependencies` to install only this module"
msgstr ""
#. TRANSLATORS `puppet module install --force` is a command line and should not be translated
#. TRANSLATORS `puppet module install --force` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:97 ../lib/puppet/module_tool/errors/shared.rb:126
msgid " Use `puppet module install --force` to install this module anyway"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:111
msgid "'%{module_name}' (%{version}) requested; Invalid dependency cycle"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:116
msgid "You specified '%{name}' (%{version})"
msgstr ""
#. TRANSLATORS This message repeats as separate lines as a list under the heading "You specified '%{name}' (%{version})\n"
#: ../lib/puppet/module_tool/errors/shared.rb:119
msgid "This depends on '%{name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:123
msgid " No version of '%{module_name}' will satisfy dependencies"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:136
msgid "Could not %{action} '%{module_name}', did you mean '%{suggestion}'?"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:141 ../lib/puppet/module_tool/errors/shared.rb:158 ../lib/puppet/module_tool/errors/shared.rb:181 ../lib/puppet/module_tool/errors/shared.rb:222
msgid "Could not %{action} module '%{module_name}'"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:142
msgid " The name '%{module_name}' is invalid"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:143
msgid " Did you mean `puppet module %{action} %{suggestion}`?"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:153
msgid "Could not %{action} '%{module_name}'; module is not installed"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:159
msgid " Module '%{module_name}' is not installed"
msgstr ""
#. TRANSLATORS `puppet module %{action} %{suggestion}` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:162
msgid " You may have meant `puppet module %{action} %{suggestion}`"
msgstr ""
#. TRANSLATORS `puppet module install` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:165
msgid " Use `puppet module install` to install this module"
msgstr ""
#. TRANSLATORS "module path" refers to a set of directories where modules may be installed
#: ../lib/puppet/module_tool/errors/shared.rb:176
msgid "Could not %{action} '%{module_name}'; module appears in multiple places in the module path"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:182
msgid " Module '%{module_name}' appears multiple places in the module path"
msgstr ""
#. TRANSLATORS This is repeats as separate lines as a list under "Module '%{module_name}' appears multiple places in the module path"
#: ../lib/puppet/module_tool/errors/shared.rb:185
msgid " '%{module_name}' (%{version}) was found in %{path}"
msgstr ""
#. TRANSLATORS `--modulepath` is command line option and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:188
msgid " Use the `--modulepath` option to limit the search to specific directories"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:199
msgid "Could not %{action} '%{module_name}'; module has had changes made locally"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:205
msgid " Installed module has had changes made locally"
msgstr ""
#. TRANSLATORS `puppet module %{action} --ignore-changes` is a command line and should not be translated
#: ../lib/puppet/module_tool/errors/shared.rb:207
msgid " Use `puppet module %{action} --ignore-changes` to %{action} this module anyway"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:217
msgid "Could not %{action} '%{module_name}'; %{error}"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:223
msgid " Failure trying to parse metadata"
msgstr ""
#: ../lib/puppet/module_tool/errors/shared.rb:224
msgid " Original message was: %{message}"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:11
msgid "Could not uninstall '%{module_name}'; no installed version matches"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:16
msgid "Could not uninstall module '%{module_name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:17
msgid " No installed version of '%{module_name}' matches (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:19
msgid " '%{module_name}' (%{version}) is installed in %{path}"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:32
msgid "Could not uninstall '%{module_name}'; installed modules still depend upon it"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:38
msgid "Could not uninstall module '%{module_name}' (v%{requested_version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:40
msgid "Could not uninstall module '%{module_name}'"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:42
msgid " Other installed modules have dependencies on '%{module_name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/uninstaller.rb:44
msgid " '%{module_name}' (%{version}) requires '%{module_dep}' (%{dep_version})"
msgstr ""
#. TRANSLATORS `puppet module uninstall --force` is a command line option that should not be translated
#: ../lib/puppet/module_tool/errors/uninstaller.rb:47
msgid " Use `puppet module uninstall --force` to uninstall this module anyway"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:21
msgid "Could not upgrade '%{module_name}'; more recent versions not found"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:26
msgid "Could not upgrade module '%{module_name}' (%{version})"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:28
msgid " The installed version is already the latest version matching %{version}"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:30
msgid " There are %{count} newer versions"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:31
msgid " No combination of dependency upgrades would satisfy all dependencies"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:33
msgid " Dependencies will not be automatically upgraded across major versions"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:34
msgid " Upgrading one or more of these modules may permit the upgrade to succeed:"
msgstr ""
#. TRANSLATORS `puppet module upgrade --force` is a command line option that should not be translated
#: ../lib/puppet/module_tool/errors/upgrader.rb:41
msgid " Use `puppet module upgrade --force` to upgrade only this module"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:54
msgid "Could not %{action} '%{module_name}' (%{version}); downgrades are not allowed"
msgstr ""
#: ../lib/puppet/module_tool/errors/upgrader.rb:60
msgid " Downgrading is not allowed."
msgstr ""
#: ../lib/puppet/module_tool/install_directory.rb:23
msgid "Created target directory %{dir}"
msgstr ""
#: ../lib/puppet/module_tool/installed_modules.rb:65
msgid "%{module_name} (%{path}) has an invalid version number (%{version}). The version has been set to 0.0.0. If you are the maintainer for this module, please update the metadata.json with a valid Semantic Version (http://semver.org)."
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:71
msgid "Dependency conflict for %{module_name}: Dependency %{name} was given conflicting version requirements %{version_requirement} and %{dup_version}. Verify that there are no duplicates in the metadata.json."
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:176
msgid "the field must be a namespaced module name"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:178
msgid "the module name contains non-alphanumeric (or underscore) characters"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:180
msgid "the module name must begin with a letter"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:182
msgid "the namespace contains non-alphanumeric characters"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:185
msgid "Invalid 'name' field in metadata.json: %{err}"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:192
msgid "version string cannot be parsed as a valid Semantic Version"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:193
msgid "Invalid 'version' field in metadata.json: %{err}"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:205
msgid "field 'data_provider' contains non-alphanumeric characters"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:207
msgid "field 'data_provider' must begin with a letter"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:211
msgid "field 'data_provider' must be a string"
msgstr ""
#: ../lib/puppet/module_tool/metadata.rb:219
msgid "Invalid 'version_range' field in metadata.json: %{err}"
msgstr ""
#: ../lib/puppet/module_tool/shared_behaviors.rb:33
msgid "Downloading from %{uri} ..."
msgstr ""
#: ../lib/puppet/module_tool/shared_behaviors.rb:156
msgid "Could not download module: %{message}"
msgstr ""
#. TRANSLATORS "tar" is a program name and should not be translated
#: ../lib/puppet/module_tool/tar.rb:16
msgid "No suitable tar implementation found"
msgstr ""
#: ../lib/puppet/network/client_request.rb:16
msgid "Request is not set up; cannot build call"
msgstr ""
#: ../lib/puppet/network/format.rb:44
msgid "Unsupported option(s) %{options_list}"
msgstr ""
#: ../lib/puppet/network/format.rb:73
msgid "%{klass} does not respond to %{method}; can not render multiple instances to %{mime}"
msgstr ""
#: ../lib/puppet/network/format_handler.rb:68
msgid "No format matches the given format name or mime-type (%{format})"
msgstr ""
#. TRANSLATORS "intern" is a function name and should not be translated
#: ../lib/puppet/network/format_support.rb:16
msgid "Could not intern from %{format}: %{err}"
msgstr ""
#. TRANSLATORS "intern_multiple" is a function name and should not be translated
#: ../lib/puppet/network/format_support.rb:23
msgid "Could not intern_multiple from %{format}: %{err}"
msgstr ""
#. TRANSLATORS "render_multiple" is a function name and should not be translated
#: ../lib/puppet/network/format_support.rb:30
msgid "Could not render_multiple to %{format}: %{err}"
msgstr ""
#. TRANSLATORS "render" is a function name and should not be translated
#: ../lib/puppet/network/format_support.rb:115
msgid "Could not render to %{format}: %{err}"
msgstr ""
#. TRANSLATORS "mime" is a function name and should not be translated
#: ../lib/puppet/network/format_support.rb:124
msgid "Could not mime to %{format}: %{err}"
msgstr ""
#: ../lib/puppet/network/formats.rb:41 ../lib/puppet/network/formats.rb:54
msgid "Serialized YAML did not contain a valid instance of %{klass}: %{message}"
msgstr ""
#: ../lib/puppet/network/formats.rb:47
msgid "Serialized YAML did not contain a collection of instances when calling intern_multiple"
msgstr ""
#: ../lib/puppet/network/formats.rb:61
msgid "Serialized YAML did not contain a valid instance of %{klass}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:43
msgid "No handler for %{indirection}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:66
msgid "The indirection name must be purely alphanumeric, not '%{indirection_name}'"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:76
msgid "Indirection '%{indirection_name}' does not match url prefix '%{url_prefix}'"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:82
msgid "Could not find indirection '%{indirection_name}'"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:88
msgid "An environment parameter must be specified"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:93
msgid "The environment must be purely alphanumeric, not '%{environment}'"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:104
msgid "Could not find environment '%{environment}'"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:111
msgid "No request key specified in %{uri}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:123
msgid "Could not find %{value0} %{key}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:130
msgid "Rendered result in %{format}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:136
msgid "Sent response"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:144
msgid "Could not find %{indirection} %{key}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:156
msgid "Could not find instances in %{indirection} with '%{key}'"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:196
msgid "Failed to serialize %{model} for '%{key}': %{detail}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:210 ../lib/puppet/network/http/request.rb:69
msgid "No supported formats are acceptable (Accept: %{accepted_formats})"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:235
msgid "The request body is invalid: %{message}"
msgstr ""
#. TRANSLATORS "mime-type" is a keyword and should not be translated
#. TRANSLATORS "mime-type" is a keyword and should not be translated
#: ../lib/puppet/network/http/api/indirected_routes.rb:241 ../lib/puppet/network/http/request.rb:40
msgid "Client sent a mime-type (%{header}) that doesn't correspond to a format we support"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:247
msgid "No support for http method %{http_method}"
msgstr ""
#: ../lib/puppet/network/http/api/indirected_routes.rb:252
msgid "No support for plurality %{indirection} for %{http_method} operations"
msgstr ""
#: ../lib/puppet/network/http/api/indirection_type.rb:30
msgid "Not a valid indirection type"
msgstr ""
#: ../lib/puppet/network/http/connection.rb:48
msgid "Unrecognized option(s): %{opts}"
msgstr ""
#: ../lib/puppet/network/http/connection.rb:54
msgid "Expected an instance of Puppet::SSL::Verifier but was passed a %{klass}"
msgstr ""
#: ../lib/puppet/network/http/connection.rb:277
msgid "Too many HTTP redirections for %{host}:%{port}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:24
msgid "Not Acceptable: %{message}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:31
msgid "Not Found: %{message}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:38
msgid "Not Authorized: %{message}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:45
msgid "Bad Request: %{message}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:52
msgid "Method Not Allowed: %{message}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:59
msgid "Unsupported Media Type: %{message}"
msgstr ""
#: ../lib/puppet/network/http/error.rb:67
msgid "Server Error: %{message}"
msgstr ""
#: ../lib/puppet/network/http/handler.rb:23
msgid "Given multiple routes with identical path regexes: %{regexes}"
msgstr ""
#: ../lib/puppet/network/http/handler.rb:67
msgid "Processed request %{request_method} %{request_path}"
msgstr ""
#: ../lib/puppet/network/http/handler.rb:113
msgid "No route for %{request} %{path}"
msgstr ""
#: ../lib/puppet/network/http/handler.rb:138
msgid "Could not resolve %{ip}: %{detail}"
msgstr ""
#: ../lib/puppet/network/http/request.rb:22
msgid "Unknown arguments: %{args}"
msgstr ""
#: ../lib/puppet/network/http/request.rb:45
msgid "No Content-Type header was received, it isn't possible to unserialize the request"
msgstr ""
#: ../lib/puppet/network/http/request.rb:53
msgid "Missing required Accept header"
msgstr ""
#. TRANSLATORS 'ssl_context' is an argument and should not be translated
#: ../lib/puppet/network/http_pool.rb:64
msgid "An ssl_context is required when connecting to 'https://%{host}:%{port}'"
msgstr ""
#. TRANSLATORS 'ssl_context' is an argument and should not be translated
#: ../lib/puppet/network/http_pool.rb:72
msgid "An ssl_context is unnecessary when connecting to 'http://%{host}:%{port}' and will be ignored"
msgstr ""
#: ../lib/puppet/node.rb:28
msgid "No name provided in serialized data"
msgstr ""
#: ../lib/puppet/node.rb:102
msgid "Node names cannot be nil"
msgstr ""
#: ../lib/puppet/node.rb:140
msgid "Could not retrieve facts for %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/node.rb:158
msgid "The node parameter '%{param_name}' for node '%{node_name}' was already set to '%{value}'. It could not be set to '%{desired_value}'"
msgstr ""
#: ../lib/puppet/node.rb:201
msgid "Trusted node data modified for node %{name}"
msgstr ""
#: ../lib/puppet/node/environment.rb:251
msgid "The 'disable_per_environment_manifest' setting is true, and the '%{env_name}' environment has an environment.conf manifest that conflicts with the 'default_manifest' setting."
msgstr ""
#: ../lib/puppet/node/environment.rb:615 ../lib/puppet/pops/loaders.rb:306
msgid "Could not parse for environment %{env}: %{detail}"
msgstr ""
#: ../lib/puppet/pal/compiler.rb:88
msgid "The argument 'puppet_code' must be a String, got %{type}"
msgstr ""
#. TRANSLATORS, the 'ast' is the name of a parameter, do not translate
#: ../lib/puppet/pal/compiler.rb:130
msgid "The given 'ast' does not represent a literal value"
msgstr ""
#: ../lib/puppet/pal/compiler.rb:142
msgid "The argument 'code_string' must be a String, got %{type}"
msgstr ""
#: ../lib/puppet/pal/compiler.rb:155
msgid "The argument 'file' must be a String, got %{type}"
msgstr ""
#: ../lib/puppet/pal/compiler.rb:192
msgid "Given data_type value is not a data type, got '%{type}'"
msgstr ""
#. TRANSLATORS 'type' and 'title' are internal parameter names - do not translate
#: ../lib/puppet/pal/json_catalog_encoder.rb:55
msgid "Both type and title must be given"
msgstr ""
#. TRANSLATORS: do not translate the variable names in this error message
#. TRANSLATORS: do not translate the variable names in this error message
#: ../lib/puppet/pal/pal_impl.rb:77 ../lib/puppet/pal/pal_impl.rb:183
msgid "manifest_file or code_string cannot be given when configured_by_env is true"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:239
msgid "temporary environment name"
msgstr ""
#. TRANSLATORS: do not translate variable name string in these assertions
#: ../lib/puppet/pal/pal_impl.rb:244
msgid "A block must be given to 'in_tmp_environment'"
msgstr ""
#. TRANSLATORS terms in the assertions below are names of terms in code
#: ../lib/puppet/pal/pal_impl.rb:299
msgid "A block must be given to 'in_environment'"
msgstr ""
#. TRANSLATORS 'in_environment' is a name, do not translate
#: ../lib/puppet/pal/pal_impl.rb:304
msgid "The environment directory '%{env_dir}' does not exist"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:327
msgid "No directory found for the environment '%{env_name}' on the path '%{envpath}'"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:381
msgid "Given variables must be a hash, got %{type}"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:387
msgid "Given variable '%{varname}' has illegal name"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:391
msgid "Given value for '%{varname}' has illegal type - got: %{type}"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:565
msgid "Puppet Pal: %{what}"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:579
msgid "Cannot use '%{a_term}' and '%{b_term}' at the same time"
msgstr ""
#: ../lib/puppet/pal/pal_impl.rb:586
msgid "A block must be given"
msgstr ""
#: ../lib/puppet/parameter.rb:348
msgid "No resource set for %{name}"
msgstr ""
#: ../lib/puppet/parameter.rb:449
msgid "Munging failed for value %{value} in class %{class_name}: %{detail}"
msgstr ""
#: ../lib/puppet/parameter.rb:485
msgid "Validate method failed for class %{class_name}: %{detail}"
msgstr ""
#: ../lib/puppet/parameter/package_options.rb:23
msgid "Expected either a string or hash of options"
msgstr ""
#: ../lib/puppet/parameter/path.rb:28 ../lib/puppet/parameter/path.rb:54
msgid "%{name} only accepts a single path, not an array of paths"
msgstr ""
#: ../lib/puppet/parameter/path.rb:31
msgid "%{name} must be a fully qualified path"
msgstr ""
#: ../lib/puppet/parameter/value_collection.rb:23
msgid "Cannot alias nonexistent value %{value}"
msgstr ""
#. TRANSLATORS ':call' is a property and should not be translated
#: ../lib/puppet/parameter/value_collection.rb:138
msgid "Property option :call is deprecated and no longer used."
msgstr ""
#: ../lib/puppet/parameter/value_collection.rb:139
msgid "Please remove it."
msgstr ""
#: ../lib/puppet/parameter/value_collection.rb:188 ../lib/puppet/type/resources.rb:86
msgid "Invalid value %{value}."
msgstr ""
#: ../lib/puppet/parameter/value_collection.rb:189
msgid "Valid values are %{value_list}."
msgstr ""
#: ../lib/puppet/parameter/value_collection.rb:190
msgid "Valid values match %{pattern}."
msgstr ""
#: ../lib/puppet/parser/ast/leaf.rb:37
msgid "'%{value}' is not a valid hostname"
msgstr ""
#: ../lib/puppet/parser/ast/node.rb:6
msgid "names should be an array"
msgstr ""
#: ../lib/puppet/parser/ast/node.rb:8
msgid "Node inheritance is removed in Puppet 4.0.0. See http://links.puppet.com/puppet-node-inheritance-deprecation"
msgstr ""
#: ../lib/puppet/parser/ast/pops_bridge.rb:181
msgid "Instantiating Resource with type checked parameters - scope is missing, skipping type checking."
msgstr ""
#: ../lib/puppet/parser/ast/resource.rb:10
msgid "Use of Puppet::Parser::AST::Resource is deprecated and not fully functional"
msgstr ""
#: ../lib/puppet/parser/ast/resource_instance.rb:8
msgid "Use of Puppet::Parser::AST::ResourceInstance is deprecated"
msgstr ""
#: ../lib/puppet/parser/ast/resourceparam.rb:8
msgid "Use of Puppet::Parser::AST::ResourceParam is deprecated and not fully functional"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:29
msgid "Compilation has been halted because: %{error}"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:30
msgid "For more information, see https://puppet.com/docs/puppet/latest/environments_about.html"
msgstr ""
#. TRANSLATORS "stage" is a keyword in Puppet and should not be translated
#: ../lib/puppet/parser/compiler.rb:83
msgid "Only classes can set 'stage'; normal resources like %{resource} cannot change run stage"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:124
msgid "For compiling %{node}"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:128
msgid "Compile: Set node parameters"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:130
msgid "Compile: Created settings scope"
msgstr ""
#. TRANSLATORS "main" is a function name and should not be translated
#: ../lib/puppet/parser/compiler.rb:133
msgid "Compile: Evaluated main"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:135
msgid "Compile: Evaluated AST node"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:137
msgid "Compile: Evaluated node classes"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:139
msgid "Compile: Evaluated generators"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:141
msgid "Compile: Validate Catalog pre-finish"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:145
msgid "Compile: Finished catalog"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:149
msgid "Compile: Validate Catalog final"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:219
msgid "Could not find node statement with name 'default' or '%{names}'"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:237
msgid "No source for scope passed to evaluate_classes"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:247
msgid "Could not find class %{name} for %{node}"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:329
msgid "Evaluated collections"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:344
msgid "Evaluated definitions"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:373
msgid "Iterated (%{count}) on generators"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:384
msgid "Somehow looped more than 1000 times while evaluating host catalog"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:416
msgid "Could not find resource(s) %{resources} for overriding"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:427
msgid "Failed to realize virtual resources %{resources}"
msgstr ""
#. TRANSLATORS "main" is a function name and should not be translated
#: ../lib/puppet/parser/compiler.rb:460
msgid "Couldn't find main"
msgstr ""
#: ../lib/puppet/parser/compiler.rb:533
msgid "For initializing compiler"
msgstr ""
#: ../lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb:32
msgid "Could not find resource '%{res}' in parameter '%{param}'"
msgstr ""
#: ../lib/puppet/parser/functions.rb:44
msgid "The method 'Puppet::Parser::Functions.autoloader#loadall' is deprecated in favor of using 'Scope#call_function'."
msgstr ""
#: ../lib/puppet/parser/functions.rb:52
msgid "The method 'Puppet::Parser::Functions.autoloader#load(\"%{name}\")' is deprecated in favor of using 'Scope#call_function'."
msgstr ""
#: ../lib/puppet/parser/functions.rb:60
msgid "The method 'Puppet::Parser::Functions.autoloader#loaded?(\"%{name}\")' is deprecated in favor of using 'Scope#call_function'."
msgstr ""
#: ../lib/puppet/parser/functions.rb:191
msgid "Overwriting previous definition for function %{name}"
msgstr ""
#: ../lib/puppet/parser/functions.rb:197
msgid "Invalid statement type %{type}"
msgstr ""
#: ../lib/puppet/parser/functions.rb:209
msgid "Called %{name}"
msgstr ""
#: ../lib/puppet/parser/functions.rb:212
msgid "%{name}(): Wrong number of arguments given (%{arg_count} for %{arity})"
msgstr ""
#: ../lib/puppet/parser/functions.rb:214
msgid "%{name}(): Wrong number of arguments given (%{arg_count} for minimum %{min_arg_count})"
msgstr ""
#: ../lib/puppet/parser/functions.rb:220
msgid "custom functions must be called with a single array that contains the arguments. For example, function_example([1]) instead of function_example(1)"
msgstr ""
#: ../lib/puppet/parser/functions.rb:319
msgid "%{name}() can only be called using the 4.x function API. See Scope#call_function"
msgstr ""
#: ../lib/puppet/parser/functions/contain.rb:29
msgid "Calling function_contain via the Scope class is deprecated. Use Scope#call_function instead"
msgstr ""
#: ../lib/puppet/parser/functions/create_resources.rb:61
msgid "create_resources(): wrong number of arguments (%{count}; must be 2 or 3)"
msgstr ""
#: ../lib/puppet/parser/functions/create_resources.rb:62
msgid "create_resources(): second argument must be a hash"
msgstr ""
#: ../lib/puppet/parser/functions/create_resources.rb:64
msgid "create_resources(): third argument, if provided, must be a hash"
msgstr ""
#: ../lib/puppet/parser/functions/file.rb:32
msgid "Could not find any files from %{values}"
msgstr ""
#. TRANSLATORS "fully qualified" refers to a fully qualified file system path
#: ../lib/puppet/parser/functions/generate.rb:17
msgid "Generators must be fully qualified"
msgstr ""
#: ../lib/puppet/parser/functions/generate.rb:26
msgid "Generators can only contain alphanumerics, file separators, and dashes"
msgstr ""
#: ../lib/puppet/parser/functions/generate.rb:30
msgid "Can not use generators with '..' in them."
msgstr ""
#: ../lib/puppet/parser/functions/generate.rb:36
msgid "Failed to execute generator %{generator}: %{detail}"
msgstr ""
#. TRANSLATORS "function_include", "Scope", and "Scope#call_function" refer to Puppet internals and should not be translated
#: ../lib/puppet/parser/functions/include.rb:34
msgid "Calling function_include via the Scope class is deprecated. Use Scope#call_function instead"
msgstr ""
#: ../lib/puppet/parser/functions/inline_template.rb:24
msgid "Failed to parse inline template: %{detail}"
msgstr ""
#: ../lib/puppet/parser/functions/require.rb:40
msgid "Calling function_require via the Scope class is deprecated. Use Scope#call_function instead"
msgstr ""
#: ../lib/puppet/parser/functions/template.rb:33
msgid "Failed to parse template %{file}:"
msgstr ""
#: ../lib/puppet/parser/functions/template.rb:34
msgid " Filepath: %{file_path}"
msgstr ""
#: ../lib/puppet/parser/functions/template.rb:35
msgid " Line: %{line}"
msgstr ""
#: ../lib/puppet/parser/functions/template.rb:36
msgid " Detail: %{detail}"
msgstr ""
#: ../lib/puppet/parser/relationship.rb:32
msgid "Invalid relationship type %{relationship_type}"
msgstr ""
#: ../lib/puppet/parser/relationship.rb:42
msgid "Could not find resource '%{source}' for relationship on '%{target}'"
msgstr ""
#: ../lib/puppet/parser/relationship.rb:45
msgid "Could not find resource '%{target}' for relationship from '%{source}'"
msgstr ""
#: ../lib/puppet/parser/resource.rb:62
msgid "Could not find stage %{stage} specified by %{resource}"
msgstr ""
#: ../lib/puppet/parser/resource.rb:72
msgid "Evaluated resource %{res}"
msgstr ""
#: ../lib/puppet/parser/resource.rb:126
msgid "Resources require a hash as last argument"
msgstr ""
#: ../lib/puppet/parser/resource.rb:127
msgid "Resources require a scope"
msgstr ""
#: ../lib/puppet/parser/resource.rb:160
msgid "Only subclasses can override parameters"
msgstr ""
#: ../lib/puppet/parser/resource.rb:166
msgid "Attempt to override an already evaluated resource with new values"
msgstr ""
#: ../lib/puppet/parser/resource.rb:168
msgid "Attempt to override an already evaluated resource, defined at %{error_location}, with new values"
msgstr ""
#: ../lib/puppet/parser/resource.rb:297
msgid "Parameter '%{name}' is already set on %{resource}; cannot redefine"
msgstr ""
#: ../lib/puppet/parser/resource.rb:300
msgid "Parameter '%{name}' is already set on %{resource} at %{error_location}; cannot redefine"
msgstr ""
#: ../lib/puppet/parser/resource.rb:305
msgid "Parameter '%{name}' is already set on %{resource} by %{source}; cannot redefine"
msgstr ""
#: ../lib/puppet/parser/resource.rb:308
msgid "Parameter '%{name}' is already set on %{resource} by %{source} at %{error_location}; cannot redefine"
msgstr ""
#: ../lib/puppet/parser/resource.rb:347
msgid "Duplicate parameter '%{param}' for on %{resource}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:156
msgid "Numerical variables cannot be changed. Attempt to set $%{name}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:161
msgid "Numerical variables cannot be deleted: Attempt to delete: $%{name}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:215
msgid "%{callee}: expects a value for parameter $%{to}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:216
msgid "%{callee}: default expression for $%{from} tries to illegally access not yet evaluated $%{to}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:235
msgid "Attempt to assign variable %{name} when evaluating parameters"
msgstr ""
#: ../lib/puppet/parser/scope.rb:378
msgid "you must pass a compiler instance to a new scope object"
msgstr ""
#: ../lib/puppet/parser/scope.rb:494
msgid "Scope variable name %{name} is a %{klass}, not a string"
msgstr ""
#: ../lib/puppet/parser/scope.rb:540
msgid "Interpolation failed with '%{name}', but compilation continuing; %{reason}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:661
msgid "class %{classname} could not be found"
msgstr ""
#: ../lib/puppet/parser/scope.rb:663
msgid "class %{classname} has not been evaluated"
msgstr ""
#: ../lib/puppet/parser/scope.rb:709
msgid "Default already defined for %{type} { %{param} }; cannot redefine"
msgstr ""
#: ../lib/puppet/parser/scope.rb:769
msgid "Cannot assign to a numeric match result variable '$%{name}'"
msgstr ""
#: ../lib/puppet/parser/scope.rb:772
msgid "Scope variable name %{name} is a %{class_type}, not a string"
msgstr ""
#: ../lib/puppet/parser/scope.rb:777 ../lib/puppet/parser/scope.rb:782
msgid "Attempt to assign to a reserved variable name: '%{name}'"
msgstr ""
#: ../lib/puppet/parser/scope.rb:787
msgid "Cannot reassign variable '$%{name}'"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1018
msgid "Invalid regex match data. Got a %{klass}"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1026
msgid "Scope#find_resource_type() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1031
msgid "Scope#find_builtin_resource_type() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1036
msgid "Scope#find_defined_resource_type() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1050
msgid "Function %{name} not defined despite being loaded!"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1057
msgid "Scope#resolve_type_and_title() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1077
msgid "Cannot use undef as a class name"
msgstr ""
#: ../lib/puppet/parser/scope.rb:1079
msgid "Cannot use empty string as a class name"
msgstr ""
#. TRANSLATORS "Class" and "Type" are Puppet keywords and should not be translated
#: ../lib/puppet/parser/scope.rb:1088
msgid "Cannot use an unspecific Class[] Type"
msgstr ""
#. TRANSLATORS "Resource" is a class name and should not be translated
#: ../lib/puppet/parser/scope.rb:1115
msgid "Cannot use an unspecific Resource[] where a Resource['class', name] is expected"
msgstr ""
#. TRANSLATORS "Resource" is a class name and should not be translated
#: ../lib/puppet/parser/scope.rb:1119
msgid "Cannot use a Resource[%{type_name}] where a Resource['class', name] is expected"
msgstr ""
#. TRANSLATORS "Resource" is a class name and should not be translated
#: ../lib/puppet/parser/scope.rb:1123
msgid "Cannot use an unspecific Resource['class'] where a Resource['class', name] is expected"
msgstr ""
#. TRANSLATORS, "For running script" is not user facing
#. TRANSLATORS "main" is a function name and should not be translated
#: ../lib/puppet/parser/script_compiler.rb:46
msgid "Script: Evaluated main"
msgstr ""
#: ../lib/puppet/parser/script_compiler.rb:113
msgid "having multiple named scopes is not supported when scripting"
msgstr ""
#: ../lib/puppet/parser/templatewrapper.rb:67
msgid "Could not find template '%{filename}'"
msgstr ""
#: ../lib/puppet/parser/templatewrapper.rb:84
msgid "Bound template variables for %{template_source} in %%{seconds} seconds"
msgstr ""
#: ../lib/puppet/parser/templatewrapper.rb:92
msgid "Interpolated template %{template_source} in %%{seconds} seconds"
msgstr ""
#: ../lib/puppet/parser/type_loader.rb:103
msgid "No file(s) found for import of '%{pattern}'"
msgstr ""
#: ../lib/puppet/pops/evaluator/access_operator.rb:289
msgid "Cannot use %{key} where %{expected} is expected"
msgstr ""
#. TRANSLATORS 'CollectExpression' is a class name and should not be translated
#: ../lib/puppet/pops/evaluator/collector_transformer.rb:15
msgid "Expected CollectExpression"
msgstr ""
#: ../lib/puppet/pops/evaluator/collector_transformer.rb:106
msgid "Cannot transform a number to a tag"
msgstr ""
#: ../lib/puppet/pops/evaluator/collector_transformer.rb:169 ../lib/puppet/pops/evaluator/collector_transformer.rb:231
msgid "Cannot transform object of class %{klass}"
msgstr ""
#: ../lib/puppet/pops/evaluator/collectors/abstract_collector.rb:31
msgid "Exported resource try to override without parameters"
msgstr ""
#: ../lib/puppet/pops/evaluator/collectors/exported_collector.rb:52
msgid "A duplicate resource was found while collecting exported resources, with the type and title %{title}"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:51
msgid "A String is not comparable to a non String"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:66
msgid "A Numeric is not comparable to non Numeric"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:94
msgid "Symbol not comparable to non Symbol"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:99
msgid "Timespans are only comparable to Timespans, Integers, and Floats"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:104
msgid "Timestamps are only comparable to Timestamps, Integers, and Floats"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:109
msgid "Versions not comparable to non Versions"
msgstr ""
#: ../lib/puppet/pops/evaluator/compare_operator.rb:114
msgid "Only Strings, Numbers, Timespans, Timestamps, and Versions are comparable"
msgstr ""
#. TRANSLATORS 'inline_epp()' is a method name and 'epp' refers to 'Embedded Puppet (EPP) template' and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:9
msgid "inline_epp(): the first argument must be a String with the epp source text, got a %{class_name}"
msgstr ""
#. TRANSLATORS 'inline_epp()' is a method name and 'EPP' refers to 'Embedded Puppet (EPP) template' and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:19
msgid "inline_epp(): Invalid EPP: %{detail}"
msgstr ""
#. TRANSLATORS 'epp()' is a method name and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:29
msgid "epp(): the first argument must be a String with the filename, got a %{class_name}"
msgstr ""
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:41
msgid "Could not find template '%{file}'"
msgstr ""
#. TRANSLATORS 'epp()' is a method name and 'EPP' refers to 'Embedded Puppet (EPP) template' and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:50
msgid "epp(): Invalid EPP: %{detail}"
msgstr ""
#. TRANSLATORS 'LambdaExpression' is a class name and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:63
msgid "%{function_name}(): the parser did not produce a LambdaExpression, got '%{class_name}'"
msgstr ""
#. TRANSLATORS 'EppExpression' is a class name and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:68
msgid "%{function_name}(): the parser did not produce an EppExpression, got '%{class_name}'"
msgstr ""
#. TRANSLATORS 'EPP' refers to 'Embedded Puppet (EPP) template'
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:73
msgid "%{function_name}(): The EPP template contains illegal expressions (definitions)"
msgstr ""
#. TRANSLATORS 'template_args' is a variable name and should not be translated
#: ../lib/puppet/pops/evaluator/epp_evaluator.rb:114
msgid "%{function_name}(): the template_args must be a Hash, got a %{class_name}"
msgstr ""
#: ../lib/puppet/pops/evaluator/evaluator_impl.rb:241
msgid "multi var assignment from class"
msgstr ""
#: ../lib/puppet/pops/evaluator/evaluator_impl.rb:757
msgid "break() from context where this is illegal"
msgstr ""
#: ../lib/puppet/pops/evaluator/evaluator_impl.rb:1234
msgid "Can only append Array or Hash to a Hash"
msgstr ""
#: ../lib/puppet/pops/evaluator/evaluator_impl.rb:1238
msgid "An URI can only be merged with an URI or String"
msgstr ""
#: ../lib/puppet/pops/evaluator/evaluator_impl.rb:1241
msgid "Can only append Binary to a Binary"
msgstr ""
#: ../lib/puppet/pops/evaluator/evaluator_impl.rb:1274
msgid "Can only delete from an Array or Hash."
msgstr ""
#: ../lib/puppet/pops/evaluator/external_syntax_support.rb:23 ../lib/puppet/pops/evaluator/runtime3_support.rb:24 ../lib/puppet/pops/evaluator/runtime3_support.rb:525
msgid "Internal Error: Configuration of runtime error handling wrong: should have raised exception"
msgstr ""
#: ../lib/puppet/pops/evaluator/runtime3_converter.rb:105
msgid "Use of an Iterator is not supported here"
msgstr ""
#. TRANSLATORS 'PClassType' and 'PResourceType' are Puppet types and should not be translated
#: ../lib/puppet/pops/evaluator/runtime3_converter.rb:151
msgid "Cannot split the type %{class_name}, it represents neither a PClassType, nor a PResourceType."
msgstr ""
#: ../lib/puppet/pops/evaluator/runtime3_resource_support.rb:32
msgid "Unknown resource type: '%{type}'"
msgstr ""
#: ../lib/puppet/pops/evaluator/runtime3_support.rb:149
msgid "Internal error - attempt to create a local scope without a hash"
msgstr ""
#: ../lib/puppet/pops/evaluator/runtime3_support.rb:289
msgid "Unknown function '%{name}'"
msgstr ""
#: ../lib/puppet/pops/functions/dispatch.rb:90
msgid "Unknown injection %{injection_name}"
msgstr ""
#: ../lib/puppet/pops/functions/function.rb:111
msgid "Function %{class_name}(): cannot call function '%{function_name}' - no loader specified"
msgstr ""
#: ../lib/puppet/pops/functions/function.rb:127
msgid "Function %{class_name}(): Unknown function: '%{function_name}'"
msgstr ""
#: ../lib/puppet/pops/issue_reporter.rb:73
msgid "Language validation logged %{error_count} errors, and %{warning_count} warnings. Giving up"
msgstr ""
#: ../lib/puppet/pops/issue_reporter.rb:76
msgid "Language validation logged %{error_count} errors. Giving up"
msgstr ""
#: ../lib/puppet/pops/issues.rb:53
msgid "Error while reporting issue: %{code}. %{message}"
msgstr ""
#. TRANSLATORS ":label" is a keyword and should not be translated
#: ../lib/puppet/pops/issues.rb:94
msgid "Label provider key :label must be set to produce the text of the message!"
msgstr ""
#. TRANSLATORS ":semantic" is a keyword and should not be translated
#: ../lib/puppet/pops/issues.rb:102
msgid "Label provider key :semantic must be set to produce the text of the message!"
msgstr ""
#: ../lib/puppet/pops/issues.rb:147
msgid "%{issue} may not have a name containing a hyphen. The name '%{name}' is not legal"
msgstr ""
#: ../lib/puppet/pops/issues.rb:157
msgid "A variable name may not contain a hyphen. The name '%{name}' is not legal"
msgstr ""
#: ../lib/puppet/pops/issues.rb:165
msgid "Classes, definitions, and nodes may only appear at toplevel or inside other classes"
msgstr ""
#: ../lib/puppet/pops/issues.rb:169
msgid "%{value} may only appear at toplevel"
msgstr ""
#: ../lib/puppet/pops/issues.rb:173
msgid "Illegal attempt to assign to '%{name}'. Cannot assign to variables in other namespaces"
msgstr ""
#: ../lib/puppet/pops/issues.rb:178
msgid "Illegal attempt to assign to '%{value}'. Not an assignable reference"
msgstr ""
#: ../lib/puppet/pops/issues.rb:184
msgid "Cannot reassign built in (or already assigned) variable '$%{var}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:186
msgid "Cannot reassign variable '$%{var}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:192
msgid "Attempt to assign to a reserved variable name: '$%{var}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:197
msgid "Illegal attempt to assign to the numeric match result variable '$%{var}'. Numeric variables are not assignable"
msgstr ""
#: ../lib/puppet/pops/issues.rb:202
msgid "Assignment not allowed here"
msgstr ""
#: ../lib/puppet/pops/issues.rb:207
msgid "The numeric parameter name '$%{name}' cannot be used (clashes with numeric match result variables)"
msgstr ""
#: ../lib/puppet/pops/issues.rb:215
msgid "Illegal attempt to assign via [index/key]. Not an assignable reference"
msgstr ""
#: ../lib/puppet/pops/issues.rb:222
msgid "Illegal attempt to assign to %{value} via [index/key]. Not an assignable reference"
msgstr ""
#: ../lib/puppet/pops/issues.rb:226
msgid "Mismatched number of assignable entries and values, expected %{expected}, got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:230
msgid "No value for required key '%{key}' in assignment to variables from hash"
msgstr ""
#: ../lib/puppet/pops/issues.rb:234
msgid "No value for required variable '$%{name}' in assignment to variables from class reference"
msgstr ""
#: ../lib/puppet/pops/issues.rb:238
msgid "The operator '%{operator}' is no longer supported. See http://links.puppet.com/remove-plus-equals"
msgstr ""
#: ../lib/puppet/pops/issues.rb:244
msgid "The operator '%{operator}' is not supported."
msgstr ""
#: ../lib/puppet/pops/issues.rb:251
msgid "The operator '%{operator}' in %{value} is not supported."
msgstr ""
#: ../lib/puppet/pops/issues.rb:257
msgid "Operator '%{operator}' is not applicable to %{left}."
msgstr ""
#: ../lib/puppet/pops/issues.rb:261
msgid "Operator '%{operator}' is not applicable to %{left} when right side is %{right}."
msgstr ""
#: ../lib/puppet/pops/issues.rb:265
msgid "Comparison of: %{left} %{operator} %{right}, is not possible. Caused by '%{detail}'."
msgstr ""
#: ../lib/puppet/pops/issues.rb:269
msgid "Can not convert right match operand to a regular expression. Caused by '%{detail}'."
msgstr ""
#: ../lib/puppet/pops/issues.rb:273
msgid "Left match operand must result in a String value. Got %{left}."
msgstr ""
#: ../lib/puppet/pops/issues.rb:280
msgid "Invalid use of expression. %{value} does not produce a value"
msgstr ""
#: ../lib/puppet/pops/issues.rb:286
msgid "Illegal +> operation on attribute %{attr}. This operator can not be used in %{expression}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:290
msgid "Illegal name. The given name '%{name}' does not conform to the naming rule /^((::)?[a-z_]\\w*)(::[a-z]\\w*)*$/"
msgstr ""
#: ../lib/puppet/pops/issues.rb:294
msgid "Illegal type mapping. Expected a Type on the left side, got %{expression}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:298
msgid "Illegal type mapping. Expected a Tuple[Regexp,String] on the left side, got %{expression}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:302
msgid "Illegal parameter name. The given name '%{name}' does not conform to the naming rule /^[a-z_]\\w*$/"
msgstr ""
#: ../lib/puppet/pops/issues.rb:306
msgid "Illegal variable name, The given name '%{name}' does not conform to the naming rule /^((::)?[a-z]\\w*)*((::)?[a-z_]\\w*)$/"
msgstr ""
#: ../lib/puppet/pops/issues.rb:310
msgid "Illegal numeric variable name, The given name '%{name}' must be a decimal value if it starts with a digit 0-9"
msgstr ""
#: ../lib/puppet/pops/issues.rb:316
msgid "Illegal type reference. The given name '%{name}' does not conform to the naming rule"
msgstr ""
#: ../lib/puppet/pops/issues.rb:324
msgid "You cannot collect exported resources without storeconfigs being set; the collection will be ignored"
msgstr ""
#: ../lib/puppet/pops/issues.rb:332
msgid "You cannot collect exported resources without storeconfigs being set; the export is ignored"
msgstr ""
#: ../lib/puppet/pops/issues.rb:338
msgid "The hostname '%{hostname}' contains illegal characters (only letters, digits, '_', '-', and '.' are allowed)"
msgstr ""
#: ../lib/puppet/pops/issues.rb:344
msgid "An interpolated expression is not allowed in a hostname of a node"
msgstr ""
#: ../lib/puppet/pops/issues.rb:351
msgid "Illegal expression. %{expression} is unacceptable as %{feature} in %{container}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:357
msgid "Illegal variable expression. %{expression} did not produce a variable name (String or Numeric)."
msgstr ""
#: ../lib/puppet/pops/issues.rb:364
msgid "Illegal query expression. %{expression} cannot be used in a query"
msgstr ""
#: ../lib/puppet/pops/issues.rb:370
msgid "Resource Defaults are not virtualizable"
msgstr ""
#: ../lib/puppet/pops/issues.rb:374
msgid "Classes are not virtualizable"
msgstr ""
#: ../lib/puppet/pops/issues.rb:381
msgid "Attempt to use unsupported range in %{expression}, %{count} values given for max 1"
msgstr ""
#: ../lib/puppet/pops/issues.rb:387
msgid "Expressions of type %{expression} are not supported in this version of Puppet"
msgstr ""
#: ../lib/puppet/pops/issues.rb:391
msgid "Illegal relationship operand, can not form a relationship with %{expression}. A Catalog type is required."
msgstr ""
#: ../lib/puppet/pops/issues.rb:395
msgid "Illegal relationship operand, can not form a relationship with something of type %{expression_type}. A Catalog type is required."
msgstr ""
#: ../lib/puppet/pops/issues.rb:399
msgid "String supports [] with one or two arguments. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:403
msgid "String-Type [] requires all arguments to be integers (or default). Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:407
msgid "Array supports [] with one or two arguments. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:411
msgid "Hash supports [] with one or more arguments. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:415
msgid "Integer-Type supports [] with one or two arguments (from, to). Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:419
msgid "Integer-Type [] requires all arguments to be integers (or default). Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:423
msgid "A Type's size constraint arguments must be a single Integer type, or 1-2 integers (or default). Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:427
msgid "Float-Type supports [] with one or two arguments (from, to). Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:431
msgid "Float-Type [] requires all arguments to be floats, or integers (or default). Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:436
msgid "%{expression}[] cannot use %{actual} where one of the following is expected: %{expected}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:438
msgid "%{expression}[] cannot use %{actual} where %{expected} is expected"
msgstr ""
#: ../lib/puppet/pops/issues.rb:443
msgid "A substring operation does not accept %{label_article} %{actual_type} as a character index. Expected an Integer"
msgstr ""
#: ../lib/puppet/pops/issues.rb:447
msgid "%{expression}[] argument must be a Type or a String. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:451
msgid "%{base_type}[] arguments must be types. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:457
msgid "%{base_type_label}[] accepts %{min} or more arguments. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:459
msgid "%{base_type_label}[] accepts %{min} to %{max} arguments. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:461
msgid "%{base_type_label}[] accepts %{min} %{label}. Got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:461
msgid "argument"
msgstr ""
#: ../lib/puppet/pops/issues.rb:466
msgid "Error creating type specialization of %{base_type}, %{message}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:470
msgid "Cannot specialize an already specialized %{kind} type"
msgstr ""
#: ../lib/puppet/pops/issues.rb:474
msgid "First argument to Resource[] must be a resource type or a String. Got %{actual}."
msgstr ""
#: ../lib/puppet/pops/issues.rb:478
msgid "Arguments to Resource[] are all empty/undefined"
msgstr ""
#: ../lib/puppet/pops/issues.rb:482
msgid "Illegal Class name in class reference. %{expression} cannot be used where a String is expected"
msgstr ""
#: ../lib/puppet/pops/issues.rb:486
msgid "Unacceptable name. The name '%{name}' is unacceptable as the name of %{value}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:490
msgid "Unacceptable location. The name '%{name}' is unacceptable in file '%{file}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:495
msgid "The %{value} '%{name}' is unacceptable as a top level construct in this location"
msgstr ""
#: ../lib/puppet/pops/issues.rb:497
msgid "This %{value} is unacceptable as a top level construct in this location"
msgstr ""
#: ../lib/puppet/pops/issues.rb:502
msgid "Parameter $%{param} is not last, and has 'captures rest'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:506
msgid "Parameter $%{param} has 'captures rest' - not supported in %{container}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:510
msgid "Parameter $%{param} is required but appears after optional parameters"
msgstr ""
#: ../lib/puppet/pops/issues.rb:514
msgid "Parameter $%{param} is required but no value was given"
msgstr ""
#: ../lib/puppet/pops/issues.rb:518
msgid "The value '%{value}' cannot be converted to Numeric."
msgstr ""
#: ../lib/puppet/pops/issues.rb:522
msgid "The string '%{before}' was automatically coerced to the numerical value %{after}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:526
msgid "Unknown function: '%{name}'."
msgstr ""
#: ../lib/puppet/pops/issues.rb:530
msgid "Unknown variable: '%{name}'."
msgstr ""
#: ../lib/puppet/pops/issues.rb:534
msgid "Error while evaluating %{expression}, %{detail}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:538
msgid "Resource type not found: %{res_type}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:542
msgid "Illegal Resource Type expression, expected result to be a type name, or untitled Resource, got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:546
msgid "The title '%{title}' has already been used in this resource expression"
msgstr ""
#: ../lib/puppet/pops/issues.rb:550
msgid "The attribute '%{attribute}' has already been set"
msgstr ""
#: ../lib/puppet/pops/issues.rb:554
msgid "Missing title. The title expression resulted in undef"
msgstr ""
#: ../lib/puppet/pops/issues.rb:558
msgid "Missing title at index %{index}. The title expression resulted in an undef title"
msgstr ""
#: ../lib/puppet/pops/issues.rb:562
msgid "Illegal title type at index %{index}. Expected String, got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:566
msgid "Empty string title at %{index}. Title strings must have a length greater than zero."
msgstr ""
#: ../lib/puppet/pops/issues.rb:570
msgid "Resource not found: %{type_name}['%{title}']"
msgstr ""
#: ../lib/puppet/pops/issues.rb:574
msgid "The resource %{type_name}['%{title}'] does not have a parameter called '%{param}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:578
msgid "Division by 0"
msgstr ""
#: ../lib/puppet/pops/issues.rb:582
msgid "The result of the %{operator} expression is Infinity"
msgstr ""
#: ../lib/puppet/pops/issues.rb:587
msgid "Heredoc syntax specification has empty segment between '+' : '%{syntax}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:591
msgid "Ambiguous EPP parameter expression. Probably missing '<%-' before parameters to remove leading whitespace"
msgstr ""
#. TRANSLATORS "import" is a function name and should not be translated
#: ../lib/puppet/pops/issues.rb:596
msgid "Use of 'import' has been discontinued in favor of a manifest directory. See http://links.puppet.com/puppet-import-deprecation"
msgstr ""
#: ../lib/puppet/pops/issues.rb:600
msgid "This %{expression} has no effect. A value was produced and then forgotten (one or more preceding expressions may have the wrong form)"
msgstr ""
#: ../lib/puppet/pops/issues.rb:604
msgid "This expression is invalid. Did you try declaring a '%{name}' resource without a title?"
msgstr ""
#: ../lib/puppet/pops/issues.rb:608
msgid "This %{expression} has no effect. %{container} can not end with a value-producing expression without other effect"
msgstr ""
#: ../lib/puppet/pops/issues.rb:612
msgid "Use of reserved word: %{word}, must be quoted if intended to be a String value"
msgstr ""
#: ../lib/puppet/pops/issues.rb:616
msgid "Use of future reserved word: '%{word}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:620
msgid "The name: '%{name}' is already defined by Puppet and can not be used as the name of %{expression}."
msgstr ""
#: ../lib/puppet/pops/issues.rb:624
msgid "No matching entry for selector parameter with value '%{param}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:628
msgid "Node inheritance is not supported in Puppet >= 4.0.0. See http://links.puppet.com/puppet-node-inheritance-deprecation"
msgstr ""
#: ../lib/puppet/pops/issues.rb:632
msgid "Resource Override can only operate on resources, got: %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:636
msgid "The parameter '%{param}' is declared more than once in the parameter list"
msgstr ""
#: ../lib/puppet/pops/issues.rb:640
msgid "The key '%{key}' is declared more than once"
msgstr ""
#: ../lib/puppet/pops/issues.rb:644
msgid "This %{container} already has a 'default' entry - this is a duplicate"
msgstr ""
#: ../lib/puppet/pops/issues.rb:648
msgid "The parameter $%{param} redefines a built in parameter in %{container}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:652
msgid "Expected value of type %{expected}, got %{actual}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:656
msgid "Unfolding of attributes from Hash can only be used once per resource body"
msgstr ""
#: ../lib/puppet/pops/issues.rb:660
msgid "This %{expression} appears in a context where catalog related expressions are not allowed"
msgstr ""
#: ../lib/puppet/pops/issues.rb:664
msgid "Syntax error at %{location}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:668
msgid "Illegal class reference"
msgstr ""
#: ../lib/puppet/pops/issues.rb:672
msgid "Illegal fully qualified class reference"
msgstr ""
#: ../lib/puppet/pops/issues.rb:676
msgid "Illegal fully qualified name"
msgstr ""
#: ../lib/puppet/pops/issues.rb:680
msgid "Illegal name or bare word"
msgstr ""
#: ../lib/puppet/pops/issues.rb:684
msgid "Illegal number '%{value}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:688
msgid "Unicode escape '\\u' was not followed by 4 hex digits or 1-6 hex digits in {} or was > 10ffff"
msgstr ""
#: ../lib/puppet/pops/issues.rb:692
msgid "Not a valid hex number %{value}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:696
msgid "Not a valid octal number %{value}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:700
msgid "Not a valid decimal number %{value}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:704
msgid "Internal Error: No string or file given to lexer to process."
msgstr ""
#: ../lib/puppet/pops/issues.rb:708
msgid "Unrecognized escape sequence '\\%{ch}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:712
msgid "Unclosed quote after %{after} followed by '%{followed_by}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:716
msgid "Unclosed multiline comment"
msgstr ""
#: ../lib/puppet/pops/issues.rb:720
msgid "Internal error: %{error}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:724
msgid "Unbalanced epp tag, reached without closing tag."
msgstr ""
#: ../lib/puppet/pops/issues.rb:728
msgid "Reaching end after opening <%# without seeing %>"
msgstr ""
#: ../lib/puppet/pops/issues.rb:732
msgid "Unbalanced embedded expression - opening <% and reaching end of input"
msgstr ""
#: ../lib/puppet/pops/issues.rb:736
msgid "Unclosed parenthesis after '@(' followed by '%{followed_by}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:740
msgid "Heredoc without end-tagged line"
msgstr ""
#: ../lib/puppet/pops/issues.rb:744
msgid "Invalid heredoc escape char. Only t, r, n, s, u, L, $ allowed. Got '%{actual}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:748
msgid "Invalid syntax in heredoc expected @(endtag[:syntax][/escapes])"
msgstr ""
#: ../lib/puppet/pops/issues.rb:752
msgid "Heredoc without any following lines of text"
msgstr ""
#: ../lib/puppet/pops/issues.rb:756
msgid "Heredoc with an empty endtag"
msgstr ""
#: ../lib/puppet/pops/issues.rb:760
msgid "An escape char for @() may only appear once. Got '%{escapes}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:764
msgid "Heredoc with text in the margin is not allowed (line %{heredoc_line} in this heredoc)"
msgstr ""
#: ../lib/puppet/pops/issues.rb:768
msgid "Illegal %{format} Byte Order mark at beginning of input: %{bom} - remove these from the puppet source"
msgstr ""
#: ../lib/puppet/pops/issues.rb:772
msgid "No such file or directory: %{file}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:776
msgid "%{file} is not a file"
msgstr ""
#: ../lib/puppet/pops/issues.rb:781
msgid "%{expression} resulted in a value outside of Puppet Integer max range, got '%{value}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:783
msgid "%{expression} resulted in a value outside of Puppet Integer min range, got '%{value}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:788
msgid "This runtime does not support hiera.yaml version %{version}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:792
msgid "hiera.yaml version 3 cannot be used in %{location}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:796
msgid "hiera.yaml version 4 cannot be used in the global layer"
msgstr ""
#: ../lib/puppet/pops/issues.rb:800
msgid "Undefined variable '%{name}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:804
msgid "Backend '%{name}' is defined more than once."
msgstr ""
#: ../lib/puppet/pops/issues.rb:807 ../lib/puppet/pops/issues.rb:820
msgid "First defined at %{error_location}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:813
msgid "No data provider is registered for backend '%{name}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:817
msgid "Hierarchy name '%{name}' defined more than once."
msgstr ""
#: ../lib/puppet/pops/issues.rb:826
msgid "'hiera3_backend' is only allowed in the global layer"
msgstr ""
#: ../lib/puppet/pops/issues.rb:830
msgid "'default_hierarchy' is only allowed in the module layer"
msgstr ""
#: ../lib/puppet/pops/issues.rb:834
msgid "Use \"data_hash: %{function_name}_data\" instead of \"hiera3_backend: %{function_name}\""
msgstr ""
#: ../lib/puppet/pops/issues.rb:838
msgid "One of %{keys} must be defined in hierarchy '%{name}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:842 ../lib/puppet/pops/issues.rb:850
msgid "Only one of %{keys} can be defined in hierarchy '%{name}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:846
msgid "Only one of %{keys} can be defined in defaults"
msgstr ""
#: ../lib/puppet/pops/issues.rb:854
msgid "Option key '%{key}' used in hierarchy '%{name}' is reserved by Puppet"
msgstr ""
#: ../lib/puppet/pops/issues.rb:858
msgid "Option key '%{key}' used in defaults is reserved by Puppet"
msgstr ""
#: ../lib/puppet/pops/issues.rb:862
msgid "Unable to find '%{function_type}' function named '%{function_name}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:866
msgid "'alias' interpolation is only permitted if the expression is equal to the entire string"
msgstr ""
#: ../lib/puppet/pops/issues.rb:870
msgid "Unknown interpolation method '%{name}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:874
msgid "Interpolation using method syntax is not allowed in this context"
msgstr ""
#: ../lib/puppet/pops/issues.rb:878
msgid "Endless recursion detected when attempting to serialize value of class %{type_name}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:882
msgid "%{path} contains the special value default. It will be converted to the String 'default'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:886
msgid "%{path} contains %{klass} value. It will be converted to the String '%{value}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:890
msgid "%{path} contains a hash with %{klass} key. It will be converted to the String '%{value}'"
msgstr ""
#: ../lib/puppet/pops/issues.rb:894
msgid "The feature '%{feature}' is only available when compiling a catalog"
msgstr ""
#: ../lib/puppet/pops/issues.rb:898
msgid "The catalog operation '%{operation}' is only available when compiling a catalog"
msgstr ""
#: ../lib/puppet/pops/issues.rb:902
msgid "%{expr} is only available when compiling a catalog"
msgstr ""
#: ../lib/puppet/pops/issues.rb:906
msgid "The task operation '%{operation}' is not available when compiling a catalog"
msgstr ""
#: ../lib/puppet/pops/issues.rb:910
msgid "%{expr} is not available when compiling a catalog"
msgstr ""
#: ../lib/puppet/pops/issues.rb:914
msgid "The 'bolt' library is required to %{action}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:918
msgid "Task not found: %{type_name}"
msgstr ""
#: ../lib/puppet/pops/issues.rb:922
msgid "Failed to load: %{type_name}"
msgstr ""
#: ../lib/puppet/pops/label_provider.rb:77
msgid "<%{string}> does not appear to contain a word"
msgstr ""
#: ../lib/puppet/pops/loader/base_loader.rb:135
msgid "Originally set %{original}."
msgstr ""
#: ../lib/puppet/pops/loader/base_loader.rb:135
msgid "Set at unknown location"
msgstr ""
#: ../lib/puppet/pops/loader/base_loader.rb:136
msgid "Attempt to redefine entity '%{name}'. %{origin_info}"
msgstr ""
#: ../lib/puppet/pops/loader/gem_support.rb:32
msgid "Gem not found %{uri}"
msgstr ""
#: ../lib/puppet/pops/loader/gem_support.rb:48
msgid "Gem not found '%{gem_name}'"
msgstr ""
#: ../lib/puppet/pops/loader/generic_plan_instantiator.rb:11
msgid "Found multiple files for plan '%{plan_name}' but only one is allowed"
msgstr ""
#: ../lib/puppet/pops/loader/generic_plan_instantiator.rb:21
msgid "No instantiator is available to load plan from %{source_ref}"
msgstr ""
#. TRANSLATORS 'loadables' is a variable containing loadable modules and should not be translated
#: ../lib/puppet/pops/loader/module_loaders.rb:140
msgid "given loadables are not of supported loadable kind"
msgstr ""
#. TRANSLATORS 'TypeSet' should not be translated
#: ../lib/puppet/pops/loader/module_loaders.rb:245
msgid "The code loaded from %{origin} does not define the TypeSet '%{module_name}'"
msgstr ""
#: ../lib/puppet/pops/loader/puppet_function_instantiator.rb:26
msgid "The code loaded from %{source_ref} does not define the function '%{func_name}' - it is empty."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_function_instantiator.rb:30
msgid "The code loaded from %{source_ref} must contain only the function '%{type_name}' - it has additional definitions."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_function_instantiator.rb:35
msgid "The code loaded from %{source_ref} does not define the function '%{type_name}' - no function found."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_function_instantiator.rb:40
msgid "The code loaded from %{source_ref} produced function with the wrong name, expected %{expected}, actual %{actual}"
msgstr ""
#: ../lib/puppet/pops/loader/puppet_function_instantiator.rb:43
msgid "The code loaded from %{source} contains additional logic - can only contain the function %{name}"
msgstr ""
#: ../lib/puppet/pops/loader/puppet_plan_instantiator.rb:35
msgid "The code loaded from %{source_ref} does not define the plan '%{plan_name}' - it is empty."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_plan_instantiator.rb:39
msgid "The code loaded from %{source_ref} must contain only the plan '%{plan_name}' - it has additional definitions."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_plan_instantiator.rb:44
msgid "The code loaded from %{source_ref} does not define the plan '%{plan_name}' - no plan found."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_plan_instantiator.rb:49
msgid "The code loaded from %{source_ref} produced plan with the wrong name, expected %{expected}, actual %{actual}"
msgstr ""
#: ../lib/puppet/pops/loader/puppet_plan_instantiator.rb:52
msgid "The code loaded from %{source} contains additional logic - can only contain the plan %{plan_name}"
msgstr ""
#: ../lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb:34
msgid "The code loaded from %{source_ref} does not create the resource type '%{type_name}' - it is empty"
msgstr ""
#: ../lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb:50
msgid "The code loaded from %{source_ref} does not create the resource type '%{type_name}' - no call to %{rname}.new found."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb:54
msgid "The code loaded from %{source_ref} must contain only the creation of resource type '%{type_name}' - it has additional logic."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb:62
msgid "The code loaded from %{source_ref} does not define the resource type '%{type_name}' - got '%{got}'."
msgstr ""
#: ../lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb:68
msgid "The code loaded from %{source_ref} produced resource type with the wrong name, expected '%{expected}', actual '%{actual}'"
msgstr ""
#: ../lib/puppet/pops/loader/ruby_data_type_instantiator.rb:18
msgid "The code loaded from %{source_ref} does not seem to be a Puppet 5x API data type - no create_type call."
msgstr ""
#: ../lib/puppet/pops/loader/ruby_data_type_instantiator.rb:25
msgid "The code loaded from %{source_ref} did not produce a data type when evaluated. Got '%{klass}'"
msgstr ""
#: ../lib/puppet/pops/loader/ruby_data_type_instantiator.rb:28 ../lib/puppet/pops/loader/ruby_function_instantiator.rb:28
msgid "The code loaded from %{source_ref} produced mis-matched name, expected '%{type_name}', got %{created_name}"
msgstr ""
#: ../lib/puppet/pops/loader/ruby_function_instantiator.rb:18
msgid "The code loaded from %{source_ref} does not seem to be a Puppet 4x API function - no create_function call."
msgstr ""
#: ../lib/puppet/pops/loader/ruby_function_instantiator.rb:25
msgid "The code loaded from %{source_ref} did not produce a Function class when evaluated. Got '%{klass}'"
msgstr ""
#: ../lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb:24
msgid "The code loaded from %{source_ref} does not seem to be a Puppet 3x API function - no 'newfunction' call."
msgstr ""
#. TRANSLATORS - the word 'newfunction' should not be translated as it is a method name.
#: ../lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb:46
msgid "Illegal legacy function definition! The code loaded from %{source_ref} did not return the result of calling 'newfunction'. Got '%{klass}'"
msgstr ""
#: ../lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb:49
msgid "The code loaded from %{source_ref} produced mis-matched name, expected 'function_%{type_name}', got '%{created_name}'"
msgstr ""
#: ../lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb:93
msgid "Illegal method definition of method '%{method_name}' in source %{source_ref} on line %{line} in legacy function. See %{url} for more information"
msgstr ""
#: ../lib/puppet/pops/loader/task_instantiator.rb:23
msgid "Failed to load metadata for task %{name}: 'parameters' must be a hash"
msgstr ""
#: ../lib/puppet/pops/loader/task_instantiator.rb:32
msgid "Failed to load metadata for task %{name}: %{reason}"
msgstr ""
#: ../lib/puppet/pops/loader/type_definition_instantiator.rb:16
msgid "The code loaded from %{source_ref} does not define the type '%{name}' - it is empty."
msgstr ""
#: ../lib/puppet/pops/loader/type_definition_instantiator.rb:21
msgid "The code loaded from %{source_ref} must contain only the type '%{name}' - it has additional definitions."
msgstr ""
#: ../lib/puppet/pops/loader/type_definition_instantiator.rb:27
msgid "The code loaded from %{source_ref} does not define the type '%{name}' - no type alias or type definition found."
msgstr ""
#: ../lib/puppet/pops/loader/type_definition_instantiator.rb:33
msgid "The code loaded from %{source_ref} produced type with the wrong name, expected '%{name}', actual '%{actual_name}'"
msgstr ""
#: ../lib/puppet/pops/loader/type_definition_instantiator.rb:38
msgid "The code loaded from %{source_ref} contains additional logic - can only contain the type '%{name}'"
msgstr ""
#: ../lib/puppet/pops/loaders.rb:39
msgid "Attempt to redefine already initialized loaders for environment"
msgstr ""
#: ../lib/puppet/pops/loaders.rb:182
msgid "Internal Error: Puppet Context ':loaders' missing"
msgstr ""
#: ../lib/puppet/pops/loaders.rb:196
msgid "Unable to find loader named '%{loader_name}'"
msgstr ""
#: ../lib/puppet/pops/loaders.rb:217
msgid "Internal Error: did not find public loader for module: '%{module_name}'"
msgstr ""
#: ../lib/puppet/pops/loaders.rb:263
msgid "Internal Error: Attempt to redefine loader named '%{name}'"
msgstr ""
#: ../lib/puppet/pops/lookup.rb:93
msgid "Function lookup() did not find a value for the name '%{name}'"
msgid_plural "Function lookup() did not find a value for any of the names [%{name_list}]"
msgstr[0] ""
msgstr[1] ""
#: ../lib/puppet/pops/lookup/environment_data_provider.rb:21
msgid "hiera.yaml version 3 found at the environment root was ignored"
msgstr ""
#. TRANSLATORS 'Explain' is referring to the 'Explainer' class and should not be translated
#: ../lib/puppet/pops/lookup/explainer.rb:496
msgid "Unknown Explain type %{qualifier_type}"
msgstr ""
#: ../lib/puppet/pops/lookup/hiera_config.rb:87
msgid "Using of legacy data provider function '%{function_name}'. Please convert to a 'data_hash' function"
msgstr ""
#: ../lib/puppet/pops/lookup/hiera_config.rb:144
msgid "%{config_path}: File exists but does not contain a valid YAML hash. Falling back to Hiera version 3 default config"
msgstr ""
#: ../lib/puppet/pops/lookup/hiera_config.rb:202
msgid "Hiera configuration recreated due to change of scope variables used in interpolation expressions"
msgstr ""
#: ../lib/puppet/pops/lookup/hiera_config.rb:431
msgid "%{config_path}: Use of 'hiera.yaml' version 3 is deprecated. It should be converted to version 5"
msgstr ""
#: ../lib/puppet/pops/lookup/hiera_config.rb:531
msgid "%{config_path}: Use of 'hiera.yaml' version 4 is deprecated. It should be converted to version 5"
msgstr ""
#: ../lib/puppet/pops/lookup/invocation.rb:92
msgid "Recursive lookup detected in [%{name_stack}]"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:109
msgid "Invalid data type in lookup_options for key '%{key}' could not parse '%{source}', error: '%{msg}"
msgstr ""
#. TRANSLATORS 'lookup_options', 'convert_to' and args_string variable should not be translated,
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:117
msgid "Applying convert_to lookup_option with arguments %{args}"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:120
msgid "The convert_to lookup_option for key '%{key}' raised error: %{msg}"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:150
msgid "Lookup of key '%{key}' failed: %{detail}"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:297
msgid "value of %{opts} must be a hash"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:304
msgid "all %{opts} patterns must match a key starting with module name '%{module_name}'"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:308
msgid "all %{opts} keys must start with module name '%{module_name}'"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:433
msgid "Defining \"data_provider\": \"%{name}\" in metadata.json is deprecated. It is ignored since a '%{config}' with version >= 5 is present"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:443
msgid "Defining \"data_provider\": \"%{name}\" in metadata.json is deprecated."
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:444 ../lib/puppet/pops/lookup/lookup_adapter.rb:498
msgid "A '%{hiera_config}' file should be used instead"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:458
msgid "Environment '%{env}', cannot find module_data_provider '%{provider}'"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:482
msgid "Defining environment_data_provider='%{provider_name}' in environment.conf is deprecated"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:486
msgid "The environment_data_provider='%{provider_name}' setting is ignored since '%{config_path}' version >= 5"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:497
msgid "Defining environment_data_provider='%{provider_name}' in environment.conf is deprecated."
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_adapter.rb:513
msgid "Environment '%{env}', cannot find environment_data_provider '%{provider}'"
msgstr ""
#: ../lib/puppet/pops/lookup/lookup_key.rb:13
msgid "%{problem} in key: '%{key}'"
msgstr ""
#: ../lib/puppet/pops/lookup/module_data_provider.rb:70
msgid "hiera.yaml version 3 found at module root was ignored"
msgstr ""
#: ../lib/puppet/pops/lookup/module_data_provider.rb:85
msgid "Environment '%{env}', cannot find module '%{module_name}'"
msgstr ""
#: ../lib/puppet/pops/lookup/sub_lookup.rb:76
msgid "Data Provider type mismatch: Got %{klass} when a hash-like object was expected to access value using '%{segment}' from key '%{key}'"
msgstr ""
#. TRANSLATORS 'merge' is a variable name and 'strategy' is a key and should not be translated
#: ../lib/puppet/pops/merge_strategy.rb:29
msgid "The hash given as 'merge' must contain the name of a strategy in string form for the key 'strategy'"
msgstr ""
#: ../lib/puppet/pops/merge_strategy.rb:38
msgid "Unknown merge strategy: '%{strategy}'"
msgstr ""
#. TRANSLATORS 'MergeStrategies.add_strategy' is a method, 'stratgey_class' is a variable and 'MergeStrategy' is a class name and should not be translated
#: ../lib/puppet/pops/merge_strategy.rb:57
msgid "MergeStrategies.add_strategy 'strategy_class' must be a 'MergeStrategy' class. Got %{strategy_class}"
msgstr ""
#: ../lib/puppet/pops/migration/migration_checker.rb:22 ../lib/puppet/pops/migration/migration_checker.rb:27 ../lib/puppet/pops/migration/migration_checker.rb:32 ../lib/puppet/pops/migration/migration_checker.rb:37 ../lib/puppet/pops/migration/migration_checker.rb:42 ../lib/puppet/pops/migration/migration_checker.rb:47 ../lib/puppet/pops/migration/migration_checker.rb:52 ../lib/puppet/pops/migration/migration_checker.rb:57
msgid "Unsupported migration method called"
msgstr ""
#: ../lib/puppet/pops/model/ast_transformer.rb:67
msgid "Error while transforming to Puppet 3 AST: %{message}"
msgstr ""
#: ../lib/puppet/pops/model/ast_transformer.rb:86
msgid "Not a valid expression in a collection query: %{class_name}"
msgstr ""
#: ../lib/puppet/pops/model/ast_transformer.rb:115
msgid "Illegal expression - unacceptable as a node name"
msgstr ""
#: ../lib/puppet/pops/model/ast_transformer.rb:119
msgid "Unacceptable transform - found an Object without a rule: %{klass}"
msgstr ""
#. TRANSLATORS 'NUMBER' refers to a method name and the 'name_or_numeric' was the passed in value and should not be translated
#: ../lib/puppet/pops/model/factory.rb:812
msgid "Internal Error, NUMBER token does not contain a valid number, %{name_or_numeric}"
msgstr ""
#: ../lib/puppet/pops/model/factory.rb:1121
msgid "can only concatenate strings, got %{class_name}"
msgstr ""
#: ../lib/puppet/pops/parser/parser_support.rb:200
msgid "attempt to pass argument list to the function '%{name}' which cannot be called without parentheses"
msgstr ""
#: ../lib/puppet/pops/parser/parser_support.rb:202
msgid "illegal comma separated argument list"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:82
msgid "unexpected end of input"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:84
msgid "unexpected %{value}"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:121
msgid "map key expected"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:132
msgid "expected identifier to follow '('"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:143
msgid "missing '%{token}' to end list"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:188
msgid "expected identifier after ':'"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:227
msgid "unterminated quote"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:253
msgid "malformed octal quote"
msgstr ""
#: ../lib/puppet/pops/parser/pn_parser.rb:268 ../lib/puppet/pops/parser/pn_parser.rb:273 ../lib/puppet/pops/parser/pn_parser.rb:277
msgid "digit expected"
msgstr ""
#: ../lib/puppet/pops/resource/resource_type_impl.rb:166 ../lib/puppet/type.rb:432
msgid "you must specify title patterns when there are two or more key attributes"
msgstr ""
#: ../lib/puppet/pops/serialization/abstract_writer.rb:60
msgid "Integer out of bounds"
msgstr ""
#. TRANSLATORS 'Integers' is a Ruby class for numbers and should not be translated
#: ../lib/puppet/pops/serialization/abstract_writer.rb:104
msgid "Internal error. Integers cannot be tabulated in extension payload"
msgstr ""
#: ../lib/puppet/pops/serialization/deserializer.rb:47 ../lib/puppet/pops/serialization/from_data_converter.rb:135
msgid "No implementation mapping found for Puppet Type %{type_name}"
msgstr ""
#: ../lib/puppet/pops/serialization/from_data_converter.rb:126
msgid "Unable to deserialize type from %{type}"
msgstr ""
#: ../lib/puppet/pops/serialization/from_data_converter.rb:219
msgid "Cannot create a %{type_name} from a %{arg_class}"
msgstr ""
#: ../lib/puppet/pops/serialization/json.rb:205
msgid "Unable to serialize a %{obj}"
msgstr ""
#: ../lib/puppet/pops/serialization/json.rb:252
msgid "JSON stream is not an array. It is a %{klass}"
msgstr ""
#: ../lib/puppet/pops/serialization/json.rb:259
msgid "Unexpected end of input"
msgstr ""
#: ../lib/puppet/pops/serialization/json.rb:273
msgid "Invalid input. %{ext_no} is not a valid extension number"
msgstr ""
#: ../lib/puppet/pops/serialization/json_path.rb:122
msgid "Unable to parse jsonpath \"%{path}\""
msgstr ""
#: ../lib/puppet/pops/serialization/object.rb:17
msgid "Feature count mismatch for %{value0}. Expected %{required_count} - %{max}, actual %{value_count}"
msgstr ""
#: ../lib/puppet/pops/serialization/object.rb:28
msgid "Missing default value for %{type_name}[%{name}]"
msgstr ""
#: ../lib/puppet/pops/serialization/serializer.rb:137
msgid "No Puppet Type found for %{klass}"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:115 ../lib/puppet/pops/time/timestamp.rb:84
msgid "Unable to parse '%{str}' using any of the formats %{formats}"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:136
msgid "%{klass} cannot be added to a Timespan"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:148
msgid "%{klass} cannot be subtracted from a Timespan"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:161
msgid "A Timestamp cannot be multiplied by %{klass}"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:172
msgid "Can not do modulus on a Timespan using a %{klass}"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:192
msgid "A Timespan cannot be divided by %{klass}"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:479
msgid "Format specifiers %L and %N denotes fractions and must be used together with a specifier of higher magnitude"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:555 ../lib/puppet/pops/time/timespan.rb:561
msgid "Unable to parse '%{timespan}' using format '%{format}'"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:611
msgid "Bad format specifier '%{expression}' in '%{format}', at position %{position}"
msgstr ""
#: ../lib/puppet/pops/time/timespan.rb:629
msgid "Format must be a String"
msgstr ""
#: ../lib/puppet/pops/time/timestamp.rb:41
msgid "Illegal timezone '%{timezone}'"
msgstr ""
#: ../lib/puppet/pops/time/timestamp.rb:90
msgid "Unable to parse '%{str}' using format '%{format}'"
msgstr ""
#: ../lib/puppet/pops/time/timestamp.rb:93
msgid "Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument"
msgstr ""
#: ../lib/puppet/pops/time/timestamp.rb:129
msgid "%{klass} cannot be added to a Timestamp"
msgstr ""
#: ../lib/puppet/pops/time/timestamp.rb:144
msgid "%{klass} cannot be subtracted from a Timestamp"
msgstr ""
#: ../lib/puppet/pops/types/p_binary_type.rb:78
msgid "The given string in encoding '%{enc}' is invalid. Cannot create a Binary UTF-8 representation"
msgstr ""
#: ../lib/puppet/pops/types/p_init_type.rb:27
msgid "Init cannot be parameterized with an undefined type and additional arguments"
msgstr ""
#: ../lib/puppet/pops/types/p_init_type.rb:158
msgid "Creation of new instance of type '%{type_name}' is not supported"
msgstr ""
#: ../lib/puppet/pops/types/p_init_type.rb:185
msgid "The type '%{type}' does not represent a valid set of parameters for %{subject}.new()"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:148
msgid "expected %{label} to override an inherited %{feature_type}, but no such %{feature_type} was found"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:165
msgid "%{member} attempts to override %{label}"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:168
msgid "%{member} attempts to override final %{label}"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:172
msgid "%{member} attempts to override %{label} without having override => true"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:175
msgid "%{member} attempts to override %{label} with a type that does not match"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:289
msgid "The attribute '%{name}' is reserved and cannot be used"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:295
msgid "%{label} of kind 'constant' cannot be combined with final => false"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:302
msgid "%{label} of kind '%{kind}' cannot be combined with an attribute value"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:307
msgid "%{label} of kind 'constant' requires a value"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:688
msgid "reference to unresolved type '%{name}'"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:724
msgid "attribute %{label}[%{key}] is defined as both a constant and an attribute"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:756
msgid "%{label} conflicts with attribute with the same name"
msgstr ""
#. TRANSLATORS equality_include_type = false should not be translated
#: ../lib/puppet/pops/types/p_object_type.rb:769
msgid "equality_include_type = false cannot be combined with non empty equality specification"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:781
msgid "%{label} equality is referencing %{attribute} which is included in equality of %{including_parent}"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:788
msgid "%{label} equality is referencing non existent attribute '%{attribute}'"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:790
msgid "%{label} equality is referencing %{attribute}. Only attribute references are allowed"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:794
msgid "%{label} equality is referencing constant %{attribute}."
msgstr ""
#: ../lib/puppet/pops/types/p_object_type.rb:795
msgid "Reference to constant is not allowed in equality"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type_extension.rb:56
msgid "The %{label}-Type cannot be parameterized using []"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type_extension.rb:71
msgid "'%{pn}' is not a known type parameter for %{label}-Type"
msgstr ""
#: ../lib/puppet/pops/types/p_object_type_extension.rb:84
msgid "The %{label}-Type cannot be parameterized using an empty parameter list"
msgstr ""
#: ../lib/puppet/pops/types/p_sem_ver_type.rb:107
msgid "The string '%{str}' cannot be converted to a SemVer"
msgstr ""
#: ../lib/puppet/pops/types/tree_iterators.rb:39
msgid "Only Array, Hash, and Object types can be used as container types. Got %{type}"
msgstr ""
#: ../lib/puppet/pops/types/tree_iterators.rb:46
msgid "Options 'include_containers' and 'include_values' cannot both be false"
msgstr ""
#. TRANSLATORS 'TypeFactory#string' is a class and method name and should not be translated
#: ../lib/puppet/pops/types/type_factory.rb:118
msgid "Passing more than one argument to TypeFactory#string is deprecated"
msgstr ""
#. TRANSLATORS TypeMismatchDescriber is a class name and 'tense' is a method name and should not be translated
#: ../lib/puppet/pops/types/type_mismatch_describer.rb:513
msgid "Passing a 'tense' argument to the TypeMismatchDescriber is deprecated and ignored."
msgstr ""
#: ../lib/puppet/pops/types/type_mismatch_describer.rb:514
msgid "Everything is now reported using present tense"
msgstr ""
#: ../lib/puppet/pops/types/type_mismatch_describer.rb:613
msgid "Deferred function %{function_name} has no return_type, unable to guarantee value type during compilation."
msgstr ""
#: ../lib/puppet/pops/types/type_parser.rb:426
msgid "Enum parameters must be identifiers or strings"
msgstr ""
#: ../lib/puppet/pops/types/type_parser.rb:662
msgid "The expression <%{expression}> is not a valid type specification."
msgstr ""
#: ../lib/puppet/pops/types/type_parser.rb:667
msgid "Invalid number of type parameters specified: %{type} requires %{required}, %{given} provided"
msgstr ""
#: ../lib/puppet/pops/types/type_parser.rb:672
msgid "Not a parameterized type <%{type}>"
msgstr ""
#: ../lib/puppet/pops/types/type_parser.rb:676
msgid "Unknown type <%{type}>"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:930
msgid "The string '%{str}' cannot be converted to Numeric"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:933
msgid "Value of type %{type} cannot be converted to Numeric"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1171
msgid "The string '%{str}' cannot be converted to Integer"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1174
msgid "Value of type %{type} cannot be converted to Integer"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1183
msgid "Illegal radix: %{radix}, expected 2, 8, 10, 16, or default"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1296
msgid "The string '%{str}' cannot be converted to Float"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1299
msgid "Value of type %{type} cannot be converted to Float"
msgstr ""
#. TRANSLATORS 'PStringType#initialize' is a class and method name and should not be translated
#: ../lib/puppet/pops/types/types.rb:1516
msgid "Passing more than one argument to PStringType#initialize is deprecated"
msgstr ""
#. TRANSLATORS 'PStringType#values' and '#value' are classes and method names and should not be translated
#: ../lib/puppet/pops/types/types.rb:1570
msgid "Method PStringType#values is deprecated. Use #value instead"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1894
msgid "The string '%{str}' cannot be converted to Boolean"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:1897
msgid "Value of type %{type} cannot be converted to Boolean"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:2625
msgid "Value of type %{type} cannot be converted to Array"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:2695
msgid "Puppet::Pops::Types::PHashType#element_type is deprecated, use #value_type instead"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:2832
msgid "odd number of arguments for Hash"
msgstr ""
#: ../lib/puppet/pops/types/types.rb:2843
msgid "Value of type %{type} cannot be converted to Hash"
msgstr ""
#: ../lib/puppet/pops/validation.rb:130
msgid "Attempt to set validation severity for something that is not an Issue. (Got %{issue})"
msgstr ""
#: ../lib/puppet/pops/validation.rb:133
msgid "Illegal severity level: %{level} for '%{issue_code}'"
msgstr ""
#: ../lib/puppet/pops/validation.rb:136
msgid "Attempt to demote the hard issue '%{issue_code}' to %{level}"
msgstr ""
#: ../lib/puppet/pops/validation.rb:156
msgid "Attempt to get validation severity for something that is not an Issue. (Got %{issue})"
msgstr ""
#: ../lib/puppet/pops/validation.rb:208
msgid "Issue %{issue_code}: Cannot pass a %{class_name} as a semantic object when it does not support #pos(), #file() and #line()"
msgstr ""
#. TRANSLATORS 'Property#array_matching', 'first', and 'all' should not be translated
#: ../lib/puppet/property.rb:100
msgid "Supported values for Property#array_matching are 'first' and 'all'"
msgstr ""
#: ../lib/puppet/property.rb:170
msgid "Attempt to redefine method %{method} with block"
msgstr ""
#: ../lib/puppet/property.rb:214
msgid "Could not convert change '%{name}' to string: %{detail}"
msgstr ""
#. TRANSLATORS 'insync_values?' should not be translated
#: ../lib/puppet/property.rb:371
msgid "Unknown failure using insync_values? on type: %{type} / property: %{name} to compare values %{should} and %{is}"
msgstr ""
#: ../lib/puppet/property.rb:495
msgid "Could not set '%{value}' on %{class_name}: %{detail}"
msgstr ""
#. TRANSLATORS 'Provider' refers to a Puppet provider class
#: ../lib/puppet/property.rb:597
msgid "Provider %{provider} must have features '%{needed_features}' to set '%{property}' to '%{value}'"
msgstr ""
#: ../lib/puppet/property/ensure.rb:54
msgid "created"
msgstr ""
#: ../lib/puppet/property/ensure.rb:56
msgid "removed"
msgstr ""
#: ../lib/puppet/property/ensure.rb:58
msgid "%{name} changed %{is} to %{should}"
msgstr ""
#: ../lib/puppet/property/ensure.rb:63
msgid "Could not convert change %{name} to string: %{detail}"
msgstr ""
#: ../lib/puppet/property/ensure.rb:87
msgid "No ability to determine if %{name} exists"
msgstr ""
#: ../lib/puppet/property/keyvalue.rb:133
msgid "The %{name} property must be specified as a hash or an array of key/value pairs (strings)!"
msgstr ""
#: ../lib/puppet/property/keyvalue.rb:139
msgid "Key/value pairs must be separated by '%{separator}'"
msgstr ""
#: ../lib/puppet/provider.rb:133
msgid "No command %{command} defined for provider %{provider}"
msgstr ""
#: ../lib/puppet/provider.rb:385
msgid "To support listing resources of this type the '%{provider}' provider needs to implement an 'instances' class method returning the current set of resources. We recommend porting your module to the simpler Resource API instead: https://puppet.com/search/docs?keys=resource+api"
msgstr ""
#: ../lib/puppet/provider.rb:458
msgid "'%{parameter_name}' is not a valid parameter for %{resource_type}"
msgstr ""
#: ../lib/puppet/provider.rb:544
msgid "No resource and no name in property hash in %{class_name} instance"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:125
msgid "Invalid value %{value}: %{property} must be an Integer!"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:334
msgid "Cannot have both 'forcelocal' and 'ia_load_module' at the same time!"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:377
msgid "Could not set %{property} on %{resource}[%{name}]: %{detail}"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:403
msgid "attributes is setting the %{properties} properties via. the %{attributes} attributes, respectively! Please specify these property values in the resource declaration instead."
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:405 ../lib/puppet/provider/aix_object.rb:414
msgid "Could not set attributes on %{resource}[%{name}]: %{detail}"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:426
msgid "aix.object_info(): Could not find %{resource}[%{name}]"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:472 ../lib/puppet/provider/nameservice.rb:165 ../lib/puppet/provider/nameservice/directoryservice.rb:426
msgid "Could not create %{resource} %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/provider/aix_object.rb:484 ../lib/puppet/provider/nameservice.rb:179
msgid "Could not delete %{resource} %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/provider/command.rb:23
msgid "Command %{name} is missing"
msgstr ""
#: ../lib/puppet/provider/exec.rb:20
msgid "Cannot understand environment setting %{setting}"
msgstr ""
#: ../lib/puppet/provider/exec.rb:27
msgid "Overriding environment setting '%{var}' with '%{value}'"
msgstr ""
#: ../lib/puppet/provider/exec.rb:31
msgid "Empty environment setting '%{var}'"
msgstr ""
#: ../lib/puppet/provider/exec.rb:104
msgid "'%{exe}' is not qualified and no path was specified. Please qualify the command or specify a path."
msgstr ""
#: ../lib/puppet/provider/exec/posix.rb:34 ../lib/puppet/provider/exec/posix.rb:51 ../lib/puppet/provider/exec/windows.rb:41 ../lib/puppet/provider/exec/windows.rb:54
msgid "Could not find command '%{exe}'"
msgstr ""
#: ../lib/puppet/provider/exec/posix.rb:36 ../lib/puppet/provider/exec/windows.rb:43
msgid "'%{exe}' is a %{klass}, not a file"
msgstr ""
#: ../lib/puppet/provider/exec/posix.rb:38
msgid "'%{exe}' is not executable"
msgstr ""
#: ../lib/puppet/provider/file/posix.rb:73
msgid "Apparently using negative UID (%{currentvalue}) on a platform that does not consistently handle them"
msgstr ""
#: ../lib/puppet/provider/file/posix.rb:91 ../lib/puppet/provider/file/windows.rb:47
msgid "Failed to set owner to '%{should}': %{detail}"
msgstr ""
#: ../lib/puppet/provider/file/posix.rb:105
msgid "Apparently using negative GID (%{currentvalue}) on a platform that does not consistently handle them"
msgstr ""
#: ../lib/puppet/provider/file/posix.rb:123 ../lib/puppet/provider/file/windows.rb:60
msgid "Failed to set group to '%{should}': %{detail}"
msgstr ""
#: ../lib/puppet/provider/file/posix.rb:140 ../lib/puppet/provider/file/windows.rb:79
msgid "failed to set mode %{mode} on %{path}: %{message}"
msgstr ""
#: ../lib/puppet/provider/file/windows.rb:87
msgid "Can only manage owner, group, and mode on filesystems that support Windows ACLs, such as NTFS"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/provider/file/windows.rb:129
msgid "%{resource_name}: %{mode_part_type} set to SYSTEM. SYSTEM permissions cannot be set below FullControl ('7')"
msgstr ""
#: ../lib/puppet/provider/group/aix.rb:49
msgid "No AIX group exists with a group name or gid of %{group}!"
msgstr ""
#: ../lib/puppet/provider/group/groupadd.rb:15 ../lib/puppet/provider/group/pw.rb:15
msgid "GID must be an integer"
msgstr ""
#: ../lib/puppet/provider/group/groupadd.rb:48
msgid "GID %{resource} already exists, use allowdupe to force group creation"
msgstr ""
#: ../lib/puppet/provider/ldap.rb:81
msgid "No LDAP Configuration defined for %{class_name}"
msgstr ""
#: ../lib/puppet/provider/ldap.rb:82
msgid "Invalid LDAP Configuration defined for %{class_name}"
msgstr ""
#: ../lib/puppet/provider/nameservice.rb:46
msgid "%{name} is not a valid attribute for %{resource_type}"
msgstr ""
#: ../lib/puppet/provider/nameservice.rb:86
msgid "Invalid value %{value}: %{error}"
msgstr ""
#. TRANSLATORS "autogen_id()" is a method name and should not be translated
#: ../lib/puppet/provider/nameservice.rb:131
msgid "autogen_id() does not support auto generation of id for resource type %{resource_type}"
msgstr ""
#: ../lib/puppet/provider/nameservice.rb:153 ../lib/puppet/provider/nameservice/directoryservice.rb:380
msgid "already exists"
msgstr ""
#: ../lib/puppet/provider/nameservice.rb:171
msgid "already absent"
msgstr ""
#: ../lib/puppet/provider/nameservice.rb:265
msgid "Nameservice command must be an array"
msgstr ""
#: ../lib/puppet/provider/nameservice.rb:270 ../lib/puppet/provider/nameservice/directoryservice.rb:341 ../lib/puppet/provider/nameservice/directoryservice.rb:370
msgid "Could not set %{param} on %{resource}[%{name}]: %{detail}"
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:102
msgid "Could not get %{resource} list from DirectoryService"
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:161
msgid "Could not get report. command execution failed."
msgstr ""
#. TRANSLATORS 'OS X 10.7' is an operating system and should not be translated, 'Salted SHA512' is the name of a hashing algorithm
#: ../lib/puppet/provider/nameservice/directoryservice.rb:201
msgid "OS X 10.7 requires a Salted SHA512 hash password of 136 characters."
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:202
msgid "Please check your password and try again."
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:289
msgid "Invalid id_type %{id_type}. Only 'uid' and 'gid' supported"
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:397
msgid "Could not set GeneratedUID for %{resource} %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:446
msgid "Could not remove %{member} from group: %{resource}, %{detail}"
msgstr ""
#: ../lib/puppet/provider/nameservice/directoryservice.rb:460
msgid "Could not add %{new_member} to group: %{name}, %{detail}"
msgstr ""
#. TRANSLATORS "prefetch" is a program name and should not be translated
#: ../lib/puppet/provider/network_device.rb:28
msgid "Could not perform network device prefetch: %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:47
msgid "The aix provider can only be used by root"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:89 ../lib/puppet/provider/package/nim.rb:54
msgid "Failed to uninstall package '%{name}'"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:96
msgid "A directory is required which will be used to find packages"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:108
msgid "aix package provider is unable to downgrade packages"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:113
msgid "Package '%{name}' is in a %{status} state and requires manual intervention"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:134
msgid "Could not list installed Packages: %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/aix.rb:157 ../lib/puppet/provider/package/yum.rb:339
msgid "Tried to get latest on a missing package"
msgstr ""
#: ../lib/puppet/provider/package/appdmg.rb:104 ../lib/puppet/provider/package/pkgdmg.rb:146
msgid "Mac OS X PKG DMGs must specify a package source."
msgstr ""
#: ../lib/puppet/provider/package/appdmg.rb:108 ../lib/puppet/provider/package/pkgdmg.rb:150
msgid "Mac OS X PKG DMGs must specify a package name."
msgstr ""
#: ../lib/puppet/provider/package/apple.rb:43
msgid "Mac OS X packages must specify a package source"
msgstr ""
#: ../lib/puppet/provider/package/apt.rb:90
msgid "/etc/apt/sources.list contains a cdrom source; not installing. Use 'allowcdrom' to override this failure."
msgstr ""
#: ../lib/puppet/provider/package/apt.rb:173 ../lib/puppet/provider/package/aptitude.rb:22 ../lib/puppet/provider/package/ports.rb:21 ../lib/puppet/provider/package/portupgrade.rb:95 ../lib/puppet/provider/package/portupgrade.rb:153 ../lib/puppet/provider/package/rug.rb:29 ../lib/puppet/provider/package/up2date.rb:18 ../lib/puppet/provider/package/yum.rb:318 ../lib/puppet/provider/package/zypper.rb:147
msgid "Could not find package %{name}"
msgstr ""
#: ../lib/puppet/provider/package/apt.rb:177 ../lib/puppet/provider/package/yum.rb:323
msgid "Failed to update to version %{should}, got version %{version} instead"
msgstr ""
#: ../lib/puppet/provider/package/apt.rb:190 ../lib/puppet/provider/package/fink.rb:56
msgid "Could not find latest version"
msgstr ""
#: ../lib/puppet/provider/package/apt.rb:201 ../lib/puppet/provider/package/fink.rb:67
msgid "Preseeding %{response} to debconf-set-selections"
msgstr ""
#: ../lib/puppet/provider/package/apt.rb:205 ../lib/puppet/provider/package/fink.rb:71
msgid "No responsefile specified or non existent, not preseeding anything"
msgstr ""
#: ../lib/puppet/provider/package/aptrpm.rb:54
msgid "Could not match version '%{version}'"
msgstr ""
#: ../lib/puppet/provider/package/aptrpm.rb:69
msgid "Could not match string"
msgstr ""
#: ../lib/puppet/provider/package/blastwave.rb:19
msgid "The pkg-get command is missing; blastwave packaging unavailable"
msgstr ""
#: ../lib/puppet/provider/package/blastwave.rb:23
msgid "It is highly recommended you create '/var/pkg-get/admin'."
msgstr ""
#: ../lib/puppet/provider/package/blastwave.rb:24
msgid "See /var/pkg-get/admin-fullauto"
msgstr ""
#: ../lib/puppet/provider/package/blastwave.rb:81 ../lib/puppet/provider/package/pkgutil.rb:74 ../lib/puppet/provider/package/pkgutil.rb:146
msgid "Cannot match %{line}"
msgstr ""
#: ../lib/puppet/provider/package/dnfmodule.rb:31
msgid "Modules are not supported on DNF versions lower than 3.0.1"
msgstr ""
#: ../lib/puppet/provider/package/dpkg.rb:91
msgid "You cannot install dpkg packages without a source"
msgstr ""
#: ../lib/puppet/provider/package/dpkg.rb:119
msgid "Could not update: You cannot install dpkg packages without a source"
msgstr ""
#: ../lib/puppet/provider/package/dpkg.rb:123
msgid "source doesn't contain named package, but %{name}"
msgstr ""
#: ../lib/puppet/provider/package/freebsd.rb:31
msgid "source is defined but does not have trailing slash, ignoring %{source}"
msgstr ""
#: ../lib/puppet/provider/package/gem.rb:123 ../lib/puppet/provider/package/puppetserver_gem.rb:62
msgid "Could not list gems: %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/gem.rb:149
msgid "Could not match %{desc}"
msgstr ""
#: ../lib/puppet/provider/package/gem.rb:227 ../lib/puppet/provider/package/puppetserver_gem.rb:94
msgid "Invalid source '%{uri}': %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/gem.rb:238 ../lib/puppet/provider/package/puppetserver_gem.rb:105
msgid "puppet:// URLs are not supported as gem sources"
msgstr ""
#: ../lib/puppet/provider/package/gem.rb:254 ../lib/puppet/provider/package/puppetserver_gem.rb:116
msgid "Could not install: %{output}"
msgstr ""
#: ../lib/puppet/provider/package/gem.rb:280 ../lib/puppet/provider/package/puppetserver_gem.rb:126
msgid "Could not uninstall: %{output}"
msgstr ""
#: ../lib/puppet/provider/package/hpux.rb:25
msgid "source must be provided to install HP-UX packages"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:48
msgid "Unrecognized AIX package type identifier: '%{pkg_type}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:61
msgid "An LPP source location is required in 'source'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:104
msgid "Unable to find package '%{package}' with version '%{version}' on lpp_source '%{source}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:107
msgid "Unable to find package '%{package}' on lpp_source '%{source}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:140 ../lib/puppet/provider/package/nim.rb:144
msgid "NIM package provider is unable to downgrade packages"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:218
msgid ""
"Unable to parse output from nimclient showres: line does not match expected package header format:\n"
"'%{line}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:225
msgid ""
"Unable to parse output from nimclient showres: package string does not match expected installp package string format:\n"
"'%{package_string}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:235
msgid ""
"Unable to parse output from nimclient showres: package string does not match expected rpm package string format:\n"
"'%{package_string}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:245
msgid ""
"Unable to parse output from nimclient showres: line does not match expected package line format:\n"
"'%{line}'"
msgstr ""
#: ../lib/puppet/provider/package/nim.rb:257
msgid ""
"Unrecognized package type specifier: '%{package_type_flag}' in package line:\n"
"'%{line}'"
msgstr ""
#: ../lib/puppet/provider/package/openbsd.rb:52 ../lib/puppet/provider/package/opkg.rb:27
msgid "Failed to match line %{line}"
msgstr ""
#: ../lib/puppet/provider/package/openbsd.rb:143
msgid "No valid installpath found in /etc/pkg.conf and no source was set"
msgstr ""
#: ../lib/puppet/provider/package/openbsd.rb:147
msgid "You must specify a package source or configure an installpath in /etc/pkg.conf"
msgstr ""
#: ../lib/puppet/provider/package/openbsd.rb:220
msgid "%{version} is not available for this package"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:49
msgid "Could not find package '%{name}'"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:86
msgid "Failed to match line '%{line}'"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:92
msgid "Error getting installed packages"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:174
msgid "%{resource_name} is a group, but allow_virtual is false."
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:201
msgid "Refusing to uninstall package group %{resource_name}, because allow_virtual is false."
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:231
msgid "Invalid source '%{source}': %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:240
msgid "puppet:// URL is not supported by pacman"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:242
msgid "Source %{source} is not supported by pacman"
msgstr ""
#: ../lib/puppet/provider/package/pacman.rb:252
msgid "Refusing to install package group %{resource_name}, because allow_virtual is false."
msgstr ""
#: ../lib/puppet/provider/package/pip.rb:58
msgid "Cannot resolve pip version"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:54 ../lib/puppet/provider/package/pkg.rb:64
msgid "Unknown format %{resource_name}: %{full_flags}[%{bad_flag}]"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:95
msgid "Unknown format %{resource_name}: %{state}"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:114
msgid "Unknown line format %{resource_name}: %{parse_line}"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:124
msgid "Unable to unfreeze %{package}"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:159
msgid "Implicit version %{should} has %{n} possible matches"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:178
msgid "Selecting version '%{version}' for implicit '%{should}'"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:183
msgid "No version of %{name} matching %{should} is installable, even though the package is currently installed"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:202
msgid "pkg warning: %{warnings}"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:246
msgid "Pkg could not install %{name} after %{tries} tries. Aborting run"
msgstr ""
#: ../lib/puppet/provider/package/pkg.rb:256 ../lib/puppet/provider/package/pkg.rb:282
msgid "Unable to update %{package}"
msgstr ""
#: ../lib/puppet/provider/package/pkgdmg.rb:79
msgid "Mac OS X PKG DMGs must specify a source string ending in .dmg or flat .pkg file"
msgstr ""
#: ../lib/puppet/provider/package/pkgdmg.rb:108
msgid "No disk entities returned by mount at %{path}"
msgstr ""
#: ../lib/puppet/provider/package/pkgin.rb:44
msgid "declared as absent but unavailable %{file}:%{line}"
msgstr ""
#: ../lib/puppet/provider/package/pkgin.rb:47
msgid "No candidate to be installed"
msgstr ""
#: ../lib/puppet/provider/package/pkgutil.rb:19
msgid "It is highly recommended you create '/var/opt/csw/pkgutil/admin'."
msgstr ""
#: ../lib/puppet/provider/package/pkgutil.rb:20
msgid "See /var/opt/csw/pkgutil"
msgstr ""
#: ../lib/puppet/provider/package/pkgutil.rb:30
msgid "It is highly recommended that you set 'wgetopts=-nv' in your pkgutil.conf."
msgstr ""
#: ../lib/puppet/provider/package/pkgutil.rb:92
msgid "Package not in pkgutil catalog: %{package}"
msgstr ""
#: ../lib/puppet/provider/package/portage.rb:226
msgid "No package found with the specified name [%{name}]"
msgstr ""
#: ../lib/puppet/provider/package/portage.rb:230
msgid "More than one package with the specified name [%{search_value}], please use the category parameter to disambiguate"
msgstr ""
#: ../lib/puppet/provider/package/ports.rb:47
msgid "Could not match package info '%{pkgstuff}'"
msgstr ""
#: ../lib/puppet/provider/package/ports.rb:61
msgid "Could not match version info '%{info}'"
msgstr ""
#: ../lib/puppet/provider/package/portupgrade.rb:156
msgid "Unexpected output from portversion: %{output}"
msgstr ""
#: ../lib/puppet/provider/package/rpm.rb:69
msgid "Failed to list packages"
msgstr ""
#: ../lib/puppet/provider/package/rpm.rb:108 ../lib/puppet/provider/package/rpm.rb:121
msgid "RPMs must specify a package source"
msgstr ""
#: ../lib/puppet/provider/package/sun.rb:80
msgid "Unable to get information about package %{name} because of: %{errmsg}"
msgstr ""
#. TRANSLATORS Sun refers to the company name, do not translate
#: ../lib/puppet/provider/package/sun.rb:98
msgid "Sun packages must specify a package source"
msgstr ""
#: ../lib/puppet/provider/package/urpmi.rb:27
msgid "Package %{name} was not present after trying to install it"
msgstr ""
#: ../lib/puppet/provider/package/windows.rb:43
msgid "Error when unlinking %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/windows.rb:111
msgid "The package %{operation}ed successfully and the system is rebooting now."
msgstr ""
#: ../lib/puppet/provider/package/windows.rb:113
msgid "The package %{operation}ed successfully, but the system must be rebooted."
msgstr ""
#: ../lib/puppet/provider/package/windows.rb:115
msgid "Failed to %{operation}"
msgstr ""
#: ../lib/puppet/provider/package/windows.rb:121
msgid "The source parameter cannot be empty when using the Windows provider."
msgstr ""
#: ../lib/puppet/provider/package/windows/exe_package.rb:80
msgid "Error when installing %{package}: %{detail}"
msgstr ""
#: ../lib/puppet/provider/package/windows/package.rb:63
msgid "The source parameter is required when using the Windows provider."
msgstr ""
#: ../lib/puppet/provider/package/windows/package.rb:71
msgid "The source does not exist: '%{source}'"
msgstr ""
#: ../lib/puppet/provider/package/windows/package.rb:75
msgid "Don't know how to install '%{source}'"
msgstr ""
#: ../lib/puppet/provider/package/yum.rb:70
msgid "The yum provider can only be used as root"
msgstr ""
#: ../lib/puppet/provider/package/yum.rb:124
msgid "Could not check for updates, '%{cmd} check-update' exited with %{status}"
msgstr ""
#: ../lib/puppet/provider/package/yum.rb:159
msgid "Failed to parse package name and architecture from '%{pkgname}'"
msgstr ""
#: ../lib/puppet/provider/package/yum.rb:312
msgid "Could not find package %{wanted}"
msgstr ""
#: ../lib/puppet/provider/package_targetable.rb:57
msgid "Provider %{name} package command is not functional on this host"
msgstr ""
#: ../lib/puppet/provider/package_targetable.rb:60
msgid "Provider %{name} package command '%{cmd}' does not exist on this host"
msgstr ""
#: ../lib/puppet/provider/parsedfile.rb:55
msgid "Invalid filetype %{type}"
msgstr ""
#: ../lib/puppet/provider/parsedfile.rb:103
msgid "Failed to read %{target}'s records when prefetching them. Reason: %{detail}"
msgstr ""
#: ../lib/puppet/provider/parsedfile.rb:285 ../lib/puppet/provider/parsedfile.rb:309
msgid "Prefetching %{target} for provider %{name} returned nil"
msgstr ""
#: ../lib/puppet/provider/parsedfile.rb:295
msgid "Could not prefetch %{resource} provider '%{name}' target '%{target}': %{detail}. Treating as empty"
msgstr ""
#: ../lib/puppet/provider/parsedfile.rb:382
msgid "Parsed Providers must define a default target"
msgstr ""
#: ../lib/puppet/provider/parsedfile.rb:473
msgid "Somehow got told to prefetch with no resource set"
msgstr ""
#: ../lib/puppet/provider/service/base.rb:124
msgid "%{name} is not running"
msgstr ""
#. TRANSLATORS 'plist' and label' should not be translated
#: ../lib/puppet/provider/service/launchd.rb:146
msgid "The %{file} plist does not contain a 'label' key; Puppet is skipping it"
msgstr ""
#: ../lib/puppet/provider/service/launchd.rb:206
msgid "Reading overrides plist, attempt %{i}"
msgstr ""
#: ../lib/puppet/provider/service/launchd.rb:209
msgid "Unable to read overrides plist, too many attempts"
msgstr ""
#: ../lib/puppet/provider/service/launchd.rb:210
msgid "Overrides file could not be read, trying again."
msgstr ""
#. TRANSLATORS 'runsvdir' is a linux service name and should not be translated
#: ../lib/puppet/provider/service/runit.rb:88
msgid "Waiting 5 seconds for runsvdir to discover service %{service}"
msgstr ""
#: ../lib/puppet/provider/service/smf.rb:97
msgid "Failed to get the FMRI of the %{service} service: The pattern '%{service}' matches multiple FMRIs! These are the FMRIs it matches: %{all_fmris}"
msgstr ""
#: ../lib/puppet/provider/service/smf.rb:112
msgid "Cannot query if the %{service} service is complete: The concept of complete/incomplete services was introduced in Solaris 11.1. You are on a Solaris %{release} machine."
msgstr ""
#: ../lib/puppet/provider/service/smf.rb:198
msgid "The %{service} service is incomplete so its status will be reported as :stopped. See `svcs -xv %{fmri}` for more details."
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:23
msgid "Cannot enable %{resource_name}, error was: %{detail}"
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:29
msgid "Cannot disable %{resource_name}, error was: %{detail}"
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:35
msgid "Cannot enable %{resource_name} for manual start, error was: %{detail}"
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:41
msgid "Cannot enable %{resource_name} for delayed start, error was: %{detail}"
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:61
msgid "Unknown start type: %{start_type}"
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:64
msgid "Cannot get start type %{resource_name}, error was: %{detail}"
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:78
msgid "Will not start disabled service %{resource_name} without managing enable. Specify 'enable => false' to override."
msgstr ""
#: ../lib/puppet/provider/service/windows.rb:110
msgid "Unknown service state '%{current_state}' for service '%{resource_name}'"
msgstr ""
#. TRANSLATORS 'AIX' is the name of an operating system and should not be translated
#: ../lib/puppet/provider/user/aix.rb:70
msgid "Could not convert AIX expires date '%{expires}' on %{class_name}[%{resource_name}]"
msgstr ""
#: ../lib/puppet/provider/user/aix.rb:84
msgid "Invalid value %{groups}: Groups must be comma separated!"
msgstr ""
#: ../lib/puppet/provider/user/aix.rb:152
msgid "Could not reset the groups property back to %{cur_groups} after setting the primary group on %{resource}[%{name}]. This means that the previous primary group of %{old_pgrp} and the new primary group of %{new_pgrp} have been added to %{cur_groups}. You will need to manually reset the groups property if this is undesirable behavior. Detail: %{detail}"
msgstr ""
#. TRANSLATORS 'ruby-shadow' is a Ruby gem library
#: ../lib/puppet/provider/user/openbsd.rb:52
msgid "ruby-shadow doesn't support %{method}"
msgstr ""
#: ../lib/puppet/provider/user/windows_adsi.rb:146
msgid "The user account '%s' is disabled; The password will still be changed"
msgstr ""
#: ../lib/puppet/provider/user/windows_adsi.rb:148
msgid "The user account '%s' is locked out; The password will still be changed"
msgstr ""
#: ../lib/puppet/provider/user/windows_adsi.rb:150
msgid "The user account '%s' is expired; The password will still be changed"
msgstr ""
#: ../lib/puppet/reference/indirection.rb:23
msgid "Could not build docs for indirector %{name}, terminus %{terminus}: could not locate terminus."
msgstr ""
#: ../lib/puppet/reference/metaparameter.rb:29
msgid "incorrect metaparams: %{detail}"
msgstr ""
#: ../lib/puppet/reference/providers.rb:58
msgid ""
" - Missing files %{files}\n"
msgstr ""
#: ../lib/puppet/reference/providers.rb:62
msgid ""
" - Setting %{name} (currently %{value}) not in list %{facts}\n"
msgstr ""
#: ../lib/puppet/reference/providers.rb:64
msgid ""
" - Fact %{name} (currently %{value}) not in list %{facts}\n"
msgstr ""
#: ../lib/puppet/reference/providers.rb:68
msgid ""
" - Got %{values} true tests that should have been false\n"
msgstr ""
#: ../lib/puppet/reference/providers.rb:70
msgid ""
" - Got %{values} false tests that should have been true\n"
msgstr ""
#: ../lib/puppet/reference/providers.rb:72
msgid ""
" - Missing features %{values}\n"
msgstr ""
#: ../lib/puppet/reference/type.rb:78
msgid "Could not retrieve property %{sname} on type %{type_name}"
msgstr ""
#: ../lib/puppet/reference/type.rb:82
msgid "No docs for %{type}[%{sname}]"
msgstr ""
#. TRANSLATORS 'NONE' should not be translated
#: ../lib/puppet/relationship.rb:31
msgid "You must pass a callback for non-NONE events"
msgstr ""
#: ../lib/puppet/reports/http.rb:41
msgid "Unable to submit report to %{url} [%{code}] %{message}"
msgstr ""
#: ../lib/puppet/reports/store.rb:65
msgid "Invalid node name %{host}"
msgstr ""
#: ../lib/puppet/resource.rb:53
msgid "No resource type provided in serialized data"
msgstr ""
#: ../lib/puppet/resource.rb:55
msgid "No resource title provided in serialized data"
msgstr ""
#. TRANSLATORS 'Puppet::Resource.new' should not be translated
#: ../lib/puppet/resource.rb:295
msgid "Puppet::Resource.new does not take a hash as the first argument."
msgstr ""
#: ../lib/puppet/resource.rb:296
msgid "Did you mean (%{type}, %{title}) ?"
msgstr ""
#: ../lib/puppet/resource.rb:338
msgid "Could not find declared class %{title}"
msgstr ""
#: ../lib/puppet/resource.rb:340
msgid "Invalid resource type %{type}"
msgstr ""
#: ../lib/puppet/resource.rb:540
msgid "no parameter named '%{name}'"
msgstr ""
#: ../lib/puppet/resource.rb:585
msgid "No title provided and %{type} is not a valid resource reference"
msgstr ""
#: ../lib/puppet/resource.rb:659
msgid "No set of title patterns matched the title \"%{title}\"."
msgstr ""
#: ../lib/puppet/resource/catalog.rb:103
msgid "Cannot add resource %{resource_1} before %{resource_2} because %{resource_2} is not yet in the catalog"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:118
msgid "Cannot add resource %{resource_1} after %{resource_2} because %{resource_2} is not yet in the catalog"
msgstr ""
#. TRANSLATORS 'alias' should not be translated
#: ../lib/puppet/resource/catalog.rb:205
msgid "Cannot alias %{resource} to %{key}; resource %{newref} already declared"
msgstr ""
#. TRANSLATORS 'alias' should not be translated
#: ../lib/puppet/resource/catalog.rb:209
msgid "Cannot alias %{resource} to %{key} at %{resource_declaration}; resource %{newref} already declared"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:291
msgid "Unknown resource type %{type}"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:434
msgid "Could not intern from data: Could not find relationship source %{source} for %{target}"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:441
msgid "Could not intern from data: Could not find relationship target %{target} for %{source}"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:531
msgid "Could not create class file %{file}: %{detail}"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:547
msgid "Could not create resource file %{file}: %{detail}"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:582
msgid "Duplicate declaration: %{resource} is already declared; cannot redeclare"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:584
msgid "Duplicate declaration: %{resource} is already declared at %{error_location}; cannot redeclare"
msgstr ""
#: ../lib/puppet/resource/catalog.rb:633 ../lib/puppet/resource/catalog.rb:638
msgid "Could not find resource %{resource} when converting %{message} resources"
msgstr ""
#: ../lib/puppet/resource/status.rb:140 ../lib/puppet/transaction.rb:275
msgid "Could not evaluate: %{detail}"
msgstr ""
#: ../lib/puppet/resource/type.rb:88
msgid "Invalid resource supertype '%{type}'"
msgstr ""
#: ../lib/puppet/resource/type.rb:118
msgid "%{name} is not a class; cannot add code to it"
msgstr ""
#: ../lib/puppet/resource/type.rb:119
msgid "%{name} is not a class; cannot add code from it"
msgstr ""
#: ../lib/puppet/resource/type.rb:123
msgid "Cannot have code outside of a class/node/define because 'freeze_main' is enabled"
msgstr ""
#: ../lib/puppet/resource/type.rb:127
msgid "Cannot merge classes with different parent classes (%{name} => %{parent} vs. %{other_name} => %{other_parent})"
msgstr ""
#: ../lib/puppet/resource/type.rb:158
msgid "Cannot create resources for defined resource types"
msgstr ""
#: ../lib/puppet/resource/type.rb:211
msgid "Could not find parent resource type '%{parent}' of type %{parent_type} in %{env}"
msgstr ""
#: ../lib/puppet/resource/type.rb:337
msgid "Parameter '%{name}' is given a type, but is not a valid parameter."
msgstr ""
#: ../lib/puppet/resource/type.rb:340
msgid "Parameter '%{name}' is given a type that is not a Puppet Type, got %{class_name}"
msgstr ""
#: ../lib/puppet/resource/type.rb:374
msgid "Could not find scope for %{class_name}"
msgstr ""
#: ../lib/puppet/resource/type.rb:395
msgid "%{param} is a metaparam; this value will inherit to all contained resources in the %{name} definition"
msgstr ""
#: ../lib/puppet/resource/type.rb:397
msgid "%{param} is a metaparameter; please choose another parameter name in the %{name} definition"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:65
msgid "Class '%{klass}' is already defined%{error}; cannot redefine"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:66
msgid "Node '%{klass}' is already defined%{error}; cannot be redefined as a class"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:67
msgid "Definition '%{klass}' is already defined%{error}; cannot be redefined as a class"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:98
msgid "Node '%{name}' is already defined%{error}; cannot redefine"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:99
msgid "Class '%{klass}' is already defined%{error}; cannot be redefined as a node"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:134
msgid "'%{name}' is already defined%{error} as a class; cannot redefine as a definition"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:135
msgid "Definition '%{name}' is already defined%{error}; cannot be redefined"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:179
msgid "Execution of config_version command `%{cmd}` failed: %{message}"
msgstr ""
#: ../lib/puppet/resource/type_collection.rb:202
msgid "Not attempting to load %{type} %{fqname} as this object was missing during a prior compilation"
msgstr ""
#: ../lib/puppet/settings.rb:104
msgid "New environment loaders generated from the requested section."
msgstr ""
#: ../lib/puppet/settings.rb:319
msgid "Attempting to initialize global default settings more than once!"
msgstr ""
#: ../lib/puppet/settings.rb:519
msgid "Using --configprint is deprecated. Use 'puppet config ' instead."
msgstr ""
#: ../lib/puppet/settings.rb:660
msgid "Could not load %{file}: %{detail}"
msgstr ""
#: ../lib/puppet/settings.rb:769
msgid "Invalid setting type '%{type}'"
msgstr ""
#: ../lib/puppet/settings.rb:887
msgid "Cannot manage owner permissions, because the provider for '%{name}' is not functional"
msgstr ""
#: ../lib/puppet/settings.rb:903
msgid "Cannot manage group permissions, because the provider for '%{name}' is not functional"
msgstr ""
#: ../lib/puppet/settings.rb:939
msgid "Unknown searchpath case: %{source_type} for the %{source} settings path element."
msgstr ""
#: ../lib/puppet/settings.rb:1020
msgid "setting definition for '%{name}' is not a hash!"
msgstr ""
#: ../lib/puppet/settings.rb:1025
msgid "Setting %{name} is already defined"
msgstr ""
#: ../lib/puppet/settings.rb:1031
msgid "Setting %{name} is already using short name '%{short}'"
msgstr ""
#: ../lib/puppet/settings.rb:1302
msgid "Setting %{name} is deprecated."
msgstr ""
#. TRANSLATORS 'puppet.conf' is a file name and should not be translated
#: ../lib/puppet/settings.rb:1307
msgid "Setting %{name} is deprecated in puppet.conf."
msgstr ""
#: ../lib/puppet/settings.rb:1494
msgid "Error converting value for param '%{name}': %{detail}"
msgstr ""
#: ../lib/puppet/settings.rb:1518
msgid "Could not find value for %{expression}"
msgstr ""
#. TRANSLATORS '$environment' is a Puppet specific variable and should not be translated
#: ../lib/puppet/settings.rb:1528
msgid "You cannot interpolate $environment within '%{setting_name}' when using directory environments."
msgstr ""
#: ../lib/puppet/settings.rb:1529
msgid "Its value will remain %{value}."
msgstr ""
#: ../lib/puppet/settings.rb:1560
msgid "Attempt to assign a value to unknown setting %{name}"
msgstr ""
#: ../lib/puppet/settings/array_setting.rb:15 ../lib/puppet/settings/http_extra_headers_setting.rb:22
msgid "Expected an Array or String, got a %{klass}"
msgstr ""
#: ../lib/puppet/settings/autosign_setting.rb:20
msgid "Invalid autosign value %{value}: must be 'true'/'false' or an absolute path"
msgstr ""
#. TRANSLATORS ':%{name}', ':call_hook', and ':on_write_only' should not be translated
#: ../lib/puppet/settings/base_setting.rb:39
msgid "Setting :%{name} :call_hook is nil, defaulting to :on_write_only"
msgstr ""
#. TRANSLATORS 'call_hook' is a Puppet option name and should not be translated
#: ../lib/puppet/settings/base_setting.rb:44
msgid "Invalid option %{value} for call_hook"
msgstr ""
#. TRANSLATORS ':call_hook' and ':hook' are specific setting names and should not be translated
#: ../lib/puppet/settings/base_setting.rb:103
msgid "Cannot reference :call_hook for :%{name} if no :hook is defined"
msgstr ""
#: ../lib/puppet/settings/base_setting.rb:109
msgid "%{class_name} (setting '%{setting}') does not accept %{parameter}"
msgstr ""
#: ../lib/puppet/settings/base_setting.rb:116
msgid "You must provide a description for the %{class_name} config option"
msgstr ""
#: ../lib/puppet/settings/base_setting.rb:130
msgid "Short names can only be one character."
msgstr ""
#. TRANSLATORS 'deprecated' is a Puppet setting and ':completely' and ':allowed_on_commandline' are possible values and should not be translated
#: ../lib/puppet/settings/base_setting.rb:199
msgid "Unsupported deprecated value '%{deprecation}'."
msgstr ""
#: ../lib/puppet/settings/base_setting.rb:200
msgid "Supported values for deprecated are ':completely' or ':allowed_on_commandline'"
msgstr ""
#: ../lib/puppet/settings/boolean_setting.rb:26
msgid "Invalid value '%{value}' for boolean parameter: %{name}"
msgstr ""
#: ../lib/puppet/settings/certificate_revocation_setting.rb:19
msgid "Invalid certificate revocation value %{value}: must be one of 'true', 'chain', 'leaf', or 'false'"
msgstr ""
#: ../lib/puppet/settings/config_file.rb:38
msgid "Could not match line %{text}"
msgstr ""
#: ../lib/puppet/settings/config_file.rb:87
msgid "Illegal section '%{name}' in config file at %{error_location}."
msgstr ""
#. TRANSLATORS 'puppet.conf' is the name of the puppet configuration file and should not be translated.
#: ../lib/puppet/settings/config_file.rb:90
msgid "The only valid puppet.conf sections are: [%{allowed_sections_list}]."
msgstr ""
#: ../lib/puppet/settings/config_file.rb:92
msgid "Please use the directory environments feature to specify environments."
msgstr ""
#: ../lib/puppet/settings/config_file.rb:93
msgid "(See https://puppet.com/docs/puppet/latest/environments_about.html)"
msgstr ""
#: ../lib/puppet/settings/config_file.rb:132
msgid "Invalid file option '%{parameter}'"
msgstr ""
#: ../lib/puppet/settings/config_file.rb:136
msgid "File modes must be numbers"
msgstr ""
#: ../lib/puppet/settings/config_file.rb:139
msgid "Could not parse '%{string}'"
msgstr ""
#: ../lib/puppet/settings/duration_setting.rb:30
msgid "Invalid duration format '%{value}' for parameter: %{name}"
msgstr ""
#. TRANSLATORS 'disable_per_environment_manifest' is a setting and 'environment.conf' is a file name and should not be translated
#: ../lib/puppet/settings/environment_conf.rb:71
msgid "The 'disable_per_environment_manifest' setting is true, but the environment located at %{path_to_env} has a manifest setting in its environment.conf of '%{environment_conf}' which does not match the default_manifest setting '%{puppet_conf}'."
msgstr ""
#: ../lib/puppet/settings/environment_conf.rb:73
msgid "If this environment is expecting to find modules in '%{environment_conf}', they will not be available!"
msgstr ""
#: ../lib/puppet/settings/environment_conf.rb:143
msgid "Invalid sections in environment.conf at '%{path_to_conf_file}'. Environment conf may not have sections. The following sections are being ignored: '%{sections}'"
msgstr ""
#: ../lib/puppet/settings/environment_conf.rb:155
msgid "Invalid settings in environment.conf at '%{path_to_conf_file}'. The following unknown setting(s) are being ignored: %{ignored_settings}"
msgstr ""
#: ../lib/puppet/settings/file_setting.rb:203
msgid "The %{parameter} parameter for the setting '%{name}' must be either 'root' or 'service', not '%{value}'"
msgstr ""
#: ../lib/puppet/settings/http_extra_headers_setting.rb:13
msgid "Expected an Array, String, or Hash, got a %{klass}"
msgstr ""
#: ../lib/puppet/settings/integer_setting.rb:9
msgid "Cannot convert '%{value}' to an integer for parameter: %{name}"
msgstr ""
#: ../lib/puppet/settings/port_setting.rb:7
msgid "Value '%{value}' is not a valid port number for parameter: %{name}"
msgstr ""
#: ../lib/puppet/settings/priority_setting.rb:41
msgid "Invalid priority format '%{value}' for parameter: %{name}"
msgstr ""
#: ../lib/puppet/settings/server_list_setting.rb:26
msgid "Expected an Array of String, got a %{klass}"
msgstr ""
#: ../lib/puppet/settings/terminus_setting.rb:12
msgid "Invalid terminus setting: %{value}"
msgstr ""
#: ../lib/puppet/settings/ttl_setting.rb:39
msgid "Invalid negative 'time to live' %{value} - did you mean 'unlimited'?"
msgstr ""
#: ../lib/puppet/settings/ttl_setting.rb:49
msgid "Invalid 'time to live' format '%{value}' for parameter: %{param_name}"
msgstr ""
#: ../lib/puppet/ssl/base.rb:27
msgid "%{name} has not declared what class it wraps"
msgstr ""
#: ../lib/puppet/ssl/base.rb:32 ../lib/puppet/x509/cert_provider.rb:384
msgid "Certname %{name} must not contain unprintable or non-ASCII characters"
msgstr ""
#: ../lib/puppet/ssl/base.rb:38
msgid "%{class_name} did not override 'generate'"
msgstr ""
#: ../lib/puppet/ssl/base.rb:65
msgid "Object must be an instance of %{class_name}, %{actual_class} given"
msgstr ""
#: ../lib/puppet/ssl/base.rb:69
msgid "Name must be supplied if it cannot be determined from the instance"
msgstr ""
#: ../lib/puppet/ssl/base.rb:141
msgid "Unknown signature algorithm '%{ln}'"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:58
msgid "Creating a new SSL certificate request for %{name}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:88
msgid "CSR sign verification failed; you need to clean the certificate request for %{name} on the server"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:94
msgid "Certificate Request fingerprint (%{digest}): %{hex_digest}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:138
msgid "CSR needs content to extract fields"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:165
msgid "In %{attr}, expected extension record %{index} to have two or three items, but found %{count}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:216
msgid "Cannot specify CSR attribute %{oid}: conflicts with internally used CSR attribute"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:225
msgid "Cannot create CSR with attribute %{oid}: %{message}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:242
msgid "Cannot specify CSR extension request %{oid}: conflicts with internally used extension request"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:248
msgid "Cannot create CSR with extension request %{oid}: %{message}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:299
msgid "In %{attr}, expected Set but found %{klass}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:303
msgid "In %{attr}, expected Set[Array] but found %{klass}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:307
msgid "In %{attr}, expected Set[Array] with one value but found %{count} elements"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:311
msgid "In %{attr}, expected Set[Array[Sequence[...]]], but found %{klass}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request.rb:315
msgid "In %{attr}, expected Set[Array[Sequence[Array[...]]]], but found %{klass}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request_attributes.rb:23
msgid "csr_attributes file loading from %{path}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request_attributes.rb:27
msgid "invalid CSR attributes, expected instance of Hash, received instance of %{klass}"
msgstr ""
#: ../lib/puppet/ssl/certificate_request_attributes.rb:32
msgid "unexpected attributes %{keys} in %{path}"
msgstr ""
#: ../lib/puppet/ssl/error.rb:19
msgid "expected one of %{certnames}"
msgstr ""
#: ../lib/puppet/ssl/error.rb:21
msgid "expected %{certname}"
msgstr ""
#: ../lib/puppet/ssl/error.rb:24
msgid "Server hostname '%{host}' did not match server certificate; %{expected_certnames}"
msgstr ""
#: ../lib/puppet/ssl/oids.rb:115
msgid "Error loading ssl custom OIDs mapping file from '%{custom_oid_file}': %{err}"
msgstr ""
#: ../lib/puppet/ssl/oids.rb:119
msgid "Error loading ssl custom OIDs mapping file from '%{custom_oid_file}': no such index '%{map_key}'"
msgstr ""
#: ../lib/puppet/ssl/oids.rb:123
msgid "Error loading ssl custom OIDs mapping file from '%{custom_oid_file}': data under index '%{map_key}' must be a Hash"
msgstr ""
#: ../lib/puppet/ssl/oids.rb:130
msgid "Error loading ssl custom OIDs mapping file from '%{custom_oid_file}': incomplete definition of oid '%{oid}'"
msgstr ""
#: ../lib/puppet/ssl/oids.rb:162
msgid "Error registering ssl custom OIDs mapping from file '%{custom_oid_file}': %{err}"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:86
msgid "Failed to add '%{path}' as a trusted CA file: %{detail}"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:90
msgid "The 'ssl_trust_store' setting does not refer to a file and will be ignored: '%{path}'"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:148
msgid "CA certs are missing"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:149
msgid "CRLs are missing"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:150
msgid "Private key is missing"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:151
msgid "Client cert is missing"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:193
msgid "Failed to load private key for host '%{name}': %{message}"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:207
msgid "The CSR for host '%{name}' does not match the public key"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:220
msgid "Verified client certificate '%{subject}' fingerprint %{digest}"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:222
msgid "Verified CA certificate '%{subject}' fingerprint %{digest}"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:284
msgid "Unsupported key '%{type}'"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:288
msgid "The certificate for '%{name}' does not match its private key"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:308
msgid "The issuer '%{issuer}' of certificate '%{subject}' cannot be found locally"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:324
msgid "The certificate '%{subject}' is not yet valid, verify time is synchronized"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:326
msgid "The certificate '%{subject}' has expired, verify time is synchronized"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:328
msgid "The CRL issued by '%{issuer}' is not yet valid, verify time is synchronized"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:330
msgid "The CRL issued by '%{issuer}' has expired, verify time is synchronized"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:332
msgid "Invalid signature for certificate '%{subject}'"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:334
msgid "Invalid signature for CRL issued by '%{issuer}'"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:336
msgid "The issuer '%{issuer}' of certificate '%{subject}' is missing"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:339
msgid "The CRL issued by '%{issuer}' is missing"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:341
msgid "Certificate '%{subject}' is revoked"
msgstr ""
#: ../lib/puppet/ssl/ssl_provider.rb:345
msgid "Certificate '%{subject}' failed verification (%{err}): %{err_utf8}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:74
msgid "Verified CA bundle with digest (%{digest_type}) %{actual_digest}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:77
msgid "CA bundle with digest (%{digest_type}) %{actual_digest} did not match expected digest %{expected_digest}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:93
msgid "CA certificate is missing from the server"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:95
msgid "Could not download CA certificate: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:111
msgid "Refreshing CA certificate"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:122
msgid "CA certificate is unmodified, using existing CA certificate"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:124 ../lib/puppet/ssl/state_machine.rb:130
msgid "Failed to refresh CA certificate, using existing CA certificate: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:191
msgid "CRL is missing from the server"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:193
msgid "Could not download CRLs: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:209
msgid "Refreshing CRL"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:220
msgid "CRL is unmodified, using existing CRL"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:222 ../lib/puppet/ssl/state_machine.rb:228
msgid "Failed to refresh CRL, using existing CRL: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:255
msgid "Loading/generating private key"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:276
msgid "Creating a new RSA SSL key for %{name}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:315
msgid "Generating and submitting a CSR"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:326
msgid "Failed to submit the CSR, HTTP response was %{code}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:335
msgid "Downloading client certificate"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:341
msgid "Downloaded certificate for %{name} from %{url}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:352
msgid "Failed to parse certificate: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:355
msgid "Certificate for %{certname} has not been signed yet"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:356
msgid "Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate (%{name})."
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:359
msgid "Failed to retrieve certificate for %{certname}: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:369
msgid "Renewing client certificate"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:382
msgid "Renewed client certificate: %{cert_digest}, not before '%{not_before}', not after '%{not_after}'"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:387
msgid "Certificate autorenewal has not been enabled on the server."
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:389
msgid "Failed to automatically renew certificate: %{code} %{reason}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:393
msgid "Unable to automatically renew certificate: %{message}"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:408
msgid "Exiting now because the waitforcert setting is set to 0."
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:411
msgid "Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate (%{name}). Exiting now because the maxwaitforcert timeout has been exceeded."
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:440
msgid "Another puppet instance is already running and the waitforlock setting is set to 0; exiting"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:442
msgid "Another puppet instance is already running and the maxwaitforlock timeout has been exceeded; exiting"
msgstr ""
#: ../lib/puppet/ssl/state_machine.rb:444
msgid "Another puppet instance is already running; waiting for it to finish"
msgstr ""
#. TRANSLATORS: `error` is an untranslated message from openssl describing why a certificate in the server's chain is invalid, and `subject` is the identity/name of the failed certificate
#: ../lib/puppet/ssl/verifier.rb:137
msgid "certificate verify failed [%{error} for %{subject}]"
msgstr ""
#: ../lib/puppet/syntax_checkers/base64.rb:19
msgid "Base64 syntax checker: the text to check must be a String."
msgstr ""
#: ../lib/puppet/syntax_checkers/base64.rb:20
msgid "Base64 syntax checker: the syntax identifier must be a String, e.g. json, data+json"
msgstr ""
#: ../lib/puppet/syntax_checkers/base64.rb:21
msgid "Base64 syntax checker: invalid Acceptor, got: '%{klass}'."
msgstr ""
#: ../lib/puppet/syntax_checkers/base64.rb:29
msgid "Base64 syntax checker: Cannot parse invalid Base64 string - padding is not correct"
msgstr ""
#: ../lib/puppet/syntax_checkers/base64.rb:31
msgid "Base64 syntax checker: Cannot parse invalid Base64 string - contains letters outside strict base 64 range (or whitespace)"
msgstr ""
#: ../lib/puppet/syntax_checkers/epp.rb:18
msgid "EPP syntax checker: the text to check must be a String."
msgstr ""
#: ../lib/puppet/syntax_checkers/epp.rb:19
msgid "EPP syntax checker: the syntax identifier must be a String, e.g. pp"
msgstr ""
#: ../lib/puppet/syntax_checkers/epp.rb:20
msgid "EPP syntax checker: invalid Acceptor, got: '%{klass}'."
msgstr ""
#: ../lib/puppet/syntax_checkers/epp.rb:26
msgid "EPP syntax checker: \"%{message}\""
msgstr ""
#: ../lib/puppet/syntax_checkers/json.rb:18
msgid "Json syntax checker: the text to check must be a String."
msgstr ""
#: ../lib/puppet/syntax_checkers/json.rb:19
msgid "Json syntax checker: the syntax identifier must be a String, e.g. json, data+json"
msgstr ""
#: ../lib/puppet/syntax_checkers/json.rb:20
msgid "Json syntax checker: invalid Acceptor, got: '%{klass}'."
msgstr ""
#: ../lib/puppet/syntax_checkers/json.rb:27
msgid "JSON syntax checker: Cannot parse invalid JSON string. \"%{message}\""
msgstr ""
#: ../lib/puppet/syntax_checkers/pp.rb:18
msgid "PP syntax checker: the text to check must be a String."
msgstr ""
#: ../lib/puppet/syntax_checkers/pp.rb:19
msgid "PP syntax checker: the syntax identifier must be a String, e.g. pp"
msgstr ""
#: ../lib/puppet/syntax_checkers/pp.rb:20
msgid "PP syntax checker: invalid Acceptor, got: '%{klass}'."
msgstr ""
#: ../lib/puppet/syntax_checkers/pp.rb:26
msgid "PP syntax checker: \"%{message}\""
msgstr ""
#: ../lib/puppet/transaction.rb:91
msgid "Some pre-run checks failed"
msgstr ""
#: ../lib/puppet/transaction.rb:107
msgid "Applying configuration version '%{version}'"
msgstr ""
#: ../lib/puppet/transaction.rb:130
msgid "Provider %{name} is not functional on this host"
msgstr ""
#: ../lib/puppet/transaction.rb:146
msgid "Could not find a suitable provider for %{type}"
msgstr ""
#: ../lib/puppet/transaction.rb:153
msgid "post_resource_eval failed for provider %{provider}"
msgstr ""
#: ../lib/puppet/transaction.rb:170
msgid "resource is part of a dependency cycle"
msgstr ""
#: ../lib/puppet/transaction.rb:172
msgid "One or more resource dependency cycles detected in graph"
msgstr ""
#: ../lib/puppet/transaction.rb:187
msgid "Somehow left a component in the relationship graph"
msgstr ""
#: ../lib/puppet/transaction.rb:190
msgid "Starting to evaluate the resource (%{progress} of %{total})"
msgstr ""
#: ../lib/puppet/transaction.rb:193
msgid "Evaluated in %{seconds} seconds"
msgstr ""
#: ../lib/puppet/transaction.rb:310
msgid "Class dependency %{dep} has failures: %{status}"
msgstr ""
#: ../lib/puppet/transaction.rb:316
msgid "Dependency %{dep} has failures: %{status}"
msgstr ""
#: ../lib/puppet/transaction.rb:338
msgid "Prefetch failed for %{type_name} provider '%{name}'"
msgstr ""
#. TRANSLATORS `prefetch` is a function name and should not be translated
#: ../lib/puppet/transaction.rb:383
msgid "Could not prefetch %{type_name} provider '%{name}': %{detail}"
msgstr ""
#: ../lib/puppet/transaction.rb:417
msgid "Skipping resources in class because of failed class dependencies"
msgstr ""
#: ../lib/puppet/transaction.rb:421
msgid "Skipping because of failed dependencies"
msgstr ""
#: ../lib/puppet/transaction.rb:426
msgid "Skipping because provider prefetch failed"
msgstr ""
#: ../lib/puppet/transaction/additional_resource_generator.rb:26
msgid "Failed to generate additional resources using 'generate': %{detail}"
msgstr ""
#: ../lib/puppet/transaction/additional_resource_generator.rb:55
msgid "Depthfirst resources are not supported by eval_generate"
msgstr ""
#. TRANSLATORS eval_generate is a method name and should be left untranslated
#: ../lib/puppet/transaction/additional_resource_generator.rb:62
msgid "Failed to generate additional resources using 'eval_generate': %{detail}"
msgstr ""
#: ../lib/puppet/transaction/event.rb:125
msgid "Event status can only be %{statuses}"
msgstr ""
#: ../lib/puppet/transaction/event_manager.rb:89
msgid "Unscheduling all events on %{target}"
msgstr ""
#: ../lib/puppet/transaction/event_manager.rb:95
msgid "Unscheduling %{callback} on %{target}"
msgstr ""
#: ../lib/puppet/transaction/event_manager.rb:110
msgid "Scheduling %{callback} of %{target}"
msgstr ""
#: ../lib/puppet/transaction/event_manager.rb:153
msgid "Triggered '%{callback}' from %{count} event"
msgid_plural "Triggered '%{callback}' from %{count} events"
msgstr[0] ""
msgstr[1] ""
#: ../lib/puppet/transaction/event_manager.rb:160
msgid "Failed to call %{callback}: %{detail}"
msgstr ""
#: ../lib/puppet/transaction/event_manager.rb:175
msgid "Would have triggered '%{callback}' from %{count} event"
msgid_plural "Would have triggered '%{callback}' from %{count} events"
msgstr[0] ""
msgstr[1] ""
#: ../lib/puppet/transaction/persistence.rb:79
msgid "Transaction store file %{filename} is not a file, ignoring"
msgstr ""
#: ../lib/puppet/transaction/persistence.rb:84
msgid "Loaded transaction store file in %{seconds} seconds"
msgstr ""
#: ../lib/puppet/transaction/persistence.rb:88
msgid "Transaction store file %{filename} is corrupt (%{detail}); replacing"
msgstr ""
#: ../lib/puppet/transaction/persistence.rb:93
msgid "Unable to rename corrupt transaction store file: %{detail}"
msgstr ""
#: ../lib/puppet/transaction/persistence.rb:94
msgid "Could not rename corrupt transaction store file %{filename}; remove manually"
msgstr ""
#: ../lib/puppet/transaction/persistence.rb:102
msgid "Transaction store file %{filename} is valid YAML but not returning a hash. Check the file for corruption, or remove it before continuing."
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:52
msgid "Cannot schedule without a schedule-containing catalog"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:58
msgid "Could not find schedule %{name}"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:150 ../lib/puppet/transaction/resource_harness.rb:158
msgid "change from %s to %s failed: "
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:165
msgid "could not create change error message for %{name}"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:218
msgid "audit change: previously recorded value %s has been changed to %s"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:228
msgid " (previously recorded value was %s)"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:235
msgid "current_value %s, should be %s (noop)"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:244
msgid "changed %s to %s"
msgstr ""
#: ../lib/puppet/transaction/resource_harness.rb:267
msgid "audit change: newly-recorded value %s"
msgstr ""
#: ../lib/puppet/trusted_external.rb:7
msgid "Retrieving trusted external data from %{command}"
msgstr ""
#: ../lib/puppet/trusted_external.rb:21
msgid "Skipping non-executable file %{file}"
msgstr ""
#: ../lib/puppet/trusted_external.rb:26
msgid "There is more than one '%{basename}' script in %{dir}"
msgstr ""
#: ../lib/puppet/type.rb:507
msgid "Options must be a hash, not %{type}"
msgstr ""
#: ../lib/puppet/type.rb:510
msgid "Class %{class_name} already has a property named %{property}"
msgstr ""
#: ../lib/puppet/type.rb:597
msgid "Class %{class_name} has not defined parameters"
msgstr ""
#: ../lib/puppet/type.rb:684
msgid "Parameter %{name} failed on %{ref}: %{detail}"
msgstr ""
#: ../lib/puppet/type.rb:705
msgid "Undefined attribute '%{attribute}' in %{name}"
msgstr ""
#: ../lib/puppet/type.rb:1149
msgid "%{name} has no providers and has not overridden 'instances'"
msgstr ""
#: ../lib/puppet/type.rb:1413
msgid "Cannot add aliases without a catalog"
msgstr ""
#: ../lib/puppet/type.rb:1493
msgid "Could not find %{description} %{ref} for %{resource}"
msgstr ""
#: ../lib/puppet/type.rb:1717
msgid "Found multiple default providers for %{name}: %{provider_list}; using %{selected_provider}"
msgstr ""
#: ../lib/puppet/type.rb:1804
msgid "Could not find parent provider %{parent} of %{name}"
msgstr ""
#: ../lib/puppet/type.rb:1878
msgid "Invalid %{resource} provider '%{provider_class}'"
msgstr ""
#: ../lib/puppet/type.rb:1963
msgid "Could not find %{name} provider of %{provider}"
msgstr ""
#: ../lib/puppet/type.rb:2081
msgid "You cannot add relationships without a catalog"
msgstr ""
#: ../lib/puppet/type.rb:2401
msgid "Unable to mark '%{name}' as sensitive: %{name} is a parameter and not a property, and cannot be automatically redacted."
msgstr ""
#: ../lib/puppet/type.rb:2404
msgid "Unable to mark '%{name}' as sensitive: the property itself was not assigned a value."
msgstr ""
#: ../lib/puppet/type.rb:2406
msgid "Unable to mark '%{name}' as sensitive: the property itself is not defined on %{type}."
msgstr ""
#: ../lib/puppet/type.rb:2464
msgid "Could not set %{attribute} on %{class_name}: %{detail}"
msgstr ""
#: ../lib/puppet/type/exec.rb:122
msgid "executed successfully"
msgstr ""
#: ../lib/puppet/type/exec.rb:156
msgid "Command exceeded timeout"
msgstr ""
#: ../lib/puppet/type/exec.rb:185
msgid "[command redacted] returned %{status} instead of one of [%{expected}]"
msgstr ""
#: ../lib/puppet/type/exec.rb:187
msgid "'%{cmd}' returned %{status} instead of one of [%{expected}]"
msgstr ""
#: ../lib/puppet/type/exec.rb:217
msgid "Command must be a String or Array, got value of class %{klass}"
msgstr ""
#: ../lib/puppet/type/exec.rb:250
msgid "Unable to execute commands as other users on Windows"
msgstr ""
#: ../lib/puppet/type/exec.rb:252
msgid "Only root can execute commands as other users"
msgstr ""
#: ../lib/puppet/type/exec.rb:308
msgid "Invalid environment setting '%{value}'"
msgstr ""
#: ../lib/puppet/type/exec.rb:321
msgid "The umask specification is invalid: %{value}"
msgstr ""
#: ../lib/puppet/type/exec.rb:337
msgid "The timeout must be a number."
msgstr ""
#: ../lib/puppet/type/exec.rb:354
msgid "Tries must be an integer"
msgstr ""
#: ../lib/puppet/type/exec.rb:358
msgid "Tries must be an integer >= 1"
msgstr ""
#: ../lib/puppet/type/exec.rb:371
msgid "try_sleep must be a number"
msgstr ""
#: ../lib/puppet/type/exec.rb:375
msgid "try_sleep cannot be a negative number"
msgstr ""
#. TRANSLATORS 'creates' is a parameter name and should not be translated
#: ../lib/puppet/type/exec.rb:447
msgid "Checking that 'creates' path '%{creates_path}' exists"
msgstr ""
#: ../lib/puppet/type/exec.rb:499 ../lib/puppet/type/exec.rb:562
msgid "Check %{value} exceeded timeout"
msgstr ""
#: ../lib/puppet/type/exec.rb:662
msgid "'%{cmd}' won't be executed because of failed check '%{check}'"
msgstr ""
#: ../lib/puppet/type/file.rb:61
msgid "File paths must be fully qualified, not '%{path}'"
msgstr ""
#: ../lib/puppet/type/file.rb:140
msgid "Invalid backup type %{value}"
msgstr ""
#: ../lib/puppet/type/file.rb:184 ../lib/puppet/type/tidy.rb:49
msgid "Invalid recurse value %{value}"
msgstr ""
#: ../lib/puppet/type/file.rb:216
msgid "Invalid recurselimit value %{value}"
msgstr ""
#: ../lib/puppet/type/file.rb:433
msgid "You cannot specify more than one of %{creators}"
msgstr ""
#: ../lib/puppet/type/file.rb:435
msgid "You cannot specify a remote recursion without a source"
msgstr ""
#: ../lib/puppet/type/file.rb:437
msgid "You cannot specify source when using checksum 'none'"
msgstr ""
#: ../lib/puppet/type/file.rb:440
msgid "You cannot specify content when using checksum '%{checksum_type}'"
msgstr ""
#: ../lib/puppet/type/file.rb:443
msgid "Possible error: recurselimit is set but not recurse, no recursion will happen"
msgstr ""
#: ../lib/puppet/type/file.rb:451
msgid "Checksum value '%{value}' is not a valid checksum type %{checksum}"
msgstr ""
#: ../lib/puppet/type/file.rb:454
msgid "Checksum value is ignored unless content or source are specified"
msgstr ""
#: ../lib/puppet/type/file.rb:492
msgid "Can not find filebucket for backups without a catalog"
msgstr ""
#: ../lib/puppet/type/file.rb:497
msgid "Could not find filebucket %{backup} specified in backup"
msgstr ""
#: ../lib/puppet/type/file.rb:796
msgid "Could not back up file of type %{current_type}"
msgstr ""
#: ../lib/puppet/type/file.rb:811
msgid "Could not remove files of type %{current_type}"
msgstr ""
#. TRANSLATORS "source_permissions => ignore" should not be translated
#: ../lib/puppet/type/file.rb:822
msgid "Copying owner/mode/group from the source file on Windows is not supported; use source_permissions => ignore."
msgstr ""
#. TRANSLATORS "stat" is a program name and should not be translated
#: ../lib/puppet/type/file.rb:903 ../lib/puppet/type/tidy.rb:373
msgid "Could not stat; permission denied"
msgstr ""
#: ../lib/puppet/type/file.rb:906
msgid "Could not stat; invalid pathname"
msgstr ""
#: ../lib/puppet/type/file.rb:1034
msgid "Not removing directory; use 'force' to override"
msgstr ""
#. TRANSLATORS refers to a file which could not be backed up
#: ../lib/puppet/type/file.rb:1059
msgid "Could not back up; will not remove"
msgstr ""
#: ../lib/puppet/type/file.rb:1074
msgid "File written to disk did not match desired checksum; discarding changes (%{content_checksum} vs %{desired_checksum})"
msgstr ""
#: ../lib/puppet/type/file/checksum.rb:21
msgid "MD5 is not supported in FIPS mode"
msgstr ""
#. TRANSLATORS "content" is an attribute and should not be translated
#: ../lib/puppet/type/file/content.rb:54
msgid "Using a checksum in a file's \"content\" property is deprecated."
msgstr ""
#. TRANSLATORS "filebucket" is a resource type and should not be translated. The quoted occurrence of "content" is an attribute and should not be translated.
#: ../lib/puppet/type/file/content.rb:56
msgid "The ability to use a checksum to retrieve content from the filebucket using the \"content\" property will be removed in a future release."
msgstr ""
#. TRANSLATORS "content" is an attribute and should not be translated.
#: ../lib/puppet/type/file/content.rb:58
msgid "The literal value of the \"content\" property will be written to the file."
msgstr ""
#. TRANSLATORS "static catalogs" should not be translated.
#: ../lib/puppet/type/file/content.rb:60
msgid "The checksum retrieval functionality is being replaced by the use of static catalogs."
msgstr ""
#: ../lib/puppet/type/file/content.rb:61
msgid "See https://puppet.com/docs/puppet/latest/static_catalogs.html for more information."
msgstr ""
#. TRANSLATORS 'Ensure' is an attribute and ':present' is a value and should not be translated
#: ../lib/puppet/type/file/data_sync.rb:32
msgid "Ensure set to :present but file type is %{file_type} so no content will be synced"
msgstr ""
#: ../lib/puppet/type/file/mode.rb:133
msgid "Not managing symlink mode"
msgstr ""
#. TRANSLATORS "source_permissions" is a parameter name and should not be translated
#: ../lib/puppet/type/file/source.rb:374
msgid "The `source_permissions` parameter is deprecated. Explicitly set `owner`, `group`, and `mode`."
msgstr ""
#: ../lib/puppet/type/filebucket.rb:74
msgid "You can only have one filebucket path"
msgstr ""
#: ../lib/puppet/type/filebucket.rb:78
msgid "Filebucket paths must be absolute"
msgstr ""
#: ../lib/puppet/type/filebucket.rb:114
msgid "Could not create %{type} filebucket: %{detail}"
msgstr ""
#: ../lib/puppet/type/group.rb:60
msgid "GID cannot be deleted"
msgstr ""
#: ../lib/puppet/type/group.rb:72
msgid "Invalid GID %{gid}"
msgstr ""
#: ../lib/puppet/type/package.rb:125 ../lib/puppet/type/package.rb:139
msgid "Could not update: %{detail}"
msgstr ""
#: ../lib/puppet/type/package.rb:174
msgid "Could not get latest version: %{detail}"
msgstr ""
#: ../lib/puppet/type/package.rb:274
msgid "Name must be a String not %{klass}"
msgstr ""
#: ../lib/puppet/type/package.rb:420
msgid "Cannot have both `ensure => disabled` and `flavor`"
msgstr ""
#: ../lib/puppet/type/package.rb:519
msgid "Cannot have both `enable_only => true` and `flavor`"
msgstr ""
#: ../lib/puppet/type/package.rb:522
msgid "Cannot have both `ensure => disabled` and `enable_only => true`"
msgstr ""
#: ../lib/puppet/type/package.rb:683
msgid "Invalid hold value %{value}. %{doc}"
msgstr ""
#: ../lib/puppet/type/package.rb:710
msgid "You cannot use \"mark\" property while \"ensure\" is one of [\"absent\", \"purged\"]"
msgstr ""
#: ../lib/puppet/type/resources.rb:17
msgid "Could not find resource type '%{name}'"
msgstr ""
#: ../lib/puppet/type/resources.rb:35
msgid "Purging resources of type %{res_type} is not supported, since they cannot be queried from the system"
msgstr ""
#: ../lib/puppet/type/resources.rb:37
msgid "Purging is only supported on types that accept 'ensure'"
msgstr ""
#: ../lib/puppet/type/resources.rb:59
msgid "Invalid value %{value}"
msgstr ""
#: ../lib/puppet/type/resources.rb:111
msgid "The 'ensure' attribute on %{name} resources does not accept 'absent' as a value"
msgstr ""
#: ../lib/puppet/type/resources.rb:134
msgid "Could not find resource type"
msgstr ""
#: ../lib/puppet/type/schedule.rb:104
msgid "Invalid range value '%{value}'"
msgstr ""
#: ../lib/puppet/type/schedule.rb:121
msgid "Invalid range %{value}"
msgstr ""
#: ../lib/puppet/type/schedule.rb:130
msgid "Invalid hour '%{n}'"
msgstr ""
#: ../lib/puppet/type/schedule.rb:134
msgid "Invalid minute '%{n}'"
msgstr ""
#: ../lib/puppet/type/schedule.rb:283
msgid "Repeat must be a number"
msgstr ""
#: ../lib/puppet/type/schedule.rb:292
msgid "Repeat must be 1 unless periodmatch is 'distance', not '%{period}'"
msgstr ""
#: ../lib/puppet/type/schedule.rb:336
msgid "%{value} is not a valid day of the week"
msgstr ""
#: ../lib/puppet/type/service.rb:152 ../lib/puppet/type/user.rb:274
msgid "Passwords cannot include ':'"
msgstr ""
#: ../lib/puppet/type/service.rb:284
msgid "\"%{value}\" is not a positive integer: the timeout parameter must be specified as a positive integer"
msgstr ""
#: ../lib/puppet/type/service.rb:306
msgid "The 'logonaccount' parameter is mandatory when setting 'logonpassword'."
msgstr ""
#: ../lib/puppet/type/tidy.rb:102
msgid "Tidy can't use matches with recurse 0, false, or undef"
msgstr ""
#: ../lib/puppet/type/tidy.rb:142
msgid "Invalid age unit '%{unit}'"
msgstr ""
#. TRANSLATORS tidy is the name of a program and should not be translated
#: ../lib/puppet/type/tidy.rb:162
msgid "Invalid tidy age %{age}"
msgstr ""
#: ../lib/puppet/type/tidy.rb:184
msgid "Invalid size unit '%{unit}'"
msgstr ""
#. TRANSLATORS tidy is the name of a program and should not be translated
#: ../lib/puppet/type/tidy.rb:202
msgid "Invalid tidy size %{age}"
msgstr ""
#. TRANSLATORS "Tidy" is a program name and should not be translated
#: ../lib/puppet/type/tidy.rb:296
msgid "Tidying %{count} files"
msgstr ""
#: ../lib/puppet/type/tidy.rb:369
msgid "File does not exist"
msgstr ""
#: ../lib/puppet/type/user.rb:182
msgid "Could not find group(s) %{groups}"
msgstr ""
#: ../lib/puppet/type/user.rb:294
msgid "Password minimum age must be provided as a number."
msgstr ""
#: ../lib/puppet/type/user.rb:313
msgid "Password maximum age must be provided as a number."
msgstr ""
#: ../lib/puppet/type/user.rb:344
msgid "Group names must be provided, not GID numbers."
msgstr ""
#: ../lib/puppet/type/user.rb:346
msgid "Group names must be provided as an array, not a comma-separated list."
msgstr ""
#: ../lib/puppet/type/user.rb:347
msgid "Group names must not be empty. If you want to specify \"no groups\" pass an empty array"
msgstr ""
#: ../lib/puppet/type/user.rb:440
msgid "User provider %{name} can not manage home directories"
msgstr ""
#. TRANSLATORS YYYY-MM-DD represents a date with a four-digit year, a two-digit month, and a two-digit day,
#. TRANSLATORS separated by dashes.
#: ../lib/puppet/type/user.rb:457
msgid "Expiry dates must be YYYY-MM-DD or the string \"absent\""
msgstr ""
#: ../lib/puppet/type/user.rb:524
msgid "Role names must be provided, not numbers"
msgstr ""
#: ../lib/puppet/type/user.rb:526
msgid "Role names must be provided as an array, not a comma-separated list"
msgstr ""
#: ../lib/puppet/type/user.rb:563
msgid "Auth names must be provided, not numbers"
msgstr ""
#: ../lib/puppet/type/user.rb:565
msgid "Auth names must be provided as an array, not a comma-separated list"
msgstr ""
#: ../lib/puppet/type/user.rb:589
msgid "Profile names must be provided, not numbers"
msgstr ""
#: ../lib/puppet/type/user.rb:591
msgid "Profile names must be provided as an array, not a comma-separated list"
msgstr ""
#: ../lib/puppet/type/user.rb:702
msgid "Ssh_authorized_key type is not available. Cannot purge SSH keys."
msgstr ""
#: ../lib/puppet/type/user.rb:740
msgid "Each entry for purge_ssh_keys must be a string, not a %{klass}"
msgstr ""
#: ../lib/puppet/type/user.rb:743
msgid "Paths to keyfiles must be absolute, not %{entry}"
msgstr ""
#: ../lib/puppet/type/user.rb:747
msgid "purge_ssh_keys must be true, false, or an array of file names, not %{value}"
msgstr ""
#: ../lib/puppet/type/user.rb:795
msgid "Class name must be provided."
msgstr ""
#: ../lib/puppet/util.rb:113
msgid "could not change to group %{group}: %{detail}"
msgstr ""
#: ../lib/puppet/util.rb:114
msgid "could not change to group %{group}"
msgstr ""
#: ../lib/puppet/util.rb:127
msgid "Could not change to user %{user}: %{detail}"
msgstr ""
#. TRANSLATORS 'benchmark' is a method name and should not be translated
#: ../lib/puppet/util.rb:181
msgid "Failed to provide level to benchmark"
msgstr ""
#: ../lib/puppet/util.rb:184
msgid "Benchmarked object does not respond to %{value}"
msgstr ""
#. TRANSLATORS PATH and HOME are environment variables and should not be translated
#: ../lib/puppet/util.rb:224
msgid "PATH contains a ~ character, and HOME is not set; ignoring PATH element '%{dir}'."
msgstr ""
#. TRANSLATORS PATH is an environment variable and should not be translated
#: ../lib/puppet/util.rb:228
msgid "Couldn't expand PATH containing a ~ character; ignoring PATH element '%{dir}'."
msgstr ""
#: ../lib/puppet/util.rb:275
msgid "unknown platform %{platform} in absolute_path"
msgstr ""
#: ../lib/puppet/util.rb:310
msgid "Failed to convert '%{path}' to URI: %{detail}"
msgstr ""
#: ../lib/puppet/util.rb:410
msgid "path may not be nil"
msgstr ""
#: ../lib/puppet/util.rb:586
msgid "replace_file requires a block"
msgstr ""
#: ../lib/puppet/util.rb:590
msgid "replace_file default_mode: %{default_mode} is invalid"
msgstr ""
#: ../lib/puppet/util/at_fork.rb:23
msgid "Failed to load Solaris implementation of the Puppet::Util::AtFork handler. Child process contract management will be unavailable, which means that agent runs executed by the puppet agent service will be killed when they attempt to restart the service."
msgstr ""
#: ../lib/puppet/util/at_fork/solaris.rb:9
msgid "The loaded Fiddle version is not supported."
msgstr ""
#: ../lib/puppet/util/at_fork/solaris.rb:84
msgid "Failed to activate a new process contract template"
msgstr ""
#: ../lib/puppet/util/at_fork/solaris.rb:98
msgid "Failed to deactivate process contract template in the parent process"
msgstr ""
#: ../lib/puppet/util/at_fork/solaris.rb:100
msgid "Failed to deactivate process contract template in the child process"
msgstr ""
#: ../lib/puppet/util/at_fork/solaris.rb:125
msgid "Failed to get latest child process contract id"
msgstr ""
#: ../lib/puppet/util/at_fork/solaris.rb:143
msgid "Failed to abandon a child process contract"
msgstr ""
#: ../lib/puppet/util/autoload.rb:84
msgid "Could not autoload %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/util/autoload.rb:178
msgid "Autoload paths cannot be fully qualified"
msgstr ""
#: ../lib/puppet/util/backups.rb:27
msgid "Recursively backing up to filebucket"
msgstr ""
#: ../lib/puppet/util/backups.rb:50
msgid "Could not back %{file} up: %{message}"
msgstr ""
#: ../lib/puppet/util/backups.rb:68
msgid "Will not remove directory backup %{newfile}; use a filebucket"
msgstr ""
#: ../lib/puppet/util/backups.rb:71
msgid "Removing old backup of type %{file_type}"
msgstr ""
#: ../lib/puppet/util/backups.rb:76
msgid "Could not remove old backup: %{detail}"
msgstr ""
#: ../lib/puppet/util/backups.rb:84
msgid "Filebucketed %{f} to %{filebucket} with sum %{sum}"
msgstr ""
#: ../lib/puppet/util/character_encoding.rb:24
msgid "%{value} is already labeled as UTF-8 but this encoding is invalid. It cannot be transcoded by Puppet."
msgstr ""
#: ../lib/puppet/util/character_encoding.rb:46
msgid "%{error}: %{value} cannot be transcoded by Puppet."
msgstr ""
#: ../lib/puppet/util/character_encoding.rb:74
msgid "%{value} is not valid UTF-8 and result of overriding encoding would be invalid."
msgstr ""
#: ../lib/puppet/util/classgen.rb:157
msgid "Redefining %{name} in %{klass}"
msgstr ""
#: ../lib/puppet/util/classgen.rb:161
msgid "Class %{const} is already defined in %{klass}"
msgstr ""
#: ../lib/puppet/util/classgen.rb:209 ../lib/puppet/util/classgen.rb:222
msgid "Already a generated class named %{klassname}"
msgstr ""
#: ../lib/puppet/util/command_line.rb:72
msgid "Could not initialize global default settings"
msgstr ""
#: ../lib/puppet/util/command_line.rb:174
msgid "Error: Could not parse application options: invalid option: %{opt}"
msgstr ""
#: ../lib/puppet/util/command_line.rb:177
msgid "See 'puppet help' for help on available puppet subcommands"
msgstr ""
#: ../lib/puppet/util/command_line.rb:190
msgid "Error: Unknown Puppet subcommand '%{cmd}'"
msgstr ""
#: ../lib/puppet/util/command_line/puppet_option_parser.rb:48
msgid "this method only takes 3 or 4 arguments. Given: %{args}"
msgstr ""
#: ../lib/puppet/util/command_line/puppet_option_parser.rb:65
msgid "Unsupported type: '%{type}'"
msgstr ""
#: ../lib/puppet/util/command_line/puppet_option_parser.rb:77
msgid "Error parsing arguments"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:150
msgid "you already have an argument named '%{name}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:169 ../lib/puppet/util/command_line/trollop.rb:173
msgid "unsupported argument type '%{type}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:198
msgid "multiple argument type cannot be deduced from an empty array for '%{value0}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:207
msgid "unsupported multiple argument type '%{value0}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:211
msgid "unsupported argument type '%{value0}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:214
msgid ":type specification and default type don't match (default type is %{type_from_default})"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:227
msgid "invalid long option name %{name}"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:229
msgid "long option name %{value0} is already taken; please specify a (different) :long"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:236
msgid "invalid short option name '%{name}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:240
msgid "short option name %{value0} is already taken; please specify a (different) :short"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:241
msgid "a short option name can't be a number or a dash"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:274 ../lib/puppet/util/command_line/trollop.rb:280
msgid "unknown option '%{sym}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:314
msgid "Print version and exit"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:315
msgid "Show this message"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:337
msgid "invalid argument syntax: '%{arg}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:342
msgid "unknown argument '%{arg}'"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:346
msgid "option '%{arg}' specified multiple times"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:383
msgid "--%{value0} requires --%{value1}"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:385
msgid "--%{value0} conflicts with --%{value1}"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:390
msgid "option --%{opt} must be specified"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:399
msgid "option '%{arg}' needs a parameter"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:459
msgid "option '%{arg}' needs a date"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:492
msgid "Options:"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:516
msgid " (Default: %{default_s})"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:518
msgid " (default: %{default_s})"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:555
msgid "Error: argument --%{value0} %{msg}."
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:557
msgid "Error: %{arg}."
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:559 ../lib/puppet/util/command_line/trollop.rb:783
msgid "Try --help for help."
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:638
msgid "option '%{arg}' needs an integer"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:643
msgid "option '%{arg}' needs a floating-point number"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:655
msgid "file or url for option '%{arg}' cannot be opened: %{value0}"
msgstr ""
#: ../lib/puppet/util/command_line/trollop.rb:782
msgid "Error: %{value0}."
msgstr ""
#. TRANSLATORS 'Trollop' is the name of a module and 'die' and 'options' are methods in it and should not be translated.
#: ../lib/puppet/util/command_line/trollop.rb:817
msgid "Trollop::die can only be called after Trollop::options"
msgstr ""
#: ../lib/puppet/util/diff.rb:31
msgid "Cannot provide diff without the diff/lcs Ruby library"
msgstr ""
#: ../lib/puppet/util/errors.rb:48
msgid "(file: %{file}, line: %{line}, column: %{column})"
msgstr ""
#: ../lib/puppet/util/errors.rb:50
msgid "(file: %{file}, line: %{line})"
msgstr ""
#: ../lib/puppet/util/errors.rb:52
msgid "(line: %{line}, column: %{column})"
msgstr ""
#: ../lib/puppet/util/errors.rb:54
msgid "(line: %{line})"
msgstr ""
#: ../lib/puppet/util/errors.rb:56
msgid "(file: %{file})"
msgstr ""
#: ../lib/puppet/util/errors.rb:89 ../lib/puppet/util/errors.rb:90
msgid "unknown"
msgstr ""
#: ../lib/puppet/util/errors.rb:120
msgid "%{klass} failed with error %{error_type}: %{detail}"
msgstr ""
#: ../lib/puppet/util/execution.rb:187
msgid "Working directory %{cwd} does not exist!"
msgstr ""
#: ../lib/puppet/util/execution.rb:284
msgid "Could not get output"
msgstr ""
#: ../lib/puppet/util/execution.rb:293
msgid "Execution of '%{str}' returned %{exit_status}: %{output}"
msgstr ""
#: ../lib/puppet/util/execution.rb:370
msgid "Could not execute posix command: %{detail}"
msgstr ""
#: ../lib/puppet/util/execution.rb:418
msgid "Waiting for output; will sleep %{time_to_sleep} seconds"
msgstr ""
#: ../lib/puppet/util/feature.rb:92
msgid "Failed to load feature test for %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/util/feature.rb:111
msgid "Libraries must be passed as strings not %{klass}"
msgstr ""
#: ../lib/puppet/util/feature.rb:121
msgid "Could not find library '%{lib}' required to enable feature '%{name}'"
msgstr ""
#: ../lib/puppet/util/feature.rb:125
msgid "Exception occurred while loading library '%{lib}' required to enable feature '%{name}': %{detail}"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:44
msgid "Cannot have fields named %{name}"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:64 ../lib/puppet/util/fileparsing.rb:338
msgid "Invalid record type %{record_type}"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:112
msgid "Field '%{field}' is required"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:179
msgid "Process record type %{record_name} returned non-hash"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:259
msgid "Could not parse line %{line}"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:268
msgid "No record types defined; cannot parse lines"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:280
msgid "Somehow got invalid line type %{record_type}"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:302
msgid "Must include a list of fields"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:317
msgid "You must provide a :match regex for text lines"
msgstr ""
#: ../lib/puppet/util/fileparsing.rb:396
msgid "Line type %{name} is already defined"
msgstr ""
#: ../lib/puppet/util/filetype.rb:49
msgid "%{klass} could not read %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/util/filetype.rb:65
msgid "%{klass} could not write %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/util/filetype.rb:83
msgid "Path is nil"
msgstr ""
#: ../lib/puppet/util/filetype.rb:153
msgid "Reading %{path} from RAM"
msgstr ""
#: ../lib/puppet/util/filetype.rb:159
msgid "Removing %{path} from RAM"
msgstr ""
#: ../lib/puppet/util/filetype.rb:165
msgid "Writing %{path} to RAM"
msgstr ""
#: ../lib/puppet/util/filetype.rb:186
msgid "Could not retrieve user %{user}: %{detail}"
msgstr ""
#: ../lib/puppet/util/filetype.rb:197 ../lib/puppet/util/filetype.rb:262 ../lib/puppet/util/filetype.rb:313
msgid "The %{path} user does not exist. Treating their crontab file as empty in case Puppet creates them in the middle of the run."
msgstr ""
#: ../lib/puppet/util/filetype.rb:208 ../lib/puppet/util/filetype.rb:273 ../lib/puppet/util/filetype.rb:324
msgid "The %{path} user is not authorized to use cron. Their crontab file is treated as empty in case Puppet authorizes them in the middle of the run (by, for example, modifying the cron.deny or cron.allow files)."
msgstr ""
#: ../lib/puppet/util/filetype.rb:212 ../lib/puppet/util/filetype.rb:277 ../lib/puppet/util/filetype.rb:328
msgid "Could not read crontab for %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/util/filetype.rb:234
msgid "Cannot write the %{path} user's crontab: The user does not exist"
msgstr ""
#: ../lib/puppet/util/filetype.rb:285 ../lib/puppet/util/filetype.rb:336
msgid "Could not remove crontab for %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/util/filetype.rb:300 ../lib/puppet/util/filetype.rb:352
msgid "Could not write crontab for %{path}: %{detail}"
msgstr ""
#: ../lib/puppet/util/inifile.rb:140
msgid "Cannot read nonexistent file %{file}"
msgstr ""
#: ../lib/puppet/util/inifile.rb:186
msgid "Property with key %{key} outside of a section"
msgstr ""
#: ../lib/puppet/util/inifile.rb:192
msgid "Can't parse line '%{line}'"
msgstr ""
#: ../lib/puppet/util/inifile.rb:241
msgid "Section %{name} is already defined, cannot redefine"
msgstr ""
#: ../lib/puppet/util/instance_loader.rb:57
msgid "Loaded %{type} file for %{name} but %{type} was not defined"
msgstr ""
#: ../lib/puppet/util/json_lockfile.rb:41
msgid "Unable to read lockfile data from %{path}: not in JSON"
msgstr ""
#: ../lib/puppet/util/ldap/connection.rb:38
msgid "Could not set up LDAP Connection: Missing ruby/ldap libraries"
msgstr ""
#: ../lib/puppet/util/ldap/connection.rb:72
msgid "Could not connect to LDAP: %{detail}"
msgstr ""
#. TRANSLATORS '#connect' is a method name and and should not be translated, 'block' refers to a Ruby code block
#: ../lib/puppet/util/ldap/manager.rb:49
msgid "You must pass a block to #connect"
msgstr ""
#: ../lib/puppet/util/ldap/manager.rb:93
msgid "Could not get dn from ldap entry"
msgstr ""
#: ../lib/puppet/util/ldap/manager.rb:146
msgid "%{source} must be defined to generate %{name}"
msgstr ""
#: ../lib/puppet/util/ldap/manager.rb:223
msgid "Removing %{name} from ldap"
msgstr ""
#: ../lib/puppet/util/ldap/manager.rb:230
msgid "Creating %{name} in ldap"
msgstr ""
#: ../lib/puppet/util/limits.rb:11
msgid "Failed to set process priority to '%{priority}'"
msgstr ""
#. TRANSLATORS "Log.close_all" is a method name and should not be translated
#: ../lib/puppet/util/log.rb:67
msgid "Log.close_all failed to close %{destinations}"
msgstr ""
#: ../lib/puppet/util/log.rb:86
msgid "Logs require a level"
msgstr ""
#: ../lib/puppet/util/log.rb:87 ../lib/puppet/util/log.rb:383 ../lib/puppet/util/windows/eventlog.rb:100
msgid "Invalid log level %{level}"
msgstr ""
#: ../lib/puppet/util/log.rb:111
msgid "Invalid loglevel %{level}"
msgstr ""
#: ../lib/puppet/util/log.rb:141
msgid "Unknown destination type %{dest}"
msgstr ""
#: ../lib/puppet/util/log.rb:181
msgid "Received a Log attribute with invalid encoding:%{log_message}"
msgstr ""
#: ../lib/puppet/util/log.rb:183
msgid ""
"Backtrace:\n"
"%{backtrace}"
msgstr ""
#: ../lib/puppet/util/log.rb:237
msgid "Reopening log files"
msgstr ""
#. TRANSLATORS 'Puppet::Util::Log' refers to a Puppet source code class
#: ../lib/puppet/util/log.rb:373
msgid "Puppet::Util::Log requires a message"
msgstr ""
#. TRANSLATORS 'Puppet::Util::Log' refers to a Puppet source code class
#: ../lib/puppet/util/log.rb:379
msgid "Puppet::Util::Log requires a log level"
msgstr ""
#. TRANSLATORS 'Puppet::Util::Log' refers to a Puppet source code class
#: ../lib/puppet/util/log.rb:381
msgid "Puppet::Util::Log requires a symbol or string"
msgstr ""
#: ../lib/puppet/util/log.rb:412
msgid "Could not parse for environment %{environment}: %{msg}"
msgstr ""
#: ../lib/puppet/util/log.rb:414
msgid "%{msg} on node %{node}"
msgstr ""
#: ../lib/puppet/util/log/destinations.rb:22
msgid "Invalid syslog facility %{str}"
msgstr ""
#: ../lib/puppet/util/log/destinations.rb:77
msgid "Creating log directory %{dir}"
msgstr ""
#: ../lib/puppet/util/logging.rb:80 ../lib/puppet/util/logging.rb:104
msgid "Wrapped exception:"
msgstr ""
#. TRANSLATORS the literals ":file", ":line", and ":key" should not be translated
#: ../lib/puppet/util/logging.rb:161
msgid "Need either :file and :line, or :key"
msgstr ""
#: ../lib/puppet/util/logging.rb:191
msgid "(file & line not available)"
msgstr ""
#: ../lib/puppet/util/logging.rb:271
msgid "(location: %{location})"
msgstr ""
#: ../lib/puppet/util/network_device.rb:11
msgid "Can't load %{provider} for %{device}: %{detail}"
msgstr ""
#: ../lib/puppet/util/network_device/config.rb:59
msgid "Duplicate device found at %{file_error_location}, already found at %{device_error_location}"
msgstr ""
#: ../lib/puppet/util/network_device/config.rb:72
msgid "Invalid entry at %{error_location}: %{file_text}"
msgstr ""
#: ../lib/puppet/util/network_device/config.rb:78
msgid "Configuration error: Cannot read %{file}; cannot serve"
msgstr ""
#: ../lib/puppet/util/network_device/config.rb:81
msgid "Configuration error: '%{file}' does not exit; cannot serve"
msgstr ""
#: ../lib/puppet/util/network_device/config.rb:95
msgid "%{value} is an invalid url"
msgstr ""
#: ../lib/puppet/util/package/version/rpm.rb:40
msgid "Cannot compare, as %{other} is not a Rpm Version"
msgstr ""
#: ../lib/puppet/util/plist.rb:49
msgid "Cannot read file %{file_path}; Puppet is skipping it."
msgstr ""
#: ../lib/puppet/util/plist.rb:50
msgid "Details: %{detail}"
msgstr ""
#: ../lib/puppet/util/plist.rb:152
msgid "Unable to write the file %{file_path}. %{error}"
msgstr ""
#: ../lib/puppet/util/posix.rb:30
msgid "Removing any duplicate group entries"
msgstr ""
#: ../lib/puppet/util/posix.rb:76
msgid "Did not get id from caller"
msgstr ""
#: ../lib/puppet/util/posix.rb:80 ../lib/puppet/util/posix.rb:105
msgid "Tried to get %{field} field for silly id %{id}"
msgstr ""
#: ../lib/puppet/util/posix.rb:133 ../lib/puppet/util/posix.rb:143 ../lib/puppet/util/posix.rb:153
msgid "Can only handle users and groups"
msgstr ""
#: ../lib/puppet/util/profiler/wall_clock.rb:16
msgid "took %{context} seconds"
msgstr ""
#: ../lib/puppet/util/provider_features.rb:64
msgid "Feature %{name} is already defined"
msgstr ""
#: ../lib/puppet/util/provider_features.rb:70
msgid "Could not create feature %{name}: %{detail}"
msgstr ""
#: ../lib/puppet/util/rdoc.rb:38 ../lib/puppet/util/rdoc.rb:44 ../lib/puppet/util/rdoc.rb:48 ../lib/puppet/util/rdoc.rb:52
msgid "RDOC SUPPORT FOR MANIFEST HAS BEEN REMOVED - See PUP-3638"
msgstr ""
#: ../lib/puppet/util/reference.rb:29
msgid "Could not find section %{name}"
msgstr ""
#: ../lib/puppet/util/reference.rb:35
msgid "creating pdf"
msgstr ""
#: ../lib/puppet/util/reference.rb:37
msgid "Could not find rst2latex"
msgstr ""
#: ../lib/puppet/util/reference.rb:47
msgid "rst2latex failed"
msgstr ""
#: ../lib/puppet/util/reference.rb:90
msgid "%{name} Reference"
msgstr ""
#: ../lib/puppet/util/reference.rb:112
msgid ""
"\n"
"\n"
"**This page is autogenerated; any changes will get overwritten**\n"
"\n"
msgstr ""
#: ../lib/puppet/util/resource_template.rb:48
msgid "Template %{file} does not exist"
msgstr ""
#: ../lib/puppet/util/retry_action.rb:32
msgid "%{retries} exceeded"
msgstr ""
#: ../lib/puppet/util/retry_action.rb:35
msgid "Caught exception %{klass}:%{error} retrying"
msgstr ""
#: ../lib/puppet/util/selinux.rb:82
msgid "Invalid context to parse: %{context}"
msgstr ""
#: ../lib/puppet/util/selinux.rb:94
msgid "Invalid SELinux parameter type"
msgstr ""
#: ../lib/puppet/util/selinux.rb:115
msgid "Can't set SELinux context on file unless the file already has some kind of context"
msgstr ""
#: ../lib/puppet/util/selinux.rb:129
msgid "set_selinux_context component must be one of :seluser, :selrole, :seltype, or :selrange"
msgstr ""
#: ../lib/puppet/util/selinux.rb:140
msgid "Failed to set SELinux context %{context} on %{file}"
msgstr ""
#: ../lib/puppet/util/selinux.rb:191
msgid "Could not open SELinux category translation file %{path}."
msgstr ""
#: ../lib/puppet/util/selinux.rb:277
msgid "got a relative path in SELinux find_fs: %{path}"
msgstr ""
#: ../lib/puppet/util/splayer.rb:15
msgid "Sleeping for %{time} seconds (splay is enabled)"
msgstr ""
#: ../lib/puppet/util/storage.rb:53
msgid "Checksumfile %{filename} is not a file, ignoring"
msgstr ""
#: ../lib/puppet/util/storage.rb:60
msgid "Checksumfile %{filename} is corrupt (%{detail}); replacing"
msgstr ""
#: ../lib/puppet/util/storage.rb:65
msgid "Could not rename corrupt %{filename}; remove manually"
msgstr ""
#: ../lib/puppet/util/storage.rb:71
msgid "State got corrupted"
msgstr ""
#: ../lib/puppet/util/storage.rb:83
msgid "Creating state file %{file}"
msgstr ""
#: ../lib/puppet/util/suidmanager.rb:102
msgid "No such group %{group}"
msgstr ""
#: ../lib/puppet/util/suidmanager.rb:118
msgid "No such user %{user}"
msgstr ""
#: ../lib/puppet/util/suidmanager.rb:146
msgid "Invalid id type %{type}"
msgstr ""
#: ../lib/puppet/util/suidmanager.rb:149
msgid "Invalid %{klass}: %{id}"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:50
msgid "An empty mode string is illegal"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:54
msgid "Numeric modes must be in octal, not decimal!"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:57
msgid "non-numeric current mode (%{mode})"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:77
msgid "Missing action"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:92
msgid "Missing operation (-, =, or +)"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:114
msgid "X only works with the '+' operator"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:125
msgid "internal error"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:129
msgid "Unknown operation"
msgstr ""
#: ../lib/puppet/util/symbolic_file_mode.rb:144
msgid "%{error}%{rest} in symbolic mode %{modification}"
msgstr ""
#: ../lib/puppet/util/tagging.rb:28
msgid "Invalid tag '%{name}'"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:37
msgid "ADSI connection error: %{e}"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:60
msgid "Failed to get computer name"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:98
msgid "Must use a valid SID::Principal"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:163
msgid "Value must be in DOMAIN\\%{object_class} style syntax"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:196
msgid "Could not resolve name: %{name}"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:238
msgid "Subclass must implement class-level method 'list_all'!"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:291
msgid "Puppet is not able to create/delete domain %{object_class} objects with the %{object_class} resource."
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:295
msgid "%{object_class} update failed: %{error}"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:321
msgid "Cannot create user if group '%{name}' exists."
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:461
msgid "Unrecognized ADS UserFlags: %{unrecognized_flags}"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:505 ../lib/puppet/util/windows/adsi.rb:538
msgid "Failed to get user name"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:588
msgid "Cannot delete user profile for '%{sid}' prior to Vista SP1"
msgstr ""
#: ../lib/puppet/util/windows/adsi.rb:606
msgid "Cannot create group if user '%{name}' exists."
msgstr ""
#: ../lib/puppet/util/windows/com.rb:18
msgid "%{name} failed (hresult %{result})."
msgstr ""
#: ../lib/puppet/util/windows/com.rb:144 ../lib/puppet/util/windows/com.rb:185
msgid "Failed to call %{klass}::%{name} with HRESULT: %{result}."
msgstr ""
#: ../lib/puppet/util/windows/com.rb:171
msgid "CoCreateInstance failed (%{klass})."
msgstr ""
#: ../lib/puppet/util/windows/error.rb:44
msgid "FormatMessageW could not format code %{code}"
msgstr ""
#: ../lib/puppet/util/windows/error.rb:50
msgid "FormatMessageW failed to allocate buffer for code %{code}"
msgstr ""
#. TRANSLATORS 'Windows' is the operating system and 'RegisterEventSourceW' is a API call and should not be translated
#: ../lib/puppet/util/windows/eventlog.rb:36
msgid "RegisterEventSourceW failed to open Windows eventlog"
msgstr ""
#: ../lib/puppet/util/windows/eventlog.rb:61
msgid "data must be a string, not %{class_name}"
msgstr ""
#. TRANSLATORS 'Windows' is the operating system and 'ReportEventW' is a API call and should not be translated
#: ../lib/puppet/util/windows/eventlog.rb:77
msgid "ReportEventW failed to report event to Windows eventlog"
msgstr ""
#. TRANSLATORS 'Win32' is the Windows API and should not be translated
#: ../lib/puppet/util/windows/eventlog.rb:119
msgid "(Win32 error: %{detail})"
msgstr ""
#: ../lib/puppet/util/windows/file.rb:118
msgid "Failed to set file attributes"
msgstr ""
#: ../lib/puppet/util/windows/file.rb:181
msgid "out_buffer is required"
msgstr ""
#: ../lib/puppet/util/windows/file.rb:254
msgid "Failed to call GetLongPathName"
msgstr ""
#: ../lib/puppet/util/windows/principal.rb:69 ../lib/puppet/util/windows/principal.rb:76
msgid "Failed to call LookupAccountNameW with account: %{account_name}"
msgstr ""
#. TRANSLATORS `lookup_account_sid` is a variable name and should not be translated
#: ../lib/puppet/util/windows/principal.rb:99
msgid "Byte array for lookup_account_sid must not be nil and must be at least 1 byte long"
msgstr ""
#: ../lib/puppet/util/windows/principal.rb:116
msgid "Byte array for lookup_account_sid is invalid: %{sid_bytes}"
msgstr ""
#: ../lib/puppet/util/windows/principal.rb:124 ../lib/puppet/util/windows/principal.rb:131
msgid "Failed to call LookupAccountSidW with bytes: %{sid_bytes}"
msgstr ""
#: ../lib/puppet/util/windows/process.rb:47
msgid "Failed to get child process exit code"
msgstr ""
#: ../lib/puppet/util/windows/process.rb:287
msgid "GetVersionEx failed"
msgstr ""
#: ../lib/puppet/util/windows/process.rb:316
msgid "Discarding environment variable %{string} which contains invalid bytes"
msgstr ""
#: ../lib/puppet/util/windows/process.rb:332
msgid "environment variable name must not be nil or empty"
msgstr ""
#: ../lib/puppet/util/windows/process.rb:337
msgid "Failed to remove environment variable: %{name}"
msgstr ""
#: ../lib/puppet/util/windows/process.rb:342
msgid "Failed to set environment variable: %{name}"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:22
msgid "Invalid registry key '%{name}'"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:32
msgid "Failed to open registry key '%{key}\\%{path}'"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:134
msgid "Failed to enumerate %{key} registry keys at index %{index}"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:168
msgid "Failed to enumerate %{key} registry values at index %{index}"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:198
msgid "Failed to query registry %{key} for sizes"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:234
msgid "Type mismatch (expect %{rtype} but %{type} present)"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:256
msgid "Type %{type} is not supported."
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:261
msgid "A value in the registry key %{parent_key_name}%{key} is corrupt or invalid"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:283
msgid "Failed to read registry value %{value} at %{key}"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:301
msgid "Failed to delete registry value %{name} at %{key}"
msgstr ""
#: ../lib/puppet/util/windows/registry.rb:316
msgid "Failed to delete registry key %{name} at %{key}"
msgstr ""
#: ../lib/puppet/util/windows/root_certs.rb:48
msgid "Failed to import root certificate: %{detail}"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:175
msgid "Failed to get volume information"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/util/windows/security.rb:341
msgid "Setting control rights for %{path} owner SYSTEM to less than Full Control rights. Setting SYSTEM rights to less than Full Control may have unintented consequences for operations on this file"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/util/windows/security.rb:344
msgid "%{path} owner and group both set to user SYSTEM, but group is not managed directly: SYSTEM user rights will be set to FullControl by group"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/util/windows/security.rb:347
msgid "An attempt to set mode %{mode} on item %{path} would result in the owner, SYSTEM, to have less than Full Control rights. This attempt has been corrected to Full Control"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/util/windows/security.rb:357
msgid "Setting control rights for %{path} group SYSTEM to less than Full Control rights. Setting SYSTEM rights to less than Full Control may have unintented consequences for operations on this file"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/util/windows/security.rb:360
msgid "%{path} owner and group both set to user SYSTEM, but owner is not managed directly: SYSTEM user rights will be set to FullControl by owner"
msgstr ""
#. TRANSLATORS 'SYSTEM' is a Windows name and should not be translated
#: ../lib/puppet/util/windows/security.rb:363
msgid "An attempt to set mode %{mode} on item %{path} would result in the group, SYSTEM, to have less than Full Control rights. This attempt has been corrected to Full Control"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:434 ../lib/puppet/util/windows/security.rb:451 ../lib/puppet/util/windows/sid.rb:162 ../lib/puppet/util/windows/sid.rb:224 ../lib/puppet/util/windows/user.rb:59
msgid "Invalid SID"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:438 ../lib/puppet/util/windows/security.rb:455
msgid "Failed to add access control entry"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:466 ../lib/puppet/util/windows/security.rb:648
msgid "Invalid DACL"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:489
msgid "Unsupported access control entry type: 0x%{type}"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:523
msgid "Failed to open '%{path}'"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:570
msgid "Failed to adjust process privileges"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:600
msgid "Failed to get security information"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:611
msgid "Failed to get security descriptor control"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:644
msgid "Failed to initialize ACL"
msgstr ""
#: ../lib/puppet/util/windows/security.rb:683
msgid "Failed to set security information"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:40
msgid "Starting the %{service_name} service. Timeout set to: %{timeout} seconds"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:50
msgid "Failed to start the service"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:54
msgid "Successfully started the %{service_name} service"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:63
msgid "Stopping the %{service_name} service. Timeout set to: %{timeout} seconds"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:71
msgid "Successfully stopped the %{service_name} service"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:80
msgid "Resuming the %{service_name} service. Timeout set to: %{timeout} seconds"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:96
msgid "Successfully resumed the %{service_name} service"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:112
msgid "Unknown Service state '%{current_state}' for '%{service_name}'"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:139
msgid "Unknown start type '%{start_type}' for '%{service_name}'"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:189
msgid "Failed to update service configuration"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:254
msgid "Failed to fetch services"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:303
msgid "Failed to open a handle to the service"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:320
msgid "Failed to open a handle to the service control manager"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:343
msgid "The service is already in the %{final_state} state. No further work needs to be done."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:355
msgid "The service must be in one of the %{valid_initial_states} states to perform this transition. It is currently in the %{current_state} state."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:366
msgid "There is already a pending transition to the %{final_state} state for the %{service_name} service."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:382
msgid "The service is in the %{pending_state} state, which is an unsafe pending state."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:387
msgid "Transitioning the %{service_name} service from %{initial_state} to %{final_state}"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:391
msgid "Waiting for the transition to finish"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:396
msgid "Failed to transition the %{service_name} service to the %{final_state} state. Detail: %{detail}"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:435 ../lib/puppet/util/windows/service.rb:471
msgid "Service query failed"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:514
msgid "Service query for %{parameter_name} failed"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:537
msgid "Failed to update service %{change} configuration"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:564
msgid "Failed to send the %{control_signal} signal to the service. Its current state is %{current_state}. Reason for failure:"
msgstr ""
#: ../lib/puppet/util/windows/service.rb:599
msgid "The service transitioned to the %{pending_state} state."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:613
msgid "Timed out while waiting for the service to transition from %{initial_state} to %{final_state} OR from %{initial_state} to %{pending_state} to %{final_state}. The service's current state is %{current_state}."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:628
msgid "Waiting for the pending transition to the %{final_state} state to finish."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:642
msgid "Unexpected transition to the %{current_state} state while waiting for the pending transition from %{pending_state} to %{final_state} to finish."
msgstr ""
#: ../lib/puppet/util/windows/service.rb:656
msgid "Timed out while waiting for the pending transition from %{pending_state} to %{final_state} to finish. The current state is %{current_state}."
msgstr ""
#: ../lib/puppet/util/windows/sid.rb:101
msgid "Octet string must be an array of bytes"
msgstr ""
#: ../lib/puppet/util/windows/sid.rb:168
msgid "Failed to convert binary SID"
msgstr ""
#: ../lib/puppet/util/windows/sid.rb:173
msgid "ConvertSidToStringSidW failed to allocate buffer for sid"
msgstr ""
#: ../lib/puppet/util/windows/sid.rb:193
msgid "Failed to convert string SID: %{string_sid}"
msgstr ""
#: ../lib/puppet/util/windows/user.rb:54
msgid "Failed to create administrators SID"
msgstr ""
#: ../lib/puppet/util/windows/user.rb:64
msgid "Failed to check membership"
msgstr ""
#: ../lib/puppet/util/windows/user.rb:104
msgid "Failed to logon user %{name}"
msgstr ""
#: ../lib/puppet/util/windows/user.rb:135
msgid "Failed to load user profile %{user}"
msgstr ""
#: ../lib/puppet/util/windows/user.rb:141
msgid "Failed to unload user profile %{user}"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:45
msgid "Failed to save CA certificates to '%{capath}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:59
msgid "The CA certificates are missing from '%{path}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:63
msgid "Failed to load CA certificates from '%{capath}'"
msgstr ""
#. TRANSLATORS 'PEM' is an acronym and shouldn't be translated
#: ../lib/puppet/x509/cert_provider.rb:75
msgid "Failed to parse CA certificates as PEM"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:91
msgid "Failed to save CRLs to '%{crlpath}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:105
msgid "The CRL is missing from '%{path}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:109
msgid "Failed to load CRLs from '%{crlpath}'"
msgstr ""
#. TRANSLATORS 'PEM' is an acronym and shouldn't be translated
#: ../lib/puppet/x509/cert_provider.rb:121
msgid "Failed to parse CRLs as PEM"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:193
msgid "Failed to save private key for '%{name}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:213
msgid "The private key is missing from '%{path}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:217
msgid "Failed to load private key for '%{name}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:260
msgid "Failed to save client certificate for '%{name}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:276
msgid "The client certificate is missing from '%{path}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:280
msgid "Failed to load client certificate for '%{name}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:336
msgid "Failed to save certificate request for '%{name}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:352
msgid "Failed to load certificate request for '%{name}'"
msgstr ""
#: ../lib/puppet/x509/cert_provider.rb:365
msgid "Failed to delete certificate request for '%{name}'"
msgstr ""
puppet-8.4.0/lib/ 0000755 0052762 0001160 00000000000 14552052637 013507 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet_x.rb 0000644 0052762 0001160 00000000772 14552052437 015704 0 ustar jenkins jenkins # frozen_string_literal: true
# The Puppet Extensions Module.
#
# Submodules of this module should be named after the publisher (e.g.
# 'user' part of a Puppet Module name). You should also add the module
# name to avoid further conflicts in the same namespace. So the
# structure should be
# `lib/puppet_x///`.
# A Puppet Extension for 'puppetlabs-powershell' would live at
# `lib/puppet_x/puppetlabs/powershell/`.
#
# @api public
#
module PuppetX
end
puppet-8.4.0/lib/puppet/ 0000755 0052762 0001160 00000000000 14552052637 015024 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/daemon.rb 0000644 0052762 0001160 00000011317 14552052437 016615 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../puppet/application'
require_relative '../puppet/scheduler'
# Run periodic actions in a daemonized process.
#
# A Daemon has 2 parts:
# * config reparse
# * an agent that responds to #run
#
# The config reparse will occur periodically based on Settings. The agent
# is run periodically and a time interval based on Settings. The config
# reparse will update this time interval when needed.
#
# The Daemon is also responsible for signal handling, starting, stopping,
# running the agent on demand, and reloading the entire process. It ensures
# that only one Daemon is running by using a lockfile.
#
# @api private
class Puppet::Daemon
SIGNAL_CHECK_INTERVAL = 5
attr_accessor :argv
attr_reader :signals, :agent
def initialize(agent, pidfile, scheduler = Puppet::Scheduler::Scheduler.new())
raise Puppet::DevError, _("Daemons must have an agent") unless agent
@scheduler = scheduler
@pidfile = pidfile
@agent = agent
@signals = []
end
def daemonname
Puppet.run_mode.name
end
# Put the daemon into the background.
def daemonize
pid = fork
if pid
Process.detach(pid)
exit(0)
end
create_pidfile
# Get rid of console logging
Puppet::Util::Log.close(:console)
Process.setsid
Dir.chdir("/")
close_streams
end
# Close stdin/stdout/stderr so that we can finish our transition into 'daemon' mode.
# @return nil
def self.close_streams()
Puppet.debug("Closing streams for daemon mode")
begin
$stdin.reopen "/dev/null"
$stdout.reopen "/dev/null", "a"
$stderr.reopen $stdout
Puppet::Util::Log.reopen
Puppet.debug("Finished closing streams for daemon mode")
rescue => detail
Puppet.err "Could not start #{Puppet.run_mode.name}: #{detail}"
Puppet::Util::replace_file("/tmp/daemonout", 0644) do |f|
f.puts "Could not start #{Puppet.run_mode.name}: #{detail}"
end
exit(12)
end
end
# Convenience signature for calling Puppet::Daemon.close_streams
def close_streams()
Puppet::Daemon.close_streams
end
def reexec
raise Puppet::DevError, _("Cannot reexec unless ARGV arguments are set") unless argv
command = $0 + " " + argv.join(" ")
Puppet.notice "Restarting with '#{command}'"
stop(:exit => false)
exec(command)
end
def reload
agent.run({:splay => false})
rescue Puppet::LockError
Puppet.notice "Not triggering already-running agent"
end
def restart
Puppet::Application.restart!
reexec
end
def reopen_logs
Puppet::Util::Log.reopen
end
# Trap a couple of the main signals. This should probably be handled
# in a way that anyone else can register callbacks for traps, but, eh.
def set_signal_traps
[:INT, :TERM].each do |signal|
Signal.trap(signal) do
Puppet.notice "Caught #{signal}; exiting"
stop
end
end
# extended signals not supported under windows
if !Puppet::Util::Platform.windows?
signals = {:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs }
signals.each do |signal, method|
Signal.trap(signal) do
Puppet.notice "Caught #{signal}; storing #{method}"
@signals << method
end
end
end
end
# Stop everything
def stop(args = {:exit => true})
Puppet::Application.stop!
remove_pidfile
Puppet::Util::Log.close_all
exit if args[:exit]
end
def start
create_pidfile
run_event_loop
end
private
# Create a pidfile for our daemon, so we can be stopped and others
# don't try to start.
def create_pidfile
raise "Could not create PID file: #{@pidfile.file_path}" unless @pidfile.lock
end
# Remove the pid file for our daemon.
def remove_pidfile
@pidfile.unlock
end
# Loop forever running events - or, at least, until we exit.
def run_event_loop
agent_run = Puppet::Scheduler.create_job(Puppet[:runinterval], Puppet[:splay], Puppet[:splaylimit]) do
# Splay for the daemon is handled in the scheduler
agent.run(:splay => false)
end
reparse_run = Puppet::Scheduler.create_job(Puppet[:filetimeout]) do
Puppet.settings.reparse_config_files
agent_run.run_interval = Puppet[:runinterval]
if Puppet[:filetimeout] == 0
reparse_run.disable
else
reparse_run.run_interval = Puppet[:filetimeout]
end
end
signal_loop = Puppet::Scheduler.create_job(SIGNAL_CHECK_INTERVAL) do
while method = @signals.shift # rubocop:disable Lint/AssignmentInCondition
Puppet.notice "Processing #{method}"
send(method)
end
end
reparse_run.disable if Puppet[:filetimeout] == 0
@scheduler.run_loop([reparse_run, agent_run, signal_loop])
end
end
puppet-8.4.0/lib/puppet/face/ 0000755 0052762 0001160 00000000000 14552052637 015722 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/face/module.rb 0000644 0052762 0001160 00000001304 14552052437 017530 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/module_tool'
require_relative '../../puppet/util/colors'
Puppet::Face.define(:module, '1.0.0') do
extend Puppet::Util::Colors
copyright "Puppet Inc.", 2012
license _("Apache 2 license; see COPYING")
summary _("Creates, installs and searches for modules on the Puppet Forge.")
description <<-EOT
This subcommand can find, install, and manage modules from the Puppet Forge,
a repository of user-contributed Puppet code. It can also generate empty
modules, and prepare locally developed modules for release on the Forge.
EOT
display_global_options "environment", "modulepath"
end
puppet-8.4.0/lib/puppet/face/plugin.rb 0000644 0052762 0001160 00000003763 14552052437 017554 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/configurer/plugin_handler'
Puppet::Face.define(:plugin, '0.0.1') do
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("Interact with the Puppet plugin system.")
description <<-'EOT'
This subcommand provides network access to the puppet master's store of
plugins.
The puppet master serves Ruby code collected from the `lib` directories
of its modules. These plugins can be used on agent nodes to extend
Facter and implement custom types and providers. Plugins are normally
downloaded by puppet agent during the course of a run.
EOT
action :download do
summary _("Download plugins from the puppet master.")
description <<-'EOT'
Downloads plugins from the configured puppet master. Any plugins
downloaded in this way will be used in all subsequent Puppet activity.
This action modifies files on disk.
EOT
returns _(<<-'EOT')
A list of the files downloaded, or a confirmation that no files were
downloaded. When used from the Ruby API, this action returns an array of
the files downloaded, which will be empty if none were retrieved.
EOT
examples <<-'EOT'
Retrieve plugins from the puppet master:
$ puppet plugin download
Retrieve plugins from the puppet master (API example):
$ Puppet::Face[:plugin, '0.0.1'].download
EOT
when_invoked do |_options|
remote_environment_for_plugins = Puppet::Node::Environment.remote(Puppet[:environment])
begin
handler = Puppet::Configurer::PluginHandler.new
handler.download_plugins(remote_environment_for_plugins)
ensure
Puppet.runtime[:http].close
end
end
when_rendering :console do |value|
if value.empty? then
_("No plugins downloaded.")
else
_("Downloaded these plugins: %{plugins}") % { plugins: value.join(', ') }
end
end
end
end
puppet-8.4.0/lib/puppet/face/help.rb 0000644 0052762 0001160 00000021134 14552052437 017176 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/application/face_base'
require_relative '../../puppet/util/constant_inflector'
require 'pathname'
require 'erb'
Puppet::Face.define(:help, '0.0.1') do
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("Display Puppet help.")
action(:help) do
summary _("Display help about Puppet subcommands and their actions.")
arguments _("[] []")
returns _("Short help text for the specified subcommand or action.")
examples _(<<-'EOT')
Get help for an action:
$ puppet help
EOT
option "--version " + _("VERSION") do
summary _("The version of the subcommand for which to show help.")
end
option "--ronn" do
summary _("Whether to render the help text in ronn format.")
default_to { false }
end
default
when_invoked do |*args|
options = args.pop
unless options[:ronn]
if default_case?(args) || help_for_help?(args)
return erb('global.erb').result(binding)
end
end
if args.length > 2
# TRANSLATORS 'puppet help' is a command line and should not be translated
raise ArgumentError, _("The 'puppet help' command takes two (optional) arguments: a subcommand and an action")
end
version = :current
if options.has_key? :version
if options[:version].to_s !~ /^current$/i
version = options[:version]
else
if args.length == 0
# TRANSLATORS '--version' is a command line option and should not be translated
raise ArgumentError, _("Supplying a '--version' only makes sense when a Faces subcommand is given")
end
end
end
facename, actionname = args
if legacy_applications.include? facename
if actionname
raise ArgumentError, _("The legacy subcommand '%{sub_command}' does not support supplying an action") % { sub_command: facename }
end
# legacy apps already emit ronn output
return render_application_help(facename)
else
if options[:ronn]
# Calling `puppet help --ronn` normally calls this action with
# as the first argument in the `args` array. However, if
# happens to match the name of an action, like `puppet help help
# --ronn`, then face_base "eats" the argument and `args` will be
# empty. Rather than force users to type `puppet help help help
# --ronn`, default the facename to `:help`
render_face_man(facename || :help)
else
render_face_help(facename, actionname, version)
end
end
end
end
def default_case?(args)
args.empty?
end
def help_for_help?(args)
args.length == 1 && args.first == 'help'
end
def render_face_man(facename)
# set 'face' as it's used in the erb processing.
face = Puppet::Face[facename.to_sym, :current]
# avoid unused variable warning
_face = face
erb('man.erb').result(binding)
end
def render_application_help(applicationname)
return Puppet::Application[applicationname].help
rescue StandardError, LoadError => detail
message = []
message << _('Could not load help for the application %{application_name}.') % { application_name: applicationname }
message << _('Please check the error logs for more information.')
message << ''
message << _('Detail: "%{detail}"') % { detail: detail.message }
fail ArgumentError, message.join("\n"), detail.backtrace
end
def render_face_help(facename, actionname, version)
face, action = load_face_help(facename, actionname, version)
return template_for(face, action).result(binding)
rescue StandardError, LoadError => detail
message = []
message << _('Could not load help for the face %{face_name}.') % { face_name: facename }
message << _('Please check the error logs for more information.')
message << ''
message << _('Detail: "%{detail}"') % { detail: detail.message }
fail ArgumentError, message.join("\n"), detail.backtrace
end
def load_face_help(facename, actionname, version)
face = Puppet::Face[facename.to_sym, version]
if actionname
action = face.get_action(actionname.to_sym)
if ! action
fail ArgumentError, _("Unable to load action %{actionname} from %{face}") % { actionname: actionname, face: face }
end
end
[face, action]
end
def template_for(face, action)
if action.nil?
erb('face.erb')
else
erb('action.erb')
end
end
def erb(name)
template = (Pathname(__FILE__).dirname + "help" + name)
erb = Puppet::Util.create_erb(template.read)
erb.filename = template.to_s
return erb
end
# Return a list of applications that are not simply just stubs for Faces.
def legacy_applications
Puppet::Application.available_application_names.reject do |appname|
(is_face_app?(appname)) or (exclude_from_docs?(appname))
end.sort
end
# Return a list of all applications (both legacy and Face applications), along with a summary
# of their functionality.
# @return [Array] An Array of Arrays. The outer array contains one entry per application; each
# element in the outer array is a pair whose first element is a String containing the application
# name, and whose second element is a String containing the summary for that application.
def all_application_summaries()
available_application_names_special_sort().inject([]) do |result, appname|
next result if exclude_from_docs?(appname)
if (appname == COMMON || appname == SPECIALIZED || appname == BLANK)
result << appname
elsif (is_face_app?(appname))
begin
face = Puppet::Face[appname, :current]
# Add deprecation message to summary if the face is deprecated
summary = face.deprecated? ? face.summary + ' ' + _("(Deprecated)") : face.summary
result << [appname, summary, ' ']
rescue StandardError, LoadError
error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname }
error_message += ' ' + _("Check error logs.")
result << [ error_message, '', ' ' ]
end
else
begin
summary = Puppet::Application[appname].summary
if summary.empty?
summary = horribly_extract_summary_from(appname)
end
result << [appname, summary, ' ']
rescue StandardError, LoadError
error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname }
error_message += ' ' + _("Check error logs.")
result << [ error_message, '', ' ' ]
end
end
end
end
COMMON = 'Common:'
SPECIALIZED = 'Specialized:'
BLANK = "\n"
def available_application_names_special_sort()
full_list = Puppet::Application.available_application_names
a_list = full_list & %w{apply agent config help lookup module resource}
a_list = a_list.sort
also_ran = full_list - a_list
also_ran = also_ran.sort
[[COMMON], a_list, [BLANK], [SPECIALIZED], also_ran].flatten(1)
end
def horribly_extract_summary_from(appname)
help = Puppet::Application[appname].help.split("\n")
# Now we find the line with our summary, extract it, and return it. This
# depends on the implementation coincidence of how our pages are
# formatted. If we can't match the pattern we expect we return the empty
# string to ensure we don't blow up in the summary. --daniel 2011-04-11
while line = help.shift do # rubocop:disable Lint/AssignmentInCondition
md = /^puppet-#{appname}\([^\)]+\) -- (.*)$/.match(line)
if md
return md[1]
end
end
return ''
end
# This should absolutely be a private method, but for some reason it appears
# that you can't use the 'private' keyword inside of a Face definition.
# See #14205.
# private :horribly_extract_summary_from
def exclude_from_docs?(appname)
%w{face_base indirection_base report status}.include? appname
end
# This should absolutely be a private method, but for some reason it appears
# that you can't use the 'private' keyword inside of a Face definition.
# See #14205.
# private :exclude_from_docs?
def is_face_app?(appname)
clazz = Puppet::Application.find(appname)
clazz.ancestors.include?(Puppet::Application::FaceBase)
end
# This should probably be a private method, but for some reason it appears
# that you can't use the 'private' keyword inside of a Face definition.
# See #14205.
# private :is_face_app?
end
puppet-8.4.0/lib/puppet/face/module/ 0000755 0052762 0001160 00000000000 14552052637 017207 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/face/module/list.rb 0000644 0052762 0001160 00000022732 14552052437 020513 0 ustar jenkins jenkins # encoding: UTF-8
# frozen_string_literal: true
Puppet::Face.define(:module, '1.0.0') do
action(:list) do
summary _("List installed modules")
description <<-HEREDOC
Lists the installed puppet modules. By default, this action scans the
modulepath from puppet.conf's `[main]` block; use the --modulepath
option to change which directories are scanned.
The output of this action includes information from the module's
metadata, including version numbers and unmet module dependencies.
HEREDOC
returns _("hash of paths to module objects")
option "--tree" do
summary _("Whether to show dependencies as a tree view")
end
examples <<-'EOT'
List installed modules:
$ puppet module list
/etc/puppetlabs/code/modules
├── bodepd-create_resources (v0.0.1)
├── puppetlabs-bacula (v0.0.2)
├── puppetlabs-mysql (v0.0.1)
├── puppetlabs-sqlite (v0.0.1)
└── puppetlabs-stdlib (v2.2.1)
/opt/puppetlabs/puppet/modules (no modules installed)
List installed modules in a tree view:
$ puppet module list --tree
/etc/puppetlabs/code/modules
└─┬ puppetlabs-bacula (v0.0.2)
├── puppetlabs-stdlib (v2.2.1)
├─┬ puppetlabs-mysql (v0.0.1)
│ └── bodepd-create_resources (v0.0.1)
└── puppetlabs-sqlite (v0.0.1)
/opt/puppetlabs/puppet/modules (no modules installed)
List installed modules from a specified environment:
$ puppet module list --environment production
/etc/puppetlabs/code/modules
├── bodepd-create_resources (v0.0.1)
├── puppetlabs-bacula (v0.0.2)
├── puppetlabs-mysql (v0.0.1)
├── puppetlabs-sqlite (v0.0.1)
└── puppetlabs-stdlib (v2.2.1)
/opt/puppetlabs/puppet/modules (no modules installed)
List installed modules from a specified modulepath:
$ puppet module list --modulepath /opt/puppetlabs/puppet/modules
/opt/puppetlabs/puppet/modules (no modules installed)
EOT
when_invoked do |options|
Puppet::ModuleTool.set_option_defaults(options)
environment = options[:environment_instance]
modules_by_path = environment.modules_by_path
{
:environment => environment,
:modules_by_path => modules_by_path,
:unmet_dependencies => unmet_dependencies(environment),
}
end
when_rendering :console do |result, options|
environment = result[:environment]
modules_by_path = result[:modules_by_path]
output = ''.dup
warn_unmet_dependencies(environment)
environment.modulepath.each do |path|
modules = modules_by_path[path]
no_mods = modules.empty? ? _(' (no modules installed)') : ''
output << "#{path}#{no_mods}\n"
if options[:tree]
# The modules with fewest things depending on them will be the
# parent of the tree. Can't assume to start with 0 dependencies
# since dependencies may be cyclical.
modules_by_num_requires = modules.sort_by {|m| m.required_by.size}
@seen = {}
tree = list_build_tree(modules_by_num_requires, [], nil,
:label_unmet => true, :path => path, :label_invalid => false)
else
tree = []
modules.sort_by { |mod| mod.forge_name or mod.name }.each do |mod|
tree << list_build_node(mod, path, :label_unmet => false,
:path => path, :label_invalid => true)
end
end
output << Puppet::ModuleTool.format_tree(tree)
end
output
end
end
def unmet_dependencies(environment)
error_types = [:non_semantic_version, :version_mismatch, :missing]
unmet_deps = {}
error_types.each do |type|
unmet_deps[type] = Hash.new do |hash, key|
hash[key] = { :errors => [], :parent => nil }
end
end
# Prepare the unmet dependencies for display on the console.
environment.modules.sort_by {|mod| mod.name}.each do |mod|
unmet_grouped = Hash.new { |h,k| h[k] = [] }
unmet_grouped = mod.unmet_dependencies.inject(unmet_grouped) do |acc, dep|
acc[dep[:reason]] << dep
acc
end
unmet_grouped.each do |type, deps|
unless deps.empty?
unmet_grouped[type].sort_by { |dep| dep[:name] }.each do |dep|
dep_name = dep[:name].tr('/', '-')
installed_version = dep[:mod_details][:installed_version]
version_constraint = dep[:version_constraint]
parent_name = dep[:parent][:name].tr('/', '-')
parent_version = dep[:parent][:version]
msg = _("'%{parent_name}' (%{parent_version}) requires '%{dependency_name}' (%{dependency_version})") % { parent_name: parent_name, parent_version: parent_version, dependency_name: dep_name, dependency_version: version_constraint }
unmet_deps[type][dep[:name]][:errors] << msg
unmet_deps[type][dep[:name]][:parent] = {
:name => dep[:parent][:name],
:version => parent_version
}
unmet_deps[type][dep[:name]][:version] = installed_version
end
end
end
end
unmet_deps
end
def warn_unmet_dependencies(environment)
@unmet_deps = unmet_dependencies(environment)
# Display unmet dependencies by category.
error_display_order = [:non_semantic_version, :version_mismatch, :missing]
error_display_order.each do |type|
unless @unmet_deps[type].empty?
@unmet_deps[type].keys.sort.each do |dep|
name = dep.tr('/', '-')
errors = @unmet_deps[type][dep][:errors]
version = @unmet_deps[type][dep][:version]
msg = case type
when :version_mismatch
_("Module '%{name}' (v%{version}) fails to meet some dependencies:\n") % { name: name, version: version }
when :non_semantic_version
_("Non semantic version dependency %{name} (v%{version}):\n") % { name: name, version: version }
else
_("Missing dependency '%{name}':\n") % { name: name }
end
errors.each { |error_string| msg << " #{error_string}\n" }
Puppet.warning msg.chomp
end
end
end
end
# Prepare a list of module objects and their dependencies for print in a
# tree view.
#
# Returns an Array of Hashes
#
# Example:
#
# [
# {
# :text => "puppetlabs-bacula (v0.0.2)",
# :dependencies=> [
# { :text => "puppetlabs-stdlib (v2.2.1)", :dependencies => [] },
# {
# :text => "puppetlabs-mysql (v1.0.0)"
# :dependencies => [
# {
# :text => "bodepd-create_resources (v0.0.1)",
# :dependencies => []
# }
# ]
# },
# { :text => "puppetlabs-sqlite (v0.0.1)", :dependencies => [] },
# ]
# }
# ]
#
# When the above data structure is passed to Puppet::ModuleTool.build_tree
# you end up with something like this:
#
# /etc/puppetlabs/code/modules
# └─┬ puppetlabs-bacula (v0.0.2)
# ├── puppetlabs-stdlib (v2.2.1)
# ├─┬ puppetlabs-mysql (v1.0.0)
# │ └── bodepd-create_resources (v0.0.1)
# └── puppetlabs-sqlite (v0.0.1)
#
def list_build_tree(list, ancestors=[], parent=nil, params={})
list.map do |mod|
next if @seen[(mod.forge_name or mod.name)]
node = list_build_node(mod, parent, params)
@seen[(mod.forge_name or mod.name)] = true
unless ancestors.include?(mod)
node[:dependencies] ||= []
missing_deps = mod.unmet_dependencies.select do |dep|
dep[:reason] == :missing
end
missing_deps.map do |mis_mod|
str = "#{colorize(:bg_red, _('UNMET DEPENDENCY'))} #{mis_mod[:name].tr('/', '-')} "
str << "(#{colorize(:cyan, mis_mod[:version_constraint])})"
node[:dependencies] << { :text => str }
end
node[:dependencies] += list_build_tree(mod.dependencies_as_modules,
ancestors + [mod], mod, params)
end
node
end.compact
end
# Prepare a module object for print in a tree view. Each node in the tree
# must be a Hash in the following format:
#
# { :text => "puppetlabs-mysql (v1.0.0)" }
#
# The value of a module's :text is affected by three (3) factors: the format
# of the tree, its dependency status, and the location in the modulepath
# relative to its parent.
#
# Returns a Hash
#
def list_build_node(mod, parent, params)
str = ''.dup
str << (mod.forge_name ? mod.forge_name.tr('/', '-') : mod.name)
str << ' (' + colorize(:cyan, mod.version ? "v#{mod.version}" : '???') + ')'
unless File.dirname(mod.path) == params[:path]
str << " [#{File.dirname(mod.path)}]"
end
if @unmet_deps[:version_mismatch].include?(mod.forge_name)
if params[:label_invalid]
str << ' ' + colorize(:red, _('invalid'))
elsif parent.respond_to?(:forge_name)
unmet_parent = @unmet_deps[:version_mismatch][mod.forge_name][:parent]
if (unmet_parent[:name] == parent.forge_name &&
unmet_parent[:version] == "v#{parent.version}")
str << ' ' + colorize(:red, _('invalid'))
end
end
end
{ :text => str }
end
end
puppet-8.4.0/lib/puppet/face/module/uninstall.rb 0000644 0052762 0001160 00000006453 14552052437 021553 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Face.define(:module, '1.0.0') do
action(:uninstall) do
summary _("Uninstall a puppet module.")
description <<-EOT
Uninstalls a puppet module from the modulepath (or a specific
target directory).
Note: Module uninstall uses MD5 checksums, which are prohibited on FIPS enabled systems.
EOT
returns _("Hash of module objects representing uninstalled modules and related errors.")
examples <<-'EOT'
Uninstall a module:
$ puppet module uninstall puppetlabs-ssh
Removed /etc/puppetlabs/code/modules/ssh (v1.0.0)
Uninstall a module from a specific directory:
$ puppet module uninstall puppetlabs-ssh --modulepath /opt/puppetlabs/puppet/modules
Removed /opt/puppetlabs/puppet/modules/ssh (v1.0.0)
Uninstall a module from a specific environment:
$ puppet module uninstall puppetlabs-ssh --environment development
Removed /etc/puppetlabs/code/environments/development/modules/ssh (v1.0.0)
Uninstall a specific version of a module:
$ puppet module uninstall puppetlabs-ssh --version 2.0.0
Removed /etc/puppetlabs/code/modules/ssh (v2.0.0)
EOT
arguments _("")
option "--force", "-f" do
summary _("Force uninstall of an installed module.")
description <<-EOT
Force the uninstall of an installed module even if there are local
changes or the possibility of causing broken dependencies.
EOT
end
option "--ignore-changes", "-c" do
summary _("Ignore any local changes made. (Implied by --force.)")
description <<-EOT
Uninstall an installed module even if there are local changes to it. (Implied by --force.)
EOT
end
option "--version=" do
summary _("The version of the module to uninstall")
description <<-EOT
The version of the module to uninstall. When using this option, a module
matching the specified version must be installed or else an error is raised.
EOT
end
when_invoked do |name, options|
name = name.tr('/', '-')
Puppet::ModuleTool.set_option_defaults options
message = if options[:version]
module_version = colorize(:cyan, options[:version].sub(/^(?=\d)/, 'v'))
_("Preparing to uninstall '%{name}' (%{module_version}) ...") % { name: name, module_version: module_version }
else
_("Preparing to uninstall '%{name}' ...") % { name: name }
end
Puppet.notice message
Puppet::ModuleTool::Applications::Uninstaller.run(name, options)
end
when_rendering :console do |return_value|
if return_value[:result] == :failure
Puppet.err(return_value[:error][:multiline])
exit 1
else
mod = return_value[:affected_modules].first
message = if mod.version
module_version = colorize(:cyan, mod.version.to_s.sub(/^(?=\d)/, 'v'))
_("Removed '%{name}' (%{module_version}) from %{path}") % { name: return_value[:module_name], module_version: module_version, path: mod.modulepath }
else
_("Removed '%{name}' from %{path}") % { name: return_value[:module_name], path: mod.modulepath }
end
message
end
end
end
end
puppet-8.4.0/lib/puppet/face/module/upgrade.rb 0000644 0052762 0001160 00000005401 14552052437 021161 0 ustar jenkins jenkins # encoding: UTF-8
# frozen_string_literal: true
Puppet::Face.define(:module, '1.0.0') do
action(:upgrade) do
summary _("Upgrade a puppet module.")
description <<-EOT
Upgrades a puppet module.
Note: Module upgrade uses MD5 checksums, which are prohibited on FIPS enabled systems.
EOT
returns "Hash"
examples <<-EOT
upgrade an installed module to the latest version
$ puppet module upgrade puppetlabs-apache
/etc/puppetlabs/puppet/modules
└── puppetlabs-apache (v1.0.0 -> v2.4.0)
upgrade an installed module to a specific version
$ puppet module upgrade puppetlabs-apache --version 2.1.0
/etc/puppetlabs/puppet/modules
└── puppetlabs-apache (v1.0.0 -> v2.1.0)
upgrade an installed module for a specific environment
$ puppet module upgrade puppetlabs-apache --environment test
/etc/puppetlabs/code/environments/test/modules
└── puppetlabs-apache (v1.0.0 -> v2.4.0)
EOT
arguments _("")
option "--force", "-f" do
summary _("Force upgrade of an installed module. (Implies --ignore-dependencies.)")
description <<-EOT
Force the upgrade of an installed module even if there are local
changes or the possibility of causing broken dependencies.
Implies --ignore-dependencies.
EOT
end
option "--ignore-dependencies" do
summary _("Do not attempt to install dependencies. (Implied by --force.)")
description <<-EOT
Do not attempt to install dependencies. Implied by --force.
EOT
end
option "--ignore-changes", "-c" do
summary _("Ignore and overwrite any local changes made. (Implied by --force.)")
description <<-EOT
Upgrade an installed module even if there are local changes to it. (Implied by --force.)
EOT
end
option "--version=" do
summary _("The version of the module to upgrade to.")
description <<-EOT
The version of the module to upgrade to.
EOT
end
when_invoked do |name, options|
name = name.tr('/', '-')
Puppet.notice _("Preparing to upgrade '%{name}' ...") % { name: name }
Puppet::ModuleTool.set_option_defaults options
Puppet::ModuleTool::Applications::Upgrader.new(name, options).run
end
when_rendering :console do |return_value|
if return_value[:result] == :noop
Puppet.notice return_value[:error][:multiline]
exit 0
elsif return_value[:result] == :failure
Puppet.err(return_value[:error][:multiline])
exit 1
else
tree = Puppet::ModuleTool.build_tree(return_value[:graph], return_value[:base_dir])
"#{return_value[:base_dir]}\n" +
Puppet::ModuleTool.format_tree(tree)
end
end
end
end
puppet-8.4.0/lib/puppet/face/module/install.rb 0000644 0052762 0001160 00000013155 14552052437 021205 0 ustar jenkins jenkins # encoding: UTF-8
# frozen_string_literal: true
require_relative '../../../puppet/forge'
require_relative '../../../puppet/module_tool/install_directory'
require 'pathname'
Puppet::Face.define(:module, '1.0.0') do
action(:install) do
summary _("Install a module from the Puppet Forge or a release archive.")
description <<-EOT
Installs a module from the Puppet Forge or from a release archive file.
Note: Module install uses MD5 checksums, which are prohibited on FIPS enabled systems.
The specified module will be installed into the directory
specified with the `--target-dir` option, which defaults to the first
directory in the modulepath.
EOT
returns _("Pathname object representing the path to the installed module.")
examples <<-'EOT'
Install a module:
$ puppet module install puppetlabs-vcsrepo
Preparing to install into /etc/puppetlabs/code/modules ...
Downloading from https://forgeapi.puppet.com ...
Installing -- do not interrupt ...
/etc/puppetlabs/code/modules
└── puppetlabs-vcsrepo (v0.0.4)
Install a module to a specific environment:
$ puppet module install puppetlabs-vcsrepo --environment development
Preparing to install into /etc/puppetlabs/code/environments/development/modules ...
Downloading from https://forgeapi.puppet.com ...
Installing -- do not interrupt ...
/etc/puppetlabs/code/environments/development/modules
└── puppetlabs-vcsrepo (v0.0.4)
Install a specific module version:
$ puppet module install puppetlabs-vcsrepo -v 0.0.4
Preparing to install into /etc/puppetlabs/modules ...
Downloading from https://forgeapi.puppet.com ...
Installing -- do not interrupt ...
/etc/puppetlabs/code/modules
└── puppetlabs-vcsrepo (v0.0.4)
Install a module into a specific directory:
$ puppet module install puppetlabs-vcsrepo --target-dir=/opt/puppetlabs/puppet/modules
Preparing to install into /opt/puppetlabs/puppet/modules ...
Downloading from https://forgeapi.puppet.com ...
Installing -- do not interrupt ...
/opt/puppetlabs/puppet/modules
└── puppetlabs-vcsrepo (v0.0.4)
Install a module into a specific directory and check for dependencies in other directories:
$ puppet module install puppetlabs-vcsrepo --target-dir=/opt/puppetlabs/puppet/modules --modulepath /etc/puppetlabs/code/modules
Preparing to install into /opt/puppetlabs/puppet/modules ...
Downloading from https://forgeapi.puppet.com ...
Installing -- do not interrupt ...
/opt/puppetlabs/puppet/modules
└── puppetlabs-vcsrepo (v0.0.4)
Install a module from a release archive:
$ puppet module install puppetlabs-vcsrepo-0.0.4.tar.gz
Preparing to install into /etc/puppetlabs/code/modules ...
Downloading from https://forgeapi.puppet.com ...
Installing -- do not interrupt ...
/etc/puppetlabs/code/modules
└── puppetlabs-vcsrepo (v0.0.4)
Install a module from a release archive and ignore dependencies:
$ puppet module install puppetlabs-vcsrepo-0.0.4.tar.gz --ignore-dependencies
Preparing to install into /etc/puppetlabs/code/modules ...
Installing -- do not interrupt ...
/etc/puppetlabs/code/modules
└── puppetlabs-vcsrepo (v0.0.4)
EOT
arguments _("")
option "--force", "-f" do
summary _("Force overwrite of existing module, if any. (Implies --ignore-dependencies.)")
description <<-EOT
Force overwrite of existing module, if any.
Implies --ignore-dependencies.
EOT
end
option "--target-dir DIR", "-i DIR" do
summary _("The directory into which modules are installed.")
description <<-EOT
The directory into which modules are installed; defaults to the first
directory in the modulepath.
Specifying this option will change the installation directory, and
will use the existing modulepath when checking for dependencies. If
you wish to check a different set of directories for dependencies, you
must also use the `--environment` or `--modulepath` options.
EOT
end
option "--ignore-dependencies" do
summary _("Do not attempt to install dependencies. (Implied by --force.)")
description <<-EOT
Do not attempt to install dependencies. Implied by --force.
EOT
end
option "--version VER", "-v VER" do
summary _("Module version to install.")
description <<-EOT
Module version to install; can be an exact version or a requirement string,
eg '>= 1.0.3'. Defaults to latest version.
EOT
end
when_invoked do |name, options|
Puppet::ModuleTool.set_option_defaults options
Puppet.notice _("Preparing to install into %{dir} ...") % { dir: options[:target_dir] }
install_dir = Puppet::ModuleTool::InstallDirectory.new(Pathname.new(options[:target_dir]))
Puppet::ModuleTool::Applications::Installer.run(name, install_dir, options)
end
when_rendering :console do |return_value, name, _options|
if return_value[:result] == :noop
Puppet.notice _("Module %{name} %{version} is already installed.") % { name: name, version: return_value[:version] }
exit 0
elsif return_value[:result] == :failure
Puppet.err(return_value[:error][:multiline])
exit 1
else
tree = Puppet::ModuleTool.build_tree(return_value[:graph], return_value[:install_dir])
"#{return_value[:install_dir]}\n" +
Puppet::ModuleTool.format_tree(tree)
end
end
end
end
puppet-8.4.0/lib/puppet/face/module/changes.rb 0000644 0052762 0001160 00000002644 14552052437 021150 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Face.define(:module, '1.0.0') do
action(:changes) do
summary _("Show modified files of an installed module.")
description <<-EOT
Shows any files in a module that have been modified since it was
installed. This action compares the files on disk to the md5 checksums
included in the module's checksums.json or, if that is missing, in
metadata.json.
EOT
returns _("Array of strings representing paths of modified files.")
examples <<-EOT
Show modified files of an installed module:
$ puppet module changes /etc/puppetlabs/code/modules/vcsrepo/
warning: 1 files modified
lib/puppet/provider/vcsrepo.rb
EOT
arguments _("")
when_invoked do |path, options|
Puppet::ModuleTool.set_option_defaults options
root_path = Puppet::ModuleTool.find_module_root(path)
unless root_path
raise ArgumentError, _("Could not find a valid module at %{path}") % { path: path.inspect }
end
Puppet::ModuleTool::Applications::Checksummer.run(root_path, options)
end
when_rendering :console do |return_value|
if return_value.empty?
Puppet.notice _("No modified files")
else
Puppet.warning _("%{count} files modified") % { count: return_value.size }
end
return_value.map do |changed_file|
"#{changed_file}"
end.join("\n")
end
end
end
puppet-8.4.0/lib/puppet/face/facts.rb 0000644 0052762 0001160 00000012320 14552052437 017343 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/indirector/face'
require_relative '../../puppet/node/facts'
Puppet::Indirector::Face.define(:facts, '0.0.1') do
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("Retrieve and store facts.")
description <<-'EOT'
This subcommand manages facts, which are collections of normalized system
information used by Puppet. It can read facts directly from the local system
(with the default `facter` terminus).
EOT
find = get_action(:find)
find.summary _("Retrieve a node's facts.")
find.arguments _("[]")
find.returns <<-'EOT'
A hash containing some metadata and (under the "values" key) the set
of facts for the requested node. When used from the Ruby API: A
Puppet::Node::Facts object.
RENDERING ISSUES: Facts cannot currently be rendered as a string; use yaml
or json.
EOT
find.notes <<-'EOT'
When using the `facter` terminus, the host argument is ignored.
EOT
find.examples <<-'EOT'
Get facts from the local system:
$ puppet facts find
EOT
deactivate_action(:destroy)
deactivate_action(:search)
action(:upload) do
summary _("Upload local facts to the puppet master.")
description <<-'EOT'
Reads facts from the local system using the `facter` terminus, then
saves the returned facts using the rest terminus.
EOT
returns "Nothing."
notes <<-'EOT'
This action requires that the Puppet Server's `auth.conf` file
allow `PUT` or `save` access to the `/puppet/v3/facts` API endpoint.
For details on configuring Puppet Server's `auth.conf`, see:
EOT
examples <<-'EOT'
Upload facts:
$ puppet facts upload
EOT
render_as :json
when_invoked do |_options|
# Use `agent` sections settings for certificates, Puppet Server URL,
# etc. instead of `user` section settings.
Puppet.settings.preferred_run_mode = :agent
Puppet::Node::Facts.indirection.terminus_class = :facter
facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
unless Puppet[:node_name_fact].empty?
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
facts.name = Puppet[:node_name_value]
end
client = Puppet.runtime[:http]
session = client.create_session
puppet = session.route_to(:puppet)
Puppet.notice(_("Uploading facts for '%{node}' to '%{server}'") % {
node: Puppet[:node_name_value],
server: puppet.url.hostname})
puppet.put_facts(Puppet[:node_name_value], facts: facts, environment: Puppet.lookup(:current_environment).name.to_s)
nil
end
end
action(:show) do
summary _("Retrieve current node's facts.")
arguments _("[]")
description <<-'EOT'
Reads facts from the local system using `facter` terminus.
A query can be provided to retrieve just a specific fact or a set of facts.
EOT
returns "The output of facter with added puppet specific facts."
notes <<-'EOT'
EOT
examples <<-'EOT'
retrieve facts:
$ puppet facts show os
EOT
default true
option("--config-file " + _("")) do
default_to { nil }
summary _("The location of the config file for Facter.")
end
option("--custom-dir " + _("")) do
default_to { nil }
summary _("The path to a directory that contains custom facts.")
end
option("--external-dir " + _("")) do
default_to { nil }
summary _("The path to a directory that contains external facts.")
end
option("--no-block") do
summary _("Disable fact blocking mechanism.")
end
option("--no-cache") do
summary _("Disable fact caching mechanism.")
end
option("--show-legacy") do
summary _("Show legacy facts when querying all facts.")
end
option("--value-only") do
summary _("Show only the value when the action is called with a single query")
end
option("--timing") do
summary _("Show how much time it took to resolve each fact.")
end
when_invoked do |*args|
options = args.pop
Puppet.settings.preferred_run_mode = :agent
Puppet::Node::Facts.indirection.terminus_class = :facter
if options[:value_only] && !args.count.eql?(1)
options[:value_only] = nil
Puppet.warning("Incorrect use of --value-only argument; it can only be used when querying for a single fact!")
end
options[:user_query] = args
options[:resolve_options] = true
result = Puppet::Node::Facts.indirection.find(Puppet.settings[:certname], options)
if options[:value_only]
result.values.values.first
else
result.values
end
end
when_rendering :console do |result|
# VALID_TYPES = [Integer, Float, TrueClass, FalseClass, NilClass, Symbol, String, Array, Hash].freeze
# from https://github.com/puppetlabs/facter/blob/4.0.49/lib/facter/custom_facts/util/normalization.rb#L8
case result
when Array, Hash
Puppet::Util::Json.dump(result, :pretty => true)
else # one of VALID_TYPES above
result
end
end
end
end
puppet-8.4.0/lib/puppet/face/node/ 0000755 0052762 0001160 00000000000 14552052637 016647 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/face/node/clean.rb 0000644 0052762 0001160 00000006506 14552052437 020263 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Face.define(:node, '0.0.1') do
action(:clean) do
summary _("Clean up signed certs, cached facts, node objects, and reports for a node stored by the puppetmaster")
arguments _(" [ ...]")
description <<-'EOT'
Cleans up the following information a puppet master knows about a node:
- ($vardir/ssl/ca/signed/node.domain.pem)
- ($vardir/yaml/facts/node.domain.yaml)
- ($vardir/yaml/node/node.domain.yaml)
- ($vardir/reports/node.domain)
NOTE: this action now cleans up certs via Puppet Server's CA API. A running server is required for certs to be cleaned.
EOT
when_invoked do |*args|
nodes = args[0..-2]
options = args.last
raise _("At least one node should be passed") if nodes.empty? || nodes == options
# This seems really bad; run_mode should be set as part of a class
# definition, and should not be modifiable beyond that. This is one of
# the only places left in the code that tries to manipulate it. Other
# parts of code that handle certificates behave differently if the
# run_mode is server. Those other behaviors are needed for cleaning the
# certificates correctly.
Puppet.settings.preferred_run_mode = "server"
Puppet::Node::Facts.indirection.terminus_class = :yaml
Puppet::Node::Facts.indirection.cache_class = :yaml
Puppet::Node.indirection.terminus_class = :yaml
Puppet::Node.indirection.cache_class = :yaml
nodes.each { |node| cleanup(node.downcase) }
end
end
def cleanup(node)
clean_cert(node)
clean_cached_facts(node)
clean_cached_node(node)
clean_reports(node)
end
class LoggerIO
def debug(message)
Puppet.debug(message)
end
def warn(message)
Puppet.warning(message) unless message =~ /cadir is currently configured to be inside/
end
def err(message)
Puppet.err(message) unless message =~ /^\s*Error:\s*/
end
def inform(message)
Puppet.notice(message)
end
end
# clean signed cert for +host+
def clean_cert(node)
if Puppet.features.puppetserver_ca?
Puppetserver::Ca::Action::Clean.new(LoggerIO.new).run({ 'certnames' => [node] })
else
Puppet.info _("Not managing %{node} certs as this host is not a CA") % { node: node }
end
end
# clean facts for +host+
def clean_cached_facts(node)
Puppet::Node::Facts.indirection.destroy(node)
Puppet.info _("%{node}'s facts removed") % { node: node }
end
# clean cached node +host+
def clean_cached_node(node)
Puppet::Node.indirection.destroy(node)
Puppet.info _("%{node}'s cached node removed") % { node: node }
end
# clean node reports for +host+
def clean_reports(node)
Puppet::Transaction::Report.indirection.destroy(node)
Puppet.info _("%{node}'s reports removed") % { node: node }
end
def environment
@environment ||= Puppet.lookup(:current_environment)
end
def type_is_ensurable(resource)
if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure)
return true
else
type = environment.known_resource_types.find_definition(resource.restype)
return true if type && type.arguments.keys.include?('ensure')
end
return false
end
end
puppet-8.4.0/lib/puppet/face/catalog/ 0000755 0052762 0001160 00000000000 14552052637 017334 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/face/catalog/select.rb 0000644 0052762 0001160 00000003407 14552052437 021142 0 ustar jenkins jenkins # frozen_string_literal: true
# Select and show a list of resources of a given type.
Puppet::Face.define(:catalog, '0.0.1') do
action :select do
summary _("Retrieve a catalog and filter it for resources of a given type.")
arguments _("")
returns _(<<-'EOT')
A list of resource references ("Type[title]"). When used from the API,
returns an array of Puppet::Resource objects excised from a catalog.
EOT
description <<-'EOT'
Retrieves a catalog for the specified host, then searches it for all
resources of the requested type.
EOT
notes <<-'NOTES'
By default, this action will retrieve a catalog from Puppet's compiler
subsystem; you must call the action with `--terminus rest` if you wish
to retrieve a catalog from the puppet master.
FORMATTING ISSUES: This action cannot currently render useful yaml;
instead, it returns an entire catalog. Use json instead.
NOTES
examples <<-'EOT'
Ask the puppet master for a list of managed file resources for a node:
$ puppet catalog select --terminus rest somenode.magpie.lan file
EOT
when_invoked do |host, type, _options|
# REVISIT: Eventually, type should have a default value that triggers
# the non-specific behaviour. For now, though, this will do.
# --daniel 2011-05-03
catalog = Puppet::Resource::Catalog.indirection.find(host)
if type == '*'
catalog.resources
else
type = type.downcase
catalog.resources.reject { |res| res.type.downcase != type }
end
end
when_rendering :console do |value|
if value.nil? then
_("no matching resources found")
else
value.map {|x| x.to_s }.join("\n")
end
end
end
end
puppet-8.4.0/lib/puppet/face/generate.rb 0000644 0052762 0001160 00000004460 14552052437 020043 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/generate/type'
# Create the Generate face
Puppet::Face.define(:generate, '0.1.0') do
copyright 'Puppet Inc.', 2016
license _('Apache 2 license; see COPYING')
summary _('Generates Puppet code from Ruby definitions.')
action(:types) do
summary _('Generates Puppet code for custom types')
description <<-'EOT'
Generates definitions for custom resource types using Puppet code.
Types defined in Puppet code can be used to isolate custom type definitions
between different environments.
EOT
examples <<-'EOT'
Generate Puppet type definitions for all custom resource types in the current environment:
$ puppet generate types
Generate Puppet type definitions for all custom resource types in the specified environment:
$ puppet generate types --environment development
EOT
option '--format ' + _('') do
summary _('The generation output format to use. Supported formats: pcore.')
default_to { 'pcore' }
before_action do |_, _, options|
raise ArgumentError, _("'%{format}' is not a supported format for type generation.") % { format: options[:format] } unless ['pcore'].include?(options[:format])
end
end
option '--force' do
summary _('Forces the generation of output files (skips up-to-date checks).')
default_to { false }
end
when_invoked do |options|
generator = Puppet::Generate::Type
inputs = generator.find_inputs(options[:format].to_sym)
environment = Puppet.lookup(:current_environment)
# get the common output directory (in /.resource_types) - create it if it does not exists
# error if it exists and is not a directory
#
path_to_env = environment.configuration.path_to_env
outputdir = File.join(path_to_env, '.resource_types')
if Puppet::FileSystem.exist?(outputdir) && !Puppet::FileSystem.directory?(outputdir)
raise ArgumentError, _("The output directory '%{outputdir}' exists and is not a directory") % { outputdir: outputdir }
end
Puppet::FileSystem::mkpath(outputdir)
generator.generate(inputs, outputdir, options[:force])
exit(1) if generator.bad_input?
nil
end
end
end
puppet-8.4.0/lib/puppet/face/catalog.rb 0000644 0052762 0001160 00000012151 14552052437 017657 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/indirector/face'
Puppet::Indirector::Face.define(:catalog, '0.0.1') do
copyright "Puppet Inc.", 2011
license "Apache 2 license; see COPYING"
summary _("Compile, save, view, and convert catalogs.")
description <<-'EOT'
This subcommand deals with catalogs, which are compiled per-node artifacts
generated from a set of Puppet manifests. By default, it interacts with the
compiling subsystem and compiles a catalog using the default manifest and
`certname`, but you can change the source of the catalog with the
`--terminus` option. You can also choose to print any catalog in 'dot'
format (for easy graph viewing with OmniGraffle or Graphviz) with
'--render-as dot'.
EOT
short_description <<-'EOT'
This subcommand deals with catalogs, which are compiled per-node artifacts
generated from a set of Puppet manifests. By default, it interacts with the
compiling subsystem and compiles a catalog using the default manifest and
`certname`; use the `--terminus` option to change the source of the catalog.
EOT
deactivate_action(:destroy)
deactivate_action(:search)
find = get_action(:find)
find.summary "Retrieve the catalog for the node from which the command is run."
find.arguments ""
find.returns <<-'EOT'
A serialized catalog. When used from the Ruby API, returns a
Puppet::Resource::Catalog object.
EOT
action(:apply) do
summary "Find and apply a catalog."
description <<-'EOT'
Finds and applies a catalog. This action takes no arguments, but
the source of the catalog can be managed with the `--terminus` option.
EOT
returns <<-'EOT'
Nothing. When used from the Ruby API, returns a
Puppet::Transaction::Report object.
EOT
examples <<-'EOT'
Apply the locally cached catalog:
$ puppet catalog apply --terminus yaml
Retrieve a catalog from the master and apply it, in one step:
$ puppet catalog apply --terminus rest
API example:
# ...
Puppet::Face[:catalog, '0.0.1'].download
# (Termini are singletons; catalog.download has a side effect of
# setting the catalog terminus to yaml)
report = Puppet::Face[:catalog, '0.0.1'].apply
# ...
EOT
when_invoked do |_options|
catalog = Puppet::Face[:catalog, "0.0.1"].find(Puppet[:certname]) or raise "Could not find catalog for #{Puppet[:certname]}"
catalog = catalog.to_ral
report = Puppet::Transaction::Report.new
report.configuration_version = catalog.version
report.environment = Puppet[:environment]
Puppet::Util::Log.newdestination(report)
begin
benchmark(:notice, "Finished catalog run in %{seconds} seconds") do
catalog.apply(:report => report)
end
rescue => detail
Puppet.log_exception(detail, "Failed to apply catalog: #{detail}")
end
report.finalize_report
report
end
end
action(:compile) do
summary _("Compile a catalog.")
description <<-'EOT'
Compiles a catalog locally for a node, requiring access to modules, node classifier, etc.
EOT
examples <<-'EOT'
Compile catalog for node 'mynode':
$ puppet catalog compile mynode --codedir ...
EOT
returns <<-'EOT'
A serialized catalog.
EOT
when_invoked do |*args|
Puppet.settings.preferred_run_mode = :server
Puppet::Face[:catalog, :current].find(*args)
end
end
action(:download) do
summary "Download this node's catalog from the puppet master server."
description <<-'EOT'
Retrieves a catalog from the puppet master and saves it to the local yaml
cache. This action always contacts the puppet master and will ignore
alternate termini.
The saved catalog can be used in any subsequent catalog action by specifying
'--terminus yaml' for that action.
EOT
returns "Nothing."
notes <<-'EOT'
When used from the Ruby API, this action has a side effect of leaving
Puppet::Resource::Catalog.indirection.terminus_class set to yaml. The
terminus must be explicitly re-set for subsequent catalog actions.
EOT
examples <<-'EOT'
Retrieve and store a catalog:
$ puppet catalog download
API example:
Puppet::Face[:plugin, '0.0.1'].download
Puppet::Face[:facts, '0.0.1'].upload
Puppet::Face[:catalog, '0.0.1'].download
# ...
EOT
when_invoked do |_options|
Puppet::Resource::Catalog.indirection.terminus_class = :rest
Puppet::Resource::Catalog.indirection.cache_class = nil
catalog = nil
retrieval_duration = thinmark do
catalog = Puppet::Face[:catalog, '0.0.1'].find(Puppet[:certname])
end
catalog.retrieval_duration = retrieval_duration
catalog.write_class_file
Puppet::Resource::Catalog.indirection.terminus_class = :yaml
Puppet::Face[:catalog, "0.0.1"].save(catalog)
Puppet.notice "Saved catalog for #{Puppet[:certname]} to #{Puppet::Resource::Catalog.indirection.terminus.path(Puppet[:certname])}"
nil
end
end
end
puppet-8.4.0/lib/puppet/face/config.rb 0000644 0052762 0001160 00000024543 14552052437 017522 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/settings/ini_file'
Puppet::Face.define(:config, '0.0.1') do
extend Puppet::Util::Colors
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("Interact with Puppet's settings.")
description "This subcommand can inspect and modify settings from Puppet's
'puppet.conf' configuration file. For documentation about individual settings,
see https://puppet.com/docs/puppet/latest/configuration.html."
DEFAULT_SECTION_MARKER = Object.new
DEFAULT_SECTION = "main"
option "--section " + _("SECTION_NAME") do
default_to { DEFAULT_SECTION_MARKER } # Sentinel object for default detection during commands
summary _("The section of the configuration file to interact with.")
description <<-EOT
The section of the puppet.conf configuration file to interact with.
The three most commonly used sections are 'main', 'server', and 'agent'.
'Main' is the default, and is used by all Puppet applications. Other
sections can override 'main' values for specific applications --- the
'server' section affects Puppet Server, and the 'agent'
section affects puppet agent.
Less commonly used is the 'user' section, which affects puppet apply. Any
other section will be treated as the name of a legacy environment
(a deprecated feature), and can only include the 'manifest' and
'modulepath' settings.
EOT
end
action(:print) do
summary _("Examine Puppet's current settings.")
arguments _("all | [ ...]")
description <<-'EOT'
Prints the value of a single setting or a list of settings.
This action is a replacement interface to the information available with
`puppet --configprint`.
EOT
notes <<-'EOT'
By default, this action reads the general configuration in the 'main'
section. Use the '--section' and '--environment' flags to examine other
configuration domains.
EOT
examples <<-'EOT'
Get puppet's runfile directory:
$ puppet config print rundir
Get a list of important directories from the server's config:
$ puppet config print all --section server | grep -E "(path|dir)"
EOT
when_invoked do |*args|
options = args.pop
@default_section = false
if options[:section] == DEFAULT_SECTION_MARKER
options[:section] = DEFAULT_SECTION
@default_section = true
end
if Puppet::Util::Log.sendlevel?(:info)
warn_default_section(options[:section]) if @default_section
report_section_and_environment(options[:section], Puppet.settings[:environment])
end
names = if args.empty? || args == ['all']
:all
else
args
end
Puppet.settings.stringify_settings(options[:section], names)
end
when_rendering :console do |to_be_rendered|
output = ''.dup
if to_be_rendered.keys.length > 1
to_be_rendered.keys.sort.each do |setting|
output << "#{setting} = #{to_be_rendered[setting]}\n"
end
else
output << "#{to_be_rendered.to_a[0].last}\n"
end
output
end
end
def warn_default_section(section_name)
messages = []
messages << _("No section specified; defaulting to '%{section_name}'.") %
{ section_name: section_name }
# TRANSLATORS '--section' is a command line option and should not be translated
messages << _("Set the config section by using the `--section` flag.")
# TRANSLATORS `puppet config --section user print foo` is a command line example and should not be translated
messages << _("For example, `puppet config --section user print foo`.")
messages << _("For more information, see https://puppet.com/docs/puppet/latest/configuration.html")
Puppet.warning(messages.join("\n"))
end
def report_section_and_environment(section_name, environment_name)
$stderr.puts colorize(:hyellow,
_("Resolving settings from section '%{section_name}' in environment '%{environment_name}'") %
{ section_name: section_name, environment_name: environment_name })
end
action(:set) do
summary _("Set Puppet's settings.")
arguments _("[setting_name] [setting_value]")
description <<-'EOT'
Updates values in the `puppet.conf` configuration file.
EOT
notes <<-'EOT'
By default, this action manipulates the configuration in the
'main' section. Use the '--section' flag to manipulate other
configuration domains.
EOT
examples <<-'EOT'
Set puppet's runfile directory:
$ puppet config set rundir /var/run/puppetlabs
Set the vardir for only the agent:
$ puppet config set vardir /opt/puppetlabs/puppet/cache --section agent
EOT
when_invoked do |name, value, options|
@default_section = false
if options[:section] == DEFAULT_SECTION_MARKER
options[:section] = DEFAULT_SECTION
@default_section = true
end
if name == 'environment' && options[:section] == 'main'
Puppet.warning _(<<~EOM).chomp
The environment should be set in either the `[user]`, `[agent]`, or `[server]`
section. Variables set in the `[agent]` section are used when running
`puppet agent`. Variables set in the `[user]` section are used when running
various other puppet subcommands, like `puppet apply` and `puppet module`; these
require the defined environment directory to exist locally. Set the config
section by using the `--section` flag. For example,
`puppet config --section user set environment foo`. For more information, see
https://puppet.com/docs/puppet/latest/configuration.html#environment
EOM
end
if Puppet::Util::Log.sendlevel?(:info)
report_section_and_environment(options[:section], Puppet.settings[:environment])
end
# only validate settings we recognize
setting = Puppet.settings.setting(name.to_sym)
if setting
# set the value, which will call `on_*_and_write` hooks, if any
Puppet.settings[setting.name] = value
# read the value to trigger interpolation and munge validation logic
Puppet.settings[setting.name]
end
path = Puppet::FileSystem.pathname(Puppet.settings.which_configuration_file)
Puppet::FileSystem.touch(path)
Puppet::FileSystem.open(path, nil, 'r+:UTF-8') do |file|
Puppet::Settings::IniFile.update(file) do |config|
if options[:section] == "master"
# delete requested master section if it exists,
# as server section should be used
setting_string = config.delete("master", name)
if setting_string
if Puppet::Util::Log.sendlevel?(:info)
report_section_and_environment(options[:section], Puppet.settings[:environment])
end
puts(_("Deleted setting from '%{section_name}': '%{setting_string}', and adding it to 'server' section") %
{ section_name: options[:section], name: name, setting_string: setting_string.strip })
end
# add the setting to the to server section instead of master section
config.set("server", name, value)
else
config.set(options[:section], name, value)
end
end
end
nil
end
end
action(:delete) do
summary _("Delete a Puppet setting.")
arguments _("")
# TRANSLATORS 'main' is a specific section name and should not be translated
description "Deletes a setting from the specified section. (The default is the section 'main')."
notes <<-'EOT'
By default, this action deletes the configuration setting from the 'main'
configuration domain. Use the '--section' flags to delete settings from other
configuration domains.
EOT
examples <<-'EOT'
Delete the setting 'setting_name' from the 'main' configuration domain:
$ puppet config delete setting_name
Delete the setting 'setting_name' from the 'server' configuration domain:
$ puppet config delete setting_name --section server
EOT
when_invoked do |name, options|
@default_section = false
if options[:section] == DEFAULT_SECTION_MARKER
options[:section] = DEFAULT_SECTION
@default_section = true
end
path = Puppet::FileSystem.pathname(Puppet.settings.which_configuration_file)
if Puppet::FileSystem.exist?(path)
Puppet::FileSystem.open(path, nil, 'r+:UTF-8') do |file|
Puppet::Settings::IniFile.update(file) do |config|
# delete from both master section and server section
if options[:section] == "master" || options[:section] == "server"
master_setting_string = config.delete("master", name)
puts(_("Deleted setting from '%{section_name}': '%{setting_string}'") %
{ section_name: 'master', name: name, setting_string: master_setting_string.strip[/[^=]+/] }) if master_setting_string
server_setting_string = config.delete("server", name)
puts(_("Deleted setting from '%{section_name}': '%{setting_string}'") %
{ section_name: 'server', name: name, setting_string: server_setting_string.strip[/[^=]+/] }) if server_setting_string
else
setting_string = config.delete(options[:section], name)
if setting_string
if Puppet::Util::Log.sendlevel?(:info)
report_section_and_environment(options[:section], Puppet.settings[:environment])
end
puts(_("Deleted setting from '%{section_name}': '%{setting_string}'") %
{ section_name: options[:section], name: name, setting_string: setting_string.strip })
else
Puppet.warning(_("No setting found in configuration file for section '%{section_name}' setting name '%{name}'") %
{ section_name: options[:section], name: name })
end
end
end
end
else
# TRANSLATORS the 'puppet.conf' is a specific file and should not be translated
Puppet.warning(_("The puppet.conf file does not exist %{puppet_conf}") % { puppet_conf: path })
end
nil
end
end
end
puppet-8.4.0/lib/puppet/face/report.rb 0000644 0052762 0001160 00000003525 14552052437 017565 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/indirector/face'
Puppet::Indirector::Face.define(:report, '0.0.1') do
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("Create, display, and submit reports.")
save = get_action(:save)
save.summary _("API only: submit a report.")
save.arguments _("")
save.returns _("Nothing.")
save.examples <<-'EOT'
From the implementation of `puppet report submit` (API example):
begin
Puppet::Transaction::Report.indirection.terminus_class = :rest
Puppet::Face[:report, "0.0.1"].save(report)
Puppet.notice "Uploaded report for #{report.name}"
rescue => detail
Puppet.log_exception(detail, "Could not send report: #{detail}")
end
EOT
action(:submit) do
summary _("API only: submit a report with error handling.")
description <<-'EOT'
API only: Submits a report to the puppet master. This action is
essentially a shortcut and wrapper for the `save` action with the `rest`
terminus, and provides additional details in the event of a failure.
EOT
arguments _("")
examples <<-'EOT'
API example:
# ...
report = Puppet::Face[:catalog, '0.0.1'].apply
Puppet::Face[:report, '0.0.1'].submit(report)
return report
EOT
when_invoked do |report, _options|
begin
Puppet::Transaction::Report.indirection.terminus_class = :rest
Puppet::Face[:report, "0.0.1"].save(report)
Puppet.notice _("Uploaded report for %{name}") % { name: report.name }
rescue => detail
Puppet.log_exception(detail, _("Could not send report: %{detail}") % { detail: detail })
end
end
end
deactivate_action(:find)
deactivate_action(:search)
deactivate_action(:destroy)
end
puppet-8.4.0/lib/puppet/face/resource.rb 0000644 0052762 0001160 00000003274 14552052437 020102 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/indirector/face'
Puppet::Indirector::Face.define(:resource, '0.0.1') do
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("API only: interact directly with resources via the RAL.")
description <<-'EOT'
API only: this face provides a Ruby API with functionality similar to the
puppet resource subcommand.
EOT
deactivate_action(:destroy)
search = get_action(:search)
search.summary _("API only: get all resources of a single type.")
search.arguments _("")
search.returns _("An array of Puppet::Resource objects.")
search.examples <<-'EOT'
Get a list of all user resources (API example):
all_users = Puppet::Face[:resource, '0.0.1'].search("user")
EOT
find = get_action(:find)
find.summary _("API only: get a single resource.")
find.arguments _("/")
find.returns _("A Puppet::Resource object.")
find.examples <<-'EOT'
Print information about a user on this system (API example):
puts Puppet::Face[:resource, '0.0.1'].find("user/luke").to_json
EOT
save = get_action(:save)
save.summary _("API only: create a new resource.")
save.description <<-EOT
API only: creates a new resource.
EOT
save.arguments _("")
save.returns _("The same resource object passed as an argument.")
save.examples <<-'EOT'
Create a new file resource (API example):
my_resource = Puppet::Resource.new(
:file,
"/tmp/demonstration",
:parameters => {:ensure => :present, :content => "some\nthing\n"}
)
Puppet::Face[:resource, '0.0.1'].save(my_resource)
EOT
end
puppet-8.4.0/lib/puppet/face/epp.rb 0000644 0052762 0001160 00000053677 14552052437 017053 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/pops'
require_relative '../../puppet/parser/files'
require_relative '../../puppet/file_system'
Puppet::Face.define(:epp, '0.0.1') do
copyright "Puppet Inc.", 2014
license _("Apache 2 license; see COPYING")
summary _("Interact directly with the EPP template parser/renderer.")
action(:validate) do
summary _("Validate the syntax of one or more EPP templates.")
arguments _("[] [ ...]")
returns _("Nothing, or encountered syntax errors.")
description <<-'EOT'
This action validates EPP syntax without producing any output.
When validating, multiple issues per file are reported up
to the settings of max_error, and max_warnings. The processing
stops after having reported issues for the first encountered file with errors
unless the option --continue_on_error is given.
Files can be given using the `modulename/template.epp` style to lookup the
template from a module, or be given as a reference to a file. If the reference
to a file can be resolved against a template in a module, the module version
wins - in this case use an absolute path to reference the template file
if the module version is not wanted.
Exits with 0 if there were no validation errors.
EOT
option("--[no-]continue_on_error") do
summary _("Whether or not to continue after errors are reported for a template.")
end
examples <<-'EOT'
Validate the template 'template.epp' in module 'mymodule':
$ puppet epp validate mymodule/template.epp
Validate two arbitrary template files:
$ puppet epp validate mymodule/template1.epp yourmodule/something.epp
Validate a template somewhere in the file system:
$ puppet epp validate /tmp/testing/template1.epp
Validate a template against a file relative to the current directory:
$ puppet epp validate template1.epp
$ puppet epp validate ./template1.epp
Validate from STDIN:
$ cat template.epp | puppet epp validate
Continue on error to see errors for all templates:
$ puppet epp validate mymodule/template1.epp mymodule/template2.epp --continue_on_error
EOT
when_invoked do |*args|
options = args.pop
# pass a dummy node, as facts are not needed for validation
options[:node] = Puppet::Node.new("testnode", :facts => Puppet::Node::Facts.new("facts", {}))
compiler = create_compiler(options)
status = true # no validation error yet
files = args
if files.empty?
if not STDIN.tty?
tmp = validate_template_string(STDIN.read)
status &&= tmp
else
# This is not an error since a validate of all files in an empty
# directory should not be treated as a failed validation.
Puppet.notice _("No template specified. No action taken")
end
end
missing_files = []
files.each do |file|
break if !status && !options[:continue_on_error]
template_file = effective_template(file, compiler.environment)
if template_file
tmp = validate_template(template_file)
status &&= tmp
else
missing_files << file
end
end
if !missing_files.empty?
raise Puppet::Error, _("One or more file(s) specified did not exist:\n%{missing_files_list}") %
{ missing_files_list: missing_files.map { |f| " #{f}" }.join("\n") }
else
# Exit with 1 if there were errors
raise Puppet::Error, _("Errors while validating epp") unless status
end
end
end
action(:dump) do
summary _("Outputs a dump of the internal template parse tree for debugging")
arguments "[--format ] [--pretty] { -e | [ ...] } "
returns _("A dump of the resulting AST model unless there are syntax or validation errors.")
description <<-'EOT'
The dump action parses and validates the EPP syntax and dumps the resulting AST model
in a human readable (but not necessarily an easy to understand) format.
The output format can be controlled using the --format where:
* 'old' is the default, but now deprecated format which is not API.
* 'pn' is the Puppet Extended S-Expression Notation.
* 'json' outputs the same graph as 'pn' but with JSON syntax.
The output will be "pretty printed" when the option --pretty is given together with --format 'pn' or 'json'.
This option has no effect on the 'old' format.
The command accepts one or more templates (.epp) files, or an -e followed by the template
source text. The given templates can be paths to template files, or references
to templates in modules when given on the form /.epp.
If no arguments are given, the stdin is read (unless it is attached to a terminal)
If multiple templates are given, they are separated with a header indicating the
name of the template. This can be suppressed with the option --no-header.
The option --[no-]header has no effect when a single template is dumped.
When debugging the epp parser itself, it may be useful to suppress the validation
step with the `--no-validate` option to observe what the parser produced from the
given source.
This command ignores the --render-as setting/option.
EOT
option("--e " + _("")) do
default_to { nil }
summary _("Dump one epp source expression given on the command line.")
end
option("--[no-]validate") do
summary _("Whether or not to validate the parsed result, if no-validate only syntax errors are reported.")
end
option('--format ' + _('')) do
summary _("Get result in 'old' (deprecated format), 'pn' (new format), or 'json' (new format in JSON).")
end
option('--pretty') do
summary _('Pretty print output. Only applicable together with --format pn or json')
end
option("--[no-]header") do
summary _("Whether or not to show a file name header between files.")
end
when_invoked do |*args|
require_relative '../../puppet/pops'
options = args.pop
# pass a dummy node, as facts are not needed for dump
options[:node] = Puppet::Node.new("testnode", :facts => Puppet::Node::Facts.new("facts", {}))
options[:header] = options[:header].nil? ? true : options[:header]
options[:validate] = options[:validate].nil? ? true : options[:validate]
compiler = create_compiler(options)
# Print to a buffer since the face needs to return the resulting string
# and the face API is "all or nothing"
#
buffer = StringIO.new
if options[:e]
buffer.print dump_parse(options[:e], 'command-line-string', options, false)
elsif args.empty?
if ! STDIN.tty?
buffer.print dump_parse(STDIN.read, 'stdin', options, false)
else
raise Puppet::Error, _("No input to parse given on command line or stdin")
end
else
templates, missing_files = args.reduce([[],[]]) do |memo, file|
template_file = effective_template(file, compiler.environment)
if template_file.nil?
memo[1] << file
else
memo[0] << template_file
end
memo
end
show_filename = templates.count > 1
templates.each do |file|
buffer.print dump_parse(Puppet::FileSystem.read(file, :encoding => 'utf-8'), file, options, show_filename)
end
if !missing_files.empty?
raise Puppet::Error, _("One or more file(s) specified did not exist:\n%{missing_files_list}") %
{ missing_files_list: missing_files.collect { |f| " #{f}" }.join("\n") }
end
end
buffer.string
end
end
action(:render) do
summary _("Renders an epp template as text")
arguments "-e | [ ...] "
returns _("A rendered result of one or more given templates.")
description <<-'EOT'
This action renders one or more EPP templates.
The command accepts one or more templates (.epp files), given the same way as templates
are given to the puppet `epp` function (a full path, or a relative reference
on the form '/.epp'), or as a relative path.args In case
the given path matches both a modulename/template and a file, the template from
the module is used.
An inline_epp equivalent can also be performed by giving the template after
an -e, or by piping the EPP source text to the command.
Values to the template can be defined using the Puppet Language on the command
line with `--values` or in a .pp or .yaml file referenced with `--values_file`. If
specifying both the result is merged with --values having higher precedence.
The --values option allows a Puppet Language sequence of expressions to be defined on the
command line the same way as it may be given in a .pp file referenced with `--values_file`.
It may set variable values (that become available in the template), and must produce
either `undef` or a `Hash` of values (the hash may be empty). Producing `undef` simulates
that the template is called without an arguments hash and thus only references
variables in its outer scope. When a hash is given, a template is limited to seeing
only the global scope. It is thus possible to simulate the different types of
calls to the `epp` and `inline_epp` functions, with or without a given hash. Note that if
variables are given, they are always available in this simulation - to test that the
template only references variables given as arguments, produce a hash in --values or
the --values_file, do not specify any variables that are not global, and
turn on --strict_variables setting.
If multiple templates are given, the same set of values are given to each template.
If both --values and --value_file are used, the --values are merged on top of those given
in the file.
When multiple templates are rendered, a separating header is output between the templates
showing the name of the template before the output. The header output can be turned off with
`--no-header`. This also concatenates the template results without any added newline separators.
Facts from the node where the command is being run are used by default.args Facts can be obtained
for other nodes if they have called in, and reported their facts by using the `--node `
flag.
Overriding node facts as well as additional facts can be given in a .yaml or .json file and referencing
it with the --facts option. (Values can be obtained in yaml format directly from
`facter`, or from puppet for a given node). Note that it is not possible to simulate the
reserved variable name `$facts` in any other way.
Note that it is not possible to set variables using the Puppet Language that have the same
names as facts as this result in an error; "attempt to redefine a variable" since facts
are set first.
Exits with 0 if there were no validation errors. On errors, no rendered output is produced for
that template file.
When designing EPP templates, it is strongly recommended to define all template arguments
in the template, and to give them in a hash when calling `epp` or `inline_epp` and to use
as few global variables as possible, preferably only the $facts hash. This makes templates
more free standing and are easier to reuse, and to test.
EOT
examples <<-'EOT'
Render the template in module 'mymodule' called 'mytemplate.epp', and give it two arguments
`a` and `b`:
$ puppet epp render mymodule/mytemplate.epp --values '{a => 10, b => 20}'
Render a template using an absolute path:
$ puppet epp render /tmp/testing/mytemplate.epp --values '{a => 10, b => 20}'
Render a template with data from a .pp file:
$ puppet epp render /tmp/testing/mytemplate.epp --values_file mydata.pp
Render a template with data from a .pp file and override one value on the command line:
$ puppet epp render /tmp/testing/mytemplate.epp --values_file mydata.pp --values '{a=>10}'
Render from STDIN:
$ cat template.epp | puppet epp render --values '{a => 10, b => 20}'
Set variables in a .pp file and render a template that uses variable references:
# data.pp file
$greeted = 'a global var'
undef
$ puppet epp render -e 'hello <%= $greeted %>' --values_file data.pp
Render a template that outputs a fact:
$ facter --yaml > data.yaml
$ puppet epp render -e '<% $facts[osfamily] %>' --facts data.yaml
EOT
option("--node " + _("")) do
summary _("The name of the node for which facts are obtained. Defaults to facts for the local node.")
end
option("--e " + _("")) do
default_to { nil }
summary _("Render one inline epp template given on the command line.")
end
option("--values " + _("")) do
summary _("A Hash in Puppet DSL form given as arguments to the template being rendered.")
end
option("--values_file " + _("")) do
summary _("A .pp or .yaml file that is processed to produce a hash of values for the template.")
end
option("--facts " + _("")) do
summary _("A .yaml or .json file containing a hash of facts made available in $facts and $trusted")
end
option("--[no-]header") do
summary _("Whether or not to show a file name header between rendered results.")
end
when_invoked do |*args|
options = args.pop
options[:header] = options[:header].nil? ? true : options[:header]
compiler = create_compiler(options)
compiler.with_context_overrides('For rendering epp') do
# Print to a buffer since the face needs to return the resulting string
# and the face API is "all or nothing"
#
buffer = StringIO.new
status = true
if options[:e]
buffer.print render_inline(options[:e], compiler, options)
elsif args.empty?
if ! STDIN.tty?
buffer.print render_inline(STDIN.read, compiler, options)
else
raise Puppet::Error, _("No input to process given on command line or stdin")
end
else
show_filename = args.count > 1
file_nbr = 0
args.each do |file|
begin
buffer.print render_file(file, compiler, options, show_filename, file_nbr += 1)
rescue Puppet::ParseError => detail
Puppet.err(detail.message)
status = false
end
end
end
raise Puppet::Error, _("error while rendering epp") unless status
buffer.string
end
end
end
def dump_parse(source, filename, options, show_filename = true)
output = ''.dup
evaluating_parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new
begin
if options[:validate]
parse_result = evaluating_parser.parse_string(source, filename)
else
# side step the assert_and_report step
parse_result = evaluating_parser.parser.parse_string(source)
end
if show_filename && options[:header]
output << "--- #{filename}\n"
end
fmt = options[:format]
if fmt.nil? || fmt == 'old'
output << Puppet::Pops::Model::ModelTreeDumper.new.dump(parse_result) << "\n"
else
require_relative '../../puppet/pops/pn'
pn = Puppet::Pops::Model::PNTransformer.transform(parse_result)
case fmt
when 'json'
options[:pretty] ? JSON.pretty_unparse(pn.to_data) : JSON.dump(pn.to_data)
else
pn.format(options[:pretty] ? Puppet::Pops::PN::Indent.new(' ') : nil, output)
end
end
rescue Puppet::ParseError => detail
if show_filename
Puppet.err("--- #{filename}")
end
Puppet.err(detail.message)
""
end
end
def get_values(compiler, options)
template_values = nil
values_file = options[:values_file]
if values_file
begin
if values_file =~ /\.yaml$/
template_values = Puppet::Util::Yaml.safe_load_file(values_file, [Symbol])
elsif values_file =~ /\.pp$/
evaluating_parser = Puppet::Pops::Parser::EvaluatingParser.new
template_values = evaluating_parser.evaluate_file(compiler.topscope, values_file)
else
Puppet.err(_("Only .yaml or .pp can be used as a --values_file"))
end
rescue => e
Puppet.err(_("Could not load --values_file %{error}") % { error: e.message })
end
if !(template_values.nil? || template_values.is_a?(Hash))
Puppet.err(_("--values_file option must evaluate to a Hash or undef/nil, got: '%{template_class}'") % { template_class: template_values.class })
end
end
values = options[:values]
if values
evaluating_parser = Puppet::Pops::Parser::EvaluatingParser.new
result = evaluating_parser.evaluate_string(compiler.topscope, values, 'values-hash')
case result
when nil
template_values
when Hash
template_values.nil? ? result : template_values.merge(result)
else
Puppet.err(_("--values option must evaluate to a Hash or undef, got: '%{values_class}'") % { values_class: result.class })
end
else
template_values
end
end
def render_inline(epp_source, compiler, options)
template_args = get_values(compiler, options)
result = Puppet::Pops::Evaluator::EppEvaluator.inline_epp(compiler.topscope, epp_source, template_args)
if result.instance_of?(Puppet::Pops::Types::PSensitiveType::Sensitive)
result.unwrap
else
result
end
end
def render_file(epp_template_name, compiler, options, show_filename, file_nbr)
template_args = get_values(compiler, options)
output = ''.dup
begin
if show_filename && options[:header]
output << "\n" unless file_nbr == 1
output << "--- #{epp_template_name}\n"
end
# Change to an absolute file only if reference is to a an existing file. Note that an absolute file must be used
# or the template must be found on the module path when calling the epp evaluator.
template_file = Puppet::Parser::Files.find_template(epp_template_name, compiler.environment)
if template_file.nil? && Puppet::FileSystem.exist?(epp_template_name)
epp_template_name = File.expand_path(epp_template_name)
end
result = Puppet::Pops::Evaluator::EppEvaluator.epp(compiler.topscope, epp_template_name, compiler.environment, template_args)
if result.instance_of?(Puppet::Pops::Types::PSensitiveType::Sensitive)
output << result.unwrap
else
output << result
end
rescue Puppet::ParseError => detail
Puppet.err("--- #{epp_template_name}") if show_filename
raise detail
end
output
end
# @api private
def validate_template(template)
parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new()
parser.parse_file(template)
true
rescue => detail
Puppet.log_exception(detail)
false
end
# @api private
def validate_template_string(source)
parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new()
parser.parse_string(source, '')
true
rescue => detail
Puppet.log_exception(detail)
false
end
# @api private
def create_compiler(options)
if options[:node]
node = options[:node]
else
node = Puppet[:node_name_value]
# If we want to lookup the node we are currently on
# we must returning these settings to their default values
Puppet.settings[:facts_terminus] = 'facter'
Puppet.settings[:node_cache_terminus] = nil
end
unless node.is_a?(Puppet::Node)
node = Puppet::Node.indirection.find(node)
# Found node must be given the environment to use in some cases, use the one configured
# or given on the command line
node.environment = Puppet[:environment]
end
fact_file = options[:facts]
if fact_file
if fact_file.is_a?(Hash) # when used via the Face API
given_facts = fact_file
elsif fact_file.end_with?("json")
given_facts = Puppet::Util::Json.load(Puppet::FileSystem.read(fact_file, :encoding => 'utf-8'))
else
given_facts = Puppet::Util::Yaml.safe_load_file(fact_file)
end
unless given_facts.instance_of?(Hash)
raise _("Incorrect formatted data in %{fact_file} given via the --facts flag") % { fact_file: fact_file }
end
# It is difficult to add to or modify the set of facts once the node is created
# as changes does not show up in parameters. Rather than manually patching up
# a node and risking future regressions, a new node is created from scratch
node = Puppet::Node.new(node.name, :facts => Puppet::Node::Facts.new("facts", node.facts.values.merge(given_facts)))
node.environment = Puppet[:environment]
node.merge(node.facts.values)
end
compiler = Puppet::Parser::Compiler.new(node)
# configure compiler with facts and node related data
# Set all global variables from facts
compiler.send(:set_node_parameters)
# pretend that the main class (named '') has been evaluated
# since it is otherwise not possible to resolve top scope variables
# using '::' when rendering. (There is no harm doing this for the other actions)
#
compiler.topscope.class_set('', compiler.topscope)
compiler
end
# Produces the effective template file from a module/template or file reference
# @api private
def effective_template(file, env)
template_file = Puppet::Parser::Files.find_template(file, env)
if !template_file.nil?
template_file
elsif Puppet::FileSystem.exist?(file)
file
else
nil
end
end
end
puppet-8.4.0/lib/puppet/face/node.rb 0000644 0052762 0001160 00000003336 14552052437 017177 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/indirector/face'
Puppet::Indirector::Face.define(:node, '0.0.1') do
copyright "Puppet Inc.", 2011
license _("Apache 2 license; see COPYING")
summary _("View and manage node definitions.")
description <<-'EOT'
This subcommand interacts with node objects, which are used by Puppet to
build a catalog. A node object consists of the node's facts, environment,
node parameters (exposed in the parser as top-scope variables), and classes.
EOT
deactivate_action(:destroy)
deactivate_action(:search)
deactivate_action(:save)
find = get_action(:find)
find.summary _("Retrieve a node object.")
find.arguments _("")
# TRANSLATORS the following are specific names and should not be translated `classes`, `environment`, `expiration`, `name`, `parameters`, Puppet::Node
find.returns _(<<-'EOT')
A hash containing the node's `classes`, `environment`, `expiration`, `name`,
`parameters` (its facts, combined with any ENC-set parameters), and `time`.
When used from the Ruby API: a Puppet::Node object.
RENDERING ISSUES: Rendering as string and json are currently broken;
node objects can only be rendered as yaml.
EOT
find.examples <<-'EOT'
Retrieve an "empty" (no classes, no ENC-imposed parameters, and an
environment of "production") node:
$ puppet node find somenode.puppetlabs.lan --terminus plain --render-as yaml
Retrieve a node using the Puppet Server's configured ENC:
$ puppet node find somenode.puppetlabs.lan --terminus exec --run_mode server --render-as yaml
Retrieve the same node from the Puppet Server:
$ puppet node find somenode.puppetlabs.lan --terminus rest --render-as yaml
EOT
end
puppet-8.4.0/lib/puppet/face/parser.rb 0000644 0052762 0001160 00000016574 14552052437 017556 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/face'
require_relative '../../puppet/parser'
Puppet::Face.define(:parser, '0.0.1') do
copyright "Puppet Inc.", 2014
license _("Apache 2 license; see COPYING")
summary _("Interact directly with the parser.")
action :validate do
summary _("Validate the syntax of one or more Puppet manifests.")
arguments _("[] [ ...]")
returns _("Nothing, or the first syntax error encountered.")
description <<-'EOT'
This action validates Puppet DSL syntax without compiling a catalog or
syncing any resources. If no manifest files are provided, it will
validate the default site manifest.
When validating multiple issues per file are reported up
to the settings of max_error, and max_warnings. The processing stops
after having reported issues for the first encountered file with errors.
EOT
examples <<-'EOT'
Validate the default site manifest at /etc/puppetlabs/puppet/manifests/site.pp:
$ puppet parser validate
Validate two arbitrary manifest files:
$ puppet parser validate init.pp vhost.pp
Validate from STDIN:
$ cat init.pp | puppet parser validate
EOT
when_invoked do |*args|
files = args.slice(0..-2)
parse_errors = {}
if files.empty?
if not STDIN.tty?
Puppet[:code] = STDIN.read
error = validate_manifest(nil)
parse_errors['STDIN'] = error if error
else
manifest = Puppet.lookup(:current_environment).manifest
files << manifest
Puppet.notice _("No manifest specified. Validating the default manifest %{manifest}") % { manifest: manifest }
end
end
missing_files = []
files.each do |file|
if Puppet::FileSystem.exist?(file)
error = validate_manifest(file)
parse_errors[file] = error if error
else
missing_files << file
end
end
unless missing_files.empty?
raise Puppet::Error, _("One or more file(s) specified did not exist:\n%{files}") % { files: missing_files.collect {|f| " " * 3 + f + "\n"} }
end
parse_errors
end
when_rendering :console do |errors|
unless errors.empty?
errors.each { |_, error| Puppet.log_exception(error) }
exit(1)
end
# Prevent face_base renderer from outputting "null"
exit(0)
end
when_rendering :json do |errors|
unless errors.empty?
ignore_error_keys = [ :arguments, :environment, :node ]
data = errors.map do |file, error|
file_errors = error.to_h.reject { |k, _| ignore_error_keys.include?(k) }
[file, file_errors]
end.to_h
puts Puppet::Util::Json.dump(Puppet::Pops::Serialization::ToDataConverter.convert(data, rich_data: false, symbol_as_string: true), :pretty => true)
exit(1)
end
# Prevent face_base renderer from outputting "null"
exit(0)
end
end
action(:dump) do
summary _("Outputs a dump of the internal parse tree for debugging")
arguments "[--format ] [--pretty] { -e | [ ...] } "
returns _("A dump of the resulting AST model unless there are syntax or validation errors.")
description <<-'EOT'
This action parses and validates the Puppet DSL syntax without compiling a catalog
or syncing any resources.
The output format can be controlled using the --format where:
* 'old' is the default, but now deprecated format which is not API.
* 'pn' is the Puppet Extended S-Expression Notation.
* 'json' outputs the same graph as 'pn' but with JSON syntax.
The output will be "pretty printed" when the option --pretty is given together with --format 'pn' or 'json'.
This option has no effect on the 'old' format.
The command accepts one or more manifests (.pp) files, or an -e followed by the puppet
source text.
If no arguments are given, the stdin is read (unless it is attached to a terminal)
The output format of the dumped tree is intended for debugging purposes and is
not API, it may change from time to time.
EOT
option "--e " + _("") do
default_to { nil }
summary _("dump one source expression given on the command line.")
end
option("--[no-]validate") do
summary _("Whether or not to validate the parsed result, if no-validate only syntax errors are reported")
end
option('--format ' + _('')) do
summary _("Get result in 'old' (deprecated format), 'pn' (new format), or 'json' (new format in JSON).")
end
option('--pretty') do
summary _('Pretty print output. Only applicable together with --format pn or json')
end
when_invoked do |*args|
require_relative '../../puppet/pops'
options = args.pop
if options[:e]
dump_parse(options[:e], 'command-line-string', options, false)
elsif args.empty?
if ! STDIN.tty?
dump_parse(STDIN.read, 'stdin', options, false)
else
raise Puppet::Error, _("No input to parse given on command line or stdin")
end
else
files = args
available_files = files.select do |file|
Puppet::FileSystem.exist?(file)
end
missing_files = files - available_files
dumps = available_files.collect do |file|
dump_parse(Puppet::FileSystem.read(file, :encoding => 'utf-8'), file, options)
end.join("")
if missing_files.empty?
dumps
else
dumps + _("One or more file(s) specified did not exist:\n") + missing_files.collect { |f| " #{f}" }.join("\n")
end
end
end
end
def dump_parse(source, filename, options, show_filename = true)
output = ''.dup
evaluating_parser = Puppet::Pops::Parser::EvaluatingParser.new
begin
if options[:validate]
parse_result = evaluating_parser.parse_string(source, filename)
else
# side step the assert_and_report step
parse_result = evaluating_parser.parser.parse_string(source)
end
if show_filename
output << "--- #{filename}"
end
fmt = options[:format]
if fmt.nil? || fmt == 'old'
output << Puppet::Pops::Model::ModelTreeDumper.new.dump(parse_result) << "\n"
else
require_relative '../../puppet/pops/pn'
pn = Puppet::Pops::Model::PNTransformer.transform(parse_result)
case fmt
when 'json'
options[:pretty] ? JSON.pretty_unparse(pn.to_data) : JSON.dump(pn.to_data)
else
pn.format(options[:pretty] ? Puppet::Pops::PN::Indent.new(' ') : nil, output)
end
end
rescue Puppet::ParseError => detail
if show_filename
Puppet.err("--- #{filename}")
end
Puppet.err(detail.message)
""
end
end
# @api private
def validate_manifest(manifest = nil)
env = Puppet.lookup(:current_environment)
loaders = Puppet::Pops::Loaders.new(env)
Puppet.override( {:loaders => loaders } , _('For puppet parser validate')) do
begin
validation_environment = manifest ? env.override_with(:manifest => manifest) : env
validation_environment.check_for_reparse
validation_environment.known_resource_types.clear
rescue Puppet::ParseError => parse_error
return parse_error
end
end
nil
end
end
puppet-8.4.0/lib/puppet/face/help/ 0000755 0052762 0001160 00000000000 14552052637 016652 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/face/help/face.erb 0000644 0052762 0001160 00000006400 14552052437 020240 0 ustar jenkins jenkins <%# encoding: UTF-8%>
<% if face.deprecated? -%>
<%= "Warning: 'puppet #{face.name}' is deprecated and will be removed in a future release." %>
<% end %>
<% if face.synopsis -%>
USAGE: <%= face.synopsis %>
<% end -%>
<%= (face.short_description || face.summary || "undocumented subcommand").strip %>
OPTIONS:
<%# Remove these options once we can introspect them normally. -%>
--render-as FORMAT - The rendering format to use.
--verbose - Whether to log verbosely.
--debug - Whether to log debug information.
<% optionroom = 30
summaryroom = 80 - 5 - optionroom
disp_glob_opts = face.display_global_options.uniq
unless disp_glob_opts.empty?
disp_glob_opts.sort.each do |name|
option = name
desc = Puppet.settings.setting(option).desc
type = Puppet.settings.setting(option).default
type ||= Puppet.settings.setting(option).type.to_s.upcase -%>
<%= "--#{option} #{type}".ljust(optionroom) + ' - ' -%>
<% if !(desc) -%>
undocumented option
<% elsif desc.length <= summaryroom -%>
<%= desc %>
<% else
words = desc.split
wrapped = ['']
i = 0
words.each do |word|
if wrapped[i].length + word.length <= summaryroom
wrapped[i] << word + ' '
else
i += 1
wrapped[i] = word + ' '
end
end -%>
<%= wrapped.shift.strip %>
<% wrapped.each do |line| -%>
<%= (' ' * (optionroom + 5) ) + line.strip %>
<% end
end
end
end
unless face.options.empty?
face.options.sort.each do |name|
option = face.get_option name -%>
<%= " " + option.optparse.join(" | ")[0,(optionroom - 1)].ljust(optionroom) + ' - ' -%>
<% if !(option.summary) -%>
undocumented option
<% elsif option.summary.length <= summaryroom -%>
<%= option.summary %>
<%
else
words = option.summary.split
wrapped = ['']
i = 0
words.each do |word|
if wrapped[i].length + word.length <= summaryroom
wrapped[i] << word + ' '
else
i += 1
wrapped[i] = word + ' '
end
end
-%>
<%= wrapped.shift.strip %>
<% wrapped.each do |line| -%>
<%= (' ' * (optionroom + 5) ) + line.strip %>
<% end
end
end -%>
<% end -%>
ACTIONS:
<% padding = face.actions.map{|x| x.to_s.length}.max + 2
summaryroom = 80 - (padding + 4)
face.actions.each do |actionname|
action = face.get_action(actionname) -%>
<%= action.name.to_s.ljust(padding) + ' ' -%>
<% if !(action.summary) -%>
undocumented action
<% elsif action.summary.length <= summaryroom -%>
<%= action.summary %>
<% else
words = action.summary.split
wrapped = ['']
i = 0
words.each do |word|
if wrapped[i].length + word.length <= summaryroom
wrapped[i] << word + ' '
else
i += 1
wrapped[i] = word + ' '
end
end
-%>
<%= wrapped.shift.strip %>
<% wrapped.each do |line| -%>
<%= (' ' * (padding + 4) ) + line.strip %>
<% end
end
end -%>
<% if face.respond_to? :indirection -%>
TERMINI: <%= face.class.terminus_classes(face.indirection.name).join(", ") %>
<% end -%>
See 'puppet help <%= face.name %>' or 'man puppet-<%= face.name %>' for full help.
puppet-8.4.0/lib/puppet/face/help/man.erb 0000644 0052762 0001160 00000010361 14552052437 020116 0 ustar jenkins jenkins <%# encoding: UTF-8%>
puppet-<%= face.name %>(8) -- <%= face.summary || "Undocumented subcommand." %>
<%= '=' * (_erbout.length - 1) %>
<% if face.synopsis -%>
SYNOPSIS
--------
<%= face.synopsis %>
<% end
if face.description -%>
DESCRIPTION
-----------
<%= face.description.strip %>
<% end -%>
OPTIONS
-------
Note that any setting that's valid in the configuration
file is also a valid long argument, although it may or may not be
relevant to the present action. For example, `server` and `run_mode` are valid
settings, so you can specify `--server `, or
`--run_mode ` as an argument.
See the configuration file documentation at
for the
full list of acceptable parameters. A commented list of all
configuration options can also be generated by running puppet with
`--genconfig`.
* --render-as FORMAT:
The format in which to render output. The most common formats are `json`,
`s` (string), `yaml`, and `console`, but other options such as `dot` are
sometimes available.
* --verbose:
Whether to log verbosely.
* --debug:
Whether to log debug information.
<% unless face.display_global_options.empty?
face.display_global_options.uniq.sort.each do |name|
option = name
desc = Puppet::Util::Docs.scrub(Puppet.settings.setting(option).desc)
type = Puppet.settings.setting(option).default
type ||= Puppet.settings.setting(option).type.to_s.upcase -%>
<%= "* --#{option} #{type}" %>:
<%= (desc || 'Undocumented setting.').gsub(/^/, ' ') %>
<% end
end -%>
<% unless face.options.empty?
face.options.sort.each do |name|
option = face.get_option name -%>
<%= "* " + option.optparse.join(" | " ) %>:
<%= (option.description || option.summary || "Undocumented option.").gsub(/^/, ' ') %>
<% end
end -%>
ACTIONS
-------
<% face.actions.each do |actionname|
action = face.get_action(actionname) -%>
* `<%= action.name.to_s %>` - <%= action.summary %>:
<% if action.synopsis -%>
`SYNOPSIS`
<%= action.synopsis %>
<% end -%>
`DESCRIPTION`
<% if action.description -%>
<%= action.description.gsub(/^/, ' ') %>
<% else -%>
<%= action.summary || "Undocumented action." %>
<% end -%>
<% unique_options = action.options - face.options
unique_display_global_options = action.display_global_options - face.display_global_options
unless unique_options.empty? and unique_display_global_options.empty? -%>
`OPTIONS`
<% unique_display_global_options.uniq.sort.each do |name|
option = name
desc = Puppet::Util::Docs.scrub(Puppet.settings.setting(option).desc)
type = Puppet.settings.setting(option).default
type ||= Puppet.settings.setting(option).type.to_s.upcase -%>
<%= "<--#{option} #{type}>" %> -
<%= (desc || "Undocumented setting.").gsub(/^/, ' ') %>
<% end -%>
<% unique_options.sort.each do |name|
option = action.get_option name
text = (option.description || option.summary || "Undocumented option.").chomp + "\n" -%>
<%= '<' + option.optparse.join("> | <") + '>' %> -
<%= text.gsub(/^/, ' ') %>
<% end -%>
<% end -%>
<% if action.returns -%>
`RETURNS`
<%= action.returns.gsub(/^/, ' ') %>
<% end
if action.notes -%>
`NOTES`
<%= action.notes.gsub(/^/, ' ') %>
<% end
end
if face.examples or face.actions.any? {|actionname| face.get_action(actionname).examples} -%>
EXAMPLES
--------
<% end
if face.examples -%>
<%= face.examples %>
<% end
face.actions.each do |actionname|
action = face.get_action(actionname)
if action.examples -%>
`<%= action.name.to_s %>`
<%= action.examples.strip %>
<% end
end -%>
<% if face.notes or face.respond_to? :indirection -%>
NOTES
-----
<% if face.notes -%>
<%= face.notes.strip %>
<% end # notes
if face.respond_to? :indirection -%>
This subcommand is an indirector face, which exposes `find`, `search`, `save`,
and `destroy` actions for an indirected subsystem of Puppet. Valid termini for
this face include:
* `<%= face.class.terminus_classes(face.indirection.name).join("`\n* `") %>`
<% end # indirection
end # notes or indirection
unless face.authors.empty? -%>
AUTHOR
------
<%= face.authors.join("\n").gsub(/^/, ' * ') %>
<% end -%>
COPYRIGHT AND LICENSE
---------------------
<%= face.copyright %>
<%= face.license %>
puppet-8.4.0/lib/puppet/face/help/global.erb 0000644 0052762 0001160 00000001527 14552052437 020607 0 ustar jenkins jenkins <%# encoding: UTF-8%>
Usage: puppet [options] [options]
Available subcommands:
<%# NOTE: this is probably not a good long-term solution for this. We're only iterating over
applications to find the list of things we need to show help for... this works for now
because faces can't be run without an application stub. However, when #6753 is resolved,
all of the application stubs for faces will go away, and this will need to be updated
to reflect that. --cprice 2012-04-26 %>
<% all_application_summaries.each do |appname, summary, indent| -%>
<%= indent %><%= appname.to_s.ljust(16) %> <%= summary %>
<% end -%>
See 'puppet help ' for help on a specific subcommand action.
See 'puppet help ' for help on a specific subcommand.
Puppet v<%= Puppet.version %>
puppet-8.4.0/lib/puppet/face/help/action.erb 0000644 0052762 0001160 00000005126 14552052437 020623 0 ustar jenkins jenkins <%# encoding: UTF-8%>
<% if action.deprecated? -%>
<%= "Warning: 'puppet #{action.face.name} #{action.name}' is deprecated and will be removed in a future release." %>
<% end %>
<% if action.synopsis -%>
USAGE: <%= action.synopsis %>
<% end -%>
<%= action.short_description || action.summary || face.summary || "undocumented subcommand" %>
<% if action.returns -%>
RETURNS: <%= action.returns.strip %>
<% end -%>
OPTIONS:
<%# Remove these options once we can introspect them normally. -%>
--render-as FORMAT - The rendering format to use.
--verbose - Whether to log verbosely.
--debug - Whether to log debug information.
<% optionroom = 30
summaryroom = 80 - 5 - optionroom
disp_glob_opts = action.display_global_options.uniq
unless disp_glob_opts.empty?
disp_glob_opts.sort.each do |name|
option = name
desc = Puppet.settings.setting(option).desc
type = Puppet.settings.setting(option).default
type ||= Puppet.settings.setting(option).type.to_s.upcase -%>
<%= "--#{option} #{type}".ljust(optionroom) + ' - ' -%>
<% if !(desc) -%>
undocumented option
<% elsif desc.length <= summaryroom -%>
<%= desc %>
<%
else
words = desc.split
wrapped = ['']
i = 0
words.each do |word|
if wrapped[i].length + word.length <= summaryroom
wrapped[i] << word + ' '
else
i += 1
wrapped[i] = word + ' '
end
end -%>
<%= wrapped.shift.strip %>
<% wrapped.each do |line| -%>
<%= (' ' * (optionroom + 5) ) + line.strip %>
<% end
end
end
end
unless action.options.empty?
action.options.sort.each do |name|
option = action.get_option name -%>
<%= " " + option.optparse.join(" | ")[0,(optionroom - 1)].ljust(optionroom) + ' - ' -%>
<% if !(option.summary) -%>
undocumented option
<% elsif option.summary.length <= summaryroom -%>
<%= option.summary %>
<%
else
words = option.summary.split
wrapped = ['']
i = 0
words.each do |word|
if wrapped[i].length + word.length <= summaryroom
wrapped[i] << word + ' '
else
i += 1
wrapped[i] = word + ' '
end
end
-%>
<%= wrapped.shift.strip %>
<% wrapped.each do |line| -%>
<%= (' ' * (optionroom + 5) ) + line.strip %>
<% end
end
end -%>
<% end -%>
<% if face.respond_to? :indirection -%>
TERMINI: <%= face.class.terminus_classes(face.indirection.name).join(", ") %>
<% end -%>
See 'puppet help <%= face.name %>' or 'man puppet-<%= face.name %>' for full help.
puppet-8.4.0/lib/puppet/module_tool.rb 0000644 0052762 0001160 00000015740 14552052437 017700 0 ustar jenkins jenkins # encoding: UTF-8
# frozen_string_literal: true
# Load standard libraries
require 'pathname'
require 'fileutils'
require_relative '../puppet/util/colors'
module Puppet
module ModuleTool
require_relative 'module_tool/tar'
extend Puppet::Util::Colors
# Directory and names that should not be checksummed.
ARTIFACTS = ['pkg', /^\./, /^~/, /^#/, 'coverage', 'checksums.json', 'REVISION']
FULL_MODULE_NAME_PATTERN = /\A([^-\/|.]+)[-|\/](.+)\z/
REPOSITORY_URL = Puppet.settings[:module_repository]
# Is this a directory that shouldn't be checksummed?
#
# TODO: Should this be part of Checksums?
# TODO: Rename this method to reflect its purpose?
# TODO: Shouldn't this be used when building packages too?
def self.artifact?(path)
case File.basename(path)
when *ARTIFACTS
true
else
false
end
end
# Return the +username+ and +modname+ for a given +full_module_name+, or raise an
# ArgumentError if the argument isn't parseable.
def self.username_and_modname_from(full_module_name)
matcher = full_module_name.match(FULL_MODULE_NAME_PATTERN)
if matcher
return matcher.captures
else
raise ArgumentError, _("Not a valid full name: %{full_module_name}") % { full_module_name: full_module_name }
end
end
# Find the module root when given a path by checking each directory up from
# its current location until it finds one that satisfies is_module_root?
#
# @param path [Pathname, String] path to start from
# @return [Pathname, nil] the root path of the module directory or nil if
# we cannot find one
def self.find_module_root(path)
path = Pathname.new(path) if path.class == String
path.expand_path.ascend do |p|
return p if is_module_root?(p)
end
nil
end
# Analyse path to see if it is a module root directory by detecting a
# file named 'metadata.json'
#
# @param path [Pathname, String] path to analyse
# @return [Boolean] true if the path is a module root, false otherwise
def self.is_module_root?(path)
path = Pathname.new(path) if path.class == String
FileTest.file?(path + 'metadata.json')
end
# Builds a formatted tree from a list of node hashes containing +:text+
# and +:dependencies+ keys.
def self.format_tree(nodes, level = 0)
str = ''.dup
nodes.each_with_index do |node, i|
last_node = nodes.length - 1 == i
deps = node[:dependencies] || []
str << (indent = " " * level)
str << (last_node ? "└" : "├")
str << "─"
str << (deps.empty? ? "─" : "┬")
str << " #{node[:text]}\n"
branch = format_tree(deps, level + 1)
branch.gsub!(/^#{indent} /, indent + '│') unless last_node
str << branch
end
return str
end
def self.build_tree(mods, dir)
mods.each do |mod|
version_string = mod[:version].to_s.sub(/^(?!v)/, 'v')
if mod[:action] == :upgrade
previous_version = mod[:previous_version].to_s.sub(/^(?!v)/, 'v')
version_string = "#{previous_version} -> #{version_string}"
end
mod[:text] = "#{mod[:name]} (#{colorize(:cyan, version_string)})"
mod[:text] += " [#{mod[:path]}]" unless mod[:path].to_s == dir.to_s
deps = (mod[:dependencies] || [])
deps.sort! { |a, b| a[:name] <=> b[:name] }
build_tree(deps, dir)
end
end
# @param options [Hash] This hash will contain any
# command-line arguments that are not Settings, as those will have already
# been extracted by the underlying application code.
#
# @note Unfortunately the whole point of this method is the side effect of
# modifying the options parameter. This same hash is referenced both
# when_invoked and when_rendering. For this reason, we are not returning
# a duplicate.
# @todo Validate the above note...
#
# An :environment_instance and a :target_dir are added/updated in the
# options parameter.
#
# @api private
def self.set_option_defaults(options)
current_environment = environment_from_options(options)
modulepath = [options[:target_dir]] + current_environment.full_modulepath
face_environment = current_environment.override_with(:modulepath => modulepath.compact)
options[:environment_instance] = face_environment
# Note: environment will have expanded the path
options[:target_dir] = face_environment.full_modulepath.first
end
# Given a hash of options, we should discover or create a
# {Puppet::Node::Environment} instance that reflects the provided options.
#
# Generally speaking, the `:modulepath` parameter should supersede all
# others, the `:environment` parameter should follow after that, and we
# should default to Puppet's current environment.
#
# @param options [{Symbol => Object}] the options to derive environment from
# @return [Puppet::Node::Environment] the environment described by the options
def self.environment_from_options(options)
if options[:modulepath]
path = options[:modulepath].split(File::PATH_SEPARATOR)
Puppet::Node::Environment.create(:anonymous, path, '')
elsif options[:environment].is_a?(Puppet::Node::Environment)
options[:environment]
elsif options[:environment]
# This use of looking up an environment is correct since it honours
# a request to get a particular environment via environment name.
Puppet.lookup(:environments).get!(options[:environment])
else
Puppet.lookup(:current_environment)
end
end
# Handles parsing of module dependency expressions into proper
# {SemanticPuppet::VersionRange}s, including reasonable error handling.
#
# @param where [String] a description of the thing we're parsing the
# dependency expression for
# @param dep [Hash] the dependency description to parse
# @return [Array(String, SemanticPuppet::VersionRange, String)] a tuple of the
# dependent module's name, the version range dependency, and the
# unparsed range expression.
def self.parse_module_dependency(where, dep)
dep_name = dep['name'].tr('/', '-')
range = dep['version_requirement'] || '>= 0.0.0'
begin
parsed_range = Module.parse_range(range)
rescue ArgumentError => e
Puppet.debug "Error in #{where} parsing dependency #{dep_name} (#{e.message}); using empty range."
parsed_range = SemanticPuppet::VersionRange::EMPTY_RANGE
end
[ dep_name, parsed_range, range ]
end
end
end
# Load remaining libraries
require_relative 'module_tool/errors'
require_relative 'module_tool/applications'
require_relative 'module_tool/checksums'
require_relative 'module_tool/contents_description'
require_relative 'module_tool/dependency'
require_relative 'module_tool/metadata'
require_relative '../puppet/forge/cache'
require_relative '../puppet/forge'
puppet-8.4.0/lib/puppet/file_system/ 0000755 0052762 0001160 00000000000 14552052637 017347 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/file_system/memory_file.rb 0000644 0052762 0001160 00000003512 14552052437 022202 0 ustar jenkins jenkins # frozen_string_literal: true
# An in-memory file abstraction. Commonly used with Puppet::FileSystem::File#overlay
# @api private
class Puppet::FileSystem::MemoryFile
attr_reader :path, :children
def self.a_missing_file(path)
new(path, :exist? => false, :executable? => false)
end
def self.a_missing_directory(path)
new(path,
:exist? => false,
:executable? => false,
:directory? => true)
end
def self.a_regular_file_containing(path, content)
new(path, :exist? => true, :executable? => false, :content => content)
end
def self.an_executable(path)
new(path, :exist? => true, :executable? => true)
end
def self.a_directory(path, children = [])
new(path,
:exist? => true,
:executable? => true,
:directory? => true,
:children => children)
end
def self.a_symlink(target_path, source_path)
new(target_path, :exist? => true, :symlink? => true, :source_path => source_path)
end
def initialize(path, properties)
@path = path
@properties = properties
@children = (properties[:children] || []).collect do |child|
child.duplicate_as(File.join(@path, child.path))
end
end
def directory?; @properties[:directory?]; end
def exist?; @properties[:exist?]; end
def executable?; @properties[:executable?]; end
def symlink?; @properties[:symlink?]; end
def source_path; @properties[:source_path]; end
def each_line(&block)
handle.each_line(&block)
end
def handle
raise Errno::ENOENT unless exist?
StringIO.new(@properties[:content] || '')
end
def duplicate_as(other_path)
self.class.new(other_path, @properties)
end
def absolute?
Pathname.new(path).absolute?
end
def to_path
path
end
def to_s
to_path
end
def inspect
""
end
end
puppet-8.4.0/lib/puppet/file_system/file_impl.rb 0000644 0052762 0001160 00000010015 14552052437 021627 0 ustar jenkins jenkins # frozen_string_literal: true
# Abstract implementation of the Puppet::FileSystem
#
class Puppet::FileSystem::FileImpl
def pathname(path)
path.is_a?(Pathname) ? path : Pathname.new(path)
end
def assert_path(path)
return path if path.is_a?(Pathname)
# Some paths are string, or in the case of WatchedFile, it pretends to be
# one by implementing to_str.
if path.respond_to?(:to_str)
Pathname.new(path)
else
raise ArgumentError, _("FileSystem implementation expected Pathname, got: '%{klass}'") % { klass: path.class }
end
end
def path_string(path)
path.to_s
end
def expand_path(path, dir_string = nil)
# ensure `nil` values behave like underlying File.expand_path
::File.expand_path(path.nil? ? nil : path_string(path), dir_string)
end
def open(path, mode, options, &block)
::File.open(path, options, mode, &block)
end
def dir(path)
path.dirname
end
def basename(path)
path.basename.to_s
end
def size(path)
path.size
end
def exclusive_create(path, mode, &block)
opt = File::CREAT | File::EXCL | File::WRONLY
self.open(path, mode, opt, &block)
end
def exclusive_open(path, mode, options = 'r', timeout = 300, &block)
wait = 0.001 + (Kernel.rand / 1000)
written = false
while !written
::File.open(path, options, mode) do |rf|
if rf.flock(::File::LOCK_EX|::File::LOCK_NB)
Puppet.debug{ _("Locked '%{path}'") % { path: path } }
yield rf
written = true
Puppet.debug{ _("Unlocked '%{path}'") % { path: path } }
else
Puppet.debug{ "Failed to lock '%s' retrying in %.2f milliseconds" % [path, wait * 1000] }
sleep wait
timeout -= wait
wait *= 2
if timeout < 0
raise Timeout::Error, _("Timeout waiting for exclusive lock on %{path}") % { path: path }
end
end
end
end
end
def each_line(path, &block)
::File.open(path) do |f|
f.each_line do |line|
yield line
end
end
end
def read(path, opts = {})
path.read(**opts)
end
def read_preserve_line_endings(path)
default_encoding = Encoding.default_external.name
encoding = default_encoding.downcase.start_with?('utf-') ? "bom|#{default_encoding}" : default_encoding
read(path, encoding: encoding)
end
def binread(path)
raise NotImplementedError
end
def exist?(path)
::File.exist?(path)
end
def directory?(path)
::File.directory?(path)
end
def file?(path)
::File.file?(path)
end
def executable?(path)
::File.executable?(path)
end
def writable?(path)
path.writable?
end
def touch(path, mtime: nil)
::FileUtils.touch(path, mtime: mtime)
end
def mkpath(path)
path.mkpath
end
def children(path)
path.children
end
def symlink(path, dest, options = {})
FileUtils.symlink(path, dest, **options)
end
def symlink?(path)
::File.symlink?(path)
end
def readlink(path)
::File.readlink(path)
end
def unlink(*paths)
::File.unlink(*paths)
end
def stat(path)
::File.stat(path)
end
def lstat(path)
::File.lstat(path)
end
def compare_stream(path, stream)
::File.open(path, 0, 'rb') { |this| FileUtils.compare_stream(this, stream) }
end
def chmod(mode, path)
FileUtils.chmod(mode, path)
end
def replace_file(path, mode = nil)
begin
stat = lstat(path)
gid = stat.gid
uid = stat.uid
mode ||= stat.mode & 07777
rescue Errno::ENOENT
mode ||= 0640
end
tempfile = Puppet::FileSystem::Uniquefile.new(Puppet::FileSystem.basename_string(path), Puppet::FileSystem.dir_string(path))
begin
begin
yield tempfile
tempfile.flush
tempfile.fsync
ensure
tempfile.close
end
tempfile_path = tempfile.path
FileUtils.chown(uid, gid, tempfile_path) if uid && gid
chmod(mode, tempfile_path)
::File.rename(tempfile_path, path_string(path))
ensure
tempfile.close!
end
end
end
puppet-8.4.0/lib/puppet/file_system/windows.rb 0000644 0052762 0001160 00000015622 14552052437 021372 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/file_system/posix'
require_relative '../../puppet/util/windows'
class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
FULL_CONTROL = Puppet::Util::Windows::File::FILE_ALL_ACCESS
FILE_READ = Puppet::Util::Windows::File::FILE_GENERIC_READ
def open(path, mode, options, &block)
# PUP-6959 mode is explicitly ignored until it can be implemented
# Ruby on Windows uses mode for setting file attributes like read-only and
# archived, not for setting permissions like POSIX
raise TypeError.new('mode must be specified as an Integer') if mode && !mode.is_a?(Numeric)
::File.open(path, options, nil, &block)
end
def expand_path(path, dir_string = nil)
# ensure `nil` values behave like underlying File.expand_path
string_path = ::File.expand_path(path.nil? ? nil : path_string(path), dir_string)
# if no tildes, nothing to expand, no need to call Windows API, return original string
return string_path if !string_path.index('~')
begin
# no need to do existence check up front as GetLongPathName implies that check is performed
# and it should be the exception that files aren't actually present
string_path = Puppet::Util::Windows::File.get_long_pathname(string_path)
rescue Puppet::Util::Windows::Error => e
# preserve original File.expand_path behavior for file / path not found by returning string
raise if (e.code != Puppet::Util::Windows::File::ERROR_FILE_NOT_FOUND &&
e.code != Puppet::Util::Windows::File::ERROR_PATH_NOT_FOUND)
end
string_path
end
def exist?(path)
return Puppet::Util::Windows::File.exist?(path)
end
def symlink(path, dest, options = {})
raise_if_symlinks_unsupported
dest_exists = exist?(dest) # returns false on dangling symlink
dest_stat = Puppet::Util::Windows::File.stat(dest) if dest_exists
# silent fail to preserve semantics of original FileUtils
return 0 if dest_exists && dest_stat.ftype == 'directory'
if dest_exists && dest_stat.ftype == 'file' && options[:force] != true
raise(Errno::EEXIST, _("%{dest} already exists and the :force option was not specified") % { dest: dest })
end
if options[:noop] != true
::File.delete(dest) if dest_exists # can only be file
Puppet::Util::Windows::File.symlink(path, dest)
end
0
end
def symlink?(path)
return false if ! Puppet.features.manages_symlinks?
Puppet::Util::Windows::File.symlink?(path)
end
def readlink(path)
raise_if_symlinks_unsupported
Puppet::Util::Windows::File.readlink(path)
end
def unlink(*file_names)
if ! Puppet.features.manages_symlinks?
return ::File.unlink(*file_names)
end
file_names.each do |file_name|
file_name = file_name.to_s # handle PathName
stat = Puppet::Util::Windows::File.stat(file_name) rescue nil
# sigh, Ruby + Windows :(
if !stat
::File.unlink(file_name) rescue Dir.rmdir(file_name)
elsif stat.ftype == 'directory'
if Puppet::Util::Windows::File.symlink?(file_name)
Dir.rmdir(file_name)
else
raise Errno::EPERM.new(file_name)
end
else
::File.unlink(file_name)
end
end
file_names.length
end
def stat(path)
Puppet::Util::Windows::File.stat(path)
end
def lstat(path)
if ! Puppet.features.manages_symlinks?
return Puppet::Util::Windows::File.stat(path)
end
Puppet::Util::Windows::File.lstat(path)
end
def chmod(mode, path)
Puppet::Util::Windows::Security.set_mode(mode, path.to_s)
end
def read_preserve_line_endings(path)
contents = path.read( :mode => 'rb', :encoding => 'bom|utf-8')
contents = path.read( :mode => 'rb', :encoding => "bom|#{Encoding::default_external.name}") unless contents.valid_encoding?
contents = path.read unless contents.valid_encoding?
contents
end
# https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--0-499-
FILE_NOT_FOUND = 2
ACCESS_DENIED = 5
SHARING_VIOLATION = 32
LOCK_VIOLATION = 33
def replace_file(path, mode = nil)
if directory?(path)
raise Errno::EISDIR, _("Is a directory: %{directory}") % { directory: path }
end
current_sid = Puppet::Util::Windows::SID.name_to_sid(Puppet::Util::Windows::ADSI::User.current_user_name)
current_sid = Puppet::Util::Windows::SID.name_to_sid(Puppet::Util::Windows::ADSI::User.current_sam_compatible_user_name) unless current_sid
dacl = case mode
when 0644
dacl = secure_dacl(current_sid)
dacl.allow(Puppet::Util::Windows::SID::BuiltinUsers, FILE_READ)
dacl
when 0660, 0640, 0600, 0440
secure_dacl(current_sid)
when nil
get_dacl_from_file(path) || secure_dacl(current_sid)
else
raise ArgumentError, "#{mode} is invalid: Only modes 0644, 0640, 0660, and 0440 are allowed"
end
tempfile = Puppet::FileSystem::Uniquefile.new(Puppet::FileSystem.basename_string(path), Puppet::FileSystem.dir_string(path))
begin
tempdacl = Puppet::Util::Windows::AccessControlList.new
tempdacl.allow(current_sid, FULL_CONTROL)
set_dacl(tempfile.path, tempdacl)
begin
yield tempfile
tempfile.flush
tempfile.fsync
ensure
tempfile.close
end
set_dacl(tempfile.path, dacl) if dacl
::File.rename(tempfile.path, path_string(path))
ensure
tempfile.close!
end
rescue Puppet::Util::Windows::Error => e
case e.code
when ACCESS_DENIED, SHARING_VIOLATION, LOCK_VIOLATION
raise Errno::EACCES.new(path_string(path), e)
else
raise SystemCallError.new(e.message)
end
end
private
def set_dacl(path, dacl)
sd = Puppet::Util::Windows::Security.get_security_descriptor(path)
new_sd = Puppet::Util::Windows::SecurityDescriptor.new(sd.owner, sd.group, dacl, true)
Puppet::Util::Windows::Security.set_security_descriptor(path, new_sd)
end
def secure_dacl(current_sid)
dacl = Puppet::Util::Windows::AccessControlList.new
[
Puppet::Util::Windows::SID::LocalSystem,
Puppet::Util::Windows::SID::BuiltinAdministrators,
current_sid
].uniq.map do |sid|
dacl.allow(sid, FULL_CONTROL)
end
dacl
end
def get_dacl_from_file(path)
sd = Puppet::Util::Windows::Security.get_security_descriptor(path_string(path))
sd.dacl
rescue Puppet::Util::Windows::Error => e
raise e unless e.code == FILE_NOT_FOUND
end
def raise_if_symlinks_unsupported
if ! Puppet.features.manages_symlinks?
msg = _("This version of Windows does not support symlinks. Windows Vista / 2008 or higher is required.")
raise Puppet::Util::Windows::Error.new(msg)
end
if ! Puppet::Util::Windows::Process.process_privilege_symlink?
Puppet.warning _("The current user does not have the necessary permission to manage symlinks.")
end
end
end
puppet-8.4.0/lib/puppet/file_system/uniquefile.rb 0000644 0052762 0001160 00000010237 14552052437 022043 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/file_system'
require 'delegate'
require 'tmpdir'
# A class that provides `Tempfile`-like capabilities, but does not attempt to
# manage the deletion of the file for you. API is identical to the
# normal `Tempfile` class.
#
# @api public
class Puppet::FileSystem::Uniquefile < DelegateClass(File)
# Convenience method which ensures that the file is closed and
# unlinked before returning
#
# @param identifier [String] additional part of generated pathname
# @yieldparam file [File] the temporary file object
# @return result of the passed block
# @api private
def self.open_tmp(identifier)
f = new(identifier)
yield f
ensure
if f
f.close!
end
end
def initialize(basename, *rest)
create_tmpname(basename, *rest) do |tmpname, _n, opts|
mode = File::RDWR|File::CREAT|File::EXCL
perm = 0600
if opts
mode |= opts.delete(:mode) || 0
opts[:perm] = perm
perm = nil
else
opts = perm
end
self.class.locking(tmpname) do
@tmpfile = File.open(tmpname, mode, opts)
@tmpname = tmpname
end
@mode = mode & ~(File::CREAT|File::EXCL)
perm or opts.freeze
@opts = opts
end
super(@tmpfile)
end
# Opens or reopens the file with mode "r+".
def open
@tmpfile.close if @tmpfile
@tmpfile = File.open(@tmpname, @mode, @opts)
__setobj__(@tmpfile)
end
def _close
begin
@tmpfile.close if @tmpfile
ensure
@tmpfile = nil
end
end
protected :_close
def close(unlink_now=false)
if unlink_now
close!
else
_close
end
end
def close!
_close
unlink
end
def unlink
return unless @tmpname
begin
File.unlink(@tmpname)
rescue Errno::ENOENT
rescue Errno::EACCES
# may not be able to unlink on Windows; just ignore
return
end
@tmpname = nil
end
alias delete unlink
# Returns the full path name of the temporary file.
# This will be nil if #unlink has been called.
def path
@tmpname
end
private
def make_tmpname(prefix_suffix, n)
case prefix_suffix
when String
prefix = prefix_suffix
suffix = ""
when Array
prefix = prefix_suffix[0]
suffix = prefix_suffix[1]
else
raise ArgumentError, _("unexpected prefix_suffix: %{value}") % { value: prefix_suffix.inspect }
end
t = Time.now.strftime("%Y%m%d")
path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
path << "-#{n}" if n
path << suffix
end
def create_tmpname(basename, *rest)
opts = try_convert_to_hash(rest[-1])
if opts
opts = opts.dup if rest.pop.equal?(opts)
max_try = opts.delete(:max_try)
opts = [opts]
else
opts = []
end
tmpdir, = *rest
tmpdir ||= tmpdir()
n = nil
begin
path = File.join(tmpdir, make_tmpname(basename, n))
yield(path, n, *opts)
rescue Errno::EEXIST
n ||= 0
n += 1
retry if !max_try or n < max_try
raise _("cannot generate temporary name using `%{basename}' under `%{tmpdir}'") % { basename: basename, tmpdir: tmpdir }
end
path
end
def try_convert_to_hash(h)
begin
h.to_hash
rescue NoMethodError
nil
end
end
@@systmpdir ||= defined?(Etc.systmpdir) ? Etc.systmpdir : '/tmp'
def tmpdir
tmp = '.'
for dir in [ ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp']
stat = File.stat(dir) if dir
if stat && stat.directory? && stat.writable?
tmp = dir
break
end rescue nil
end
File.expand_path(tmp)
end
class << self
# yields with locking for +tmpname+ and returns the result of the
# block.
def locking(tmpname)
lock = tmpname + '.lock'
mkdir(lock)
yield
rescue Errno::ENOENT => e
ex = Errno::ENOENT.new("A directory component in #{lock} does not exist or is a dangling symbolic link")
ex.set_backtrace(e.backtrace)
raise ex
ensure
rmdir(lock) if Puppet::FileSystem.exist?(lock)
end
def mkdir(*args)
Dir.mkdir(*args)
end
def rmdir(*args)
Dir.rmdir(*args)
end
end
end
puppet-8.4.0/lib/puppet/file_system/path_pattern.rb 0000644 0052762 0001160 00000004430 14552052437 022364 0 ustar jenkins jenkins # frozen_string_literal: true
require 'pathname'
require_relative '../../puppet/error'
module Puppet::FileSystem
class PathPattern
class InvalidPattern < Puppet::Error; end
DOTDOT = '..'
ABSOLUTE_UNIX = /^\//
ABSOLUTE_WINDOWS = /^[a-z]:/i
CURRENT_DRIVE_RELATIVE_WINDOWS = /^\\/
def self.relative(pattern)
RelativePathPattern.new(pattern)
end
def self.absolute(pattern)
AbsolutePathPattern.new(pattern)
end
class << self
protected :new
end
# @param prefix [AbsolutePathPattern] An absolute path pattern instance
# @return [AbsolutePathPattern] A new AbsolutePathPattern prepended with
# the passed prefix's pattern.
def prefix_with(prefix)
new_pathname = prefix.pathname + pathname
self.class.absolute(new_pathname.to_s)
end
def glob
Dir.glob(@pathstr)
end
def to_s
@pathstr
end
protected
attr_reader :pathname
private
def validate
if @pathstr.split(Pathname::SEPARATOR_PAT).any? { |f| f == DOTDOT }
raise(InvalidPattern, _("PathPatterns cannot be created with directory traversals."))
elsif @pathstr.match?(CURRENT_DRIVE_RELATIVE_WINDOWS)
raise(InvalidPattern, _("A PathPattern cannot be a Windows current drive relative path."))
end
end
def initialize(pattern)
begin
@pathname = Pathname.new(pattern.strip)
@pathstr = @pathname.to_s
rescue ArgumentError => error
raise InvalidPattern.new(_("PathPatterns cannot be created with a zero byte."), error)
end
validate
end
end
class RelativePathPattern < PathPattern
def absolute?
false
end
def validate
super
if @pathstr.match?(ABSOLUTE_WINDOWS)
raise(InvalidPattern, _("A relative PathPattern cannot be prefixed with a drive."))
elsif @pathstr.match?(ABSOLUTE_UNIX)
raise(InvalidPattern, _("A relative PathPattern cannot be an absolute path."))
end
end
end
class AbsolutePathPattern < PathPattern
def absolute?
true
end
def validate
super
if !@pathstr.match?(ABSOLUTE_UNIX) && !@pathstr.match?(ABSOLUTE_WINDOWS)
raise(InvalidPattern, _("An absolute PathPattern cannot be a relative path."))
end
end
end
end
puppet-8.4.0/lib/puppet/file_system/memory_impl.rb 0000644 0052762 0001160 00000003600 14552052437 022222 0 ustar jenkins jenkins # frozen_string_literal: true
class Puppet::FileSystem::MemoryImpl
def initialize(*files)
@files = files + all_children_of(files)
end
def expand_path(path, dir_string = nil)
File.expand_path(path, dir_string)
end
def exist?(path)
path.exist?
end
def directory?(path)
path.directory?
end
def file?(path)
path.file?
end
def executable?(path)
path.executable?
end
def symlink?(path)
path.symlink?
end
def readlink(path)
path = path.path
link = find(path)
return Puppet::FileSystem::MemoryFile.a_missing_file(path) unless link
source = link.source_path
return Puppet::FileSystem::MemoryFile.a_missing_file(link) unless source
find(source) || Puppet::FileSystem::MemoryFile.a_missing_file(source)
end
def children(path)
path.children
end
def each_line(path, &block)
path.each_line(&block)
end
def pathname(path)
find(path) || Puppet::FileSystem::MemoryFile.a_missing_file(path)
end
def basename(path)
path.duplicate_as(File.basename(path_string(path)))
end
def path_string(object)
object.path
end
def read(path, opts = {})
handle = assert_path(path).handle
handle.read
end
def read_preserve_line_endings(path)
read(path)
end
def open(path, *args, &block)
handle = assert_path(path).handle
if block_given?
yield handle
else
return handle
end
end
def assert_path(path)
if path.is_a?(Puppet::FileSystem::MemoryFile)
path
else
find(path) or raise ArgumentError, _("Unable to find registered object for %{path}") % { path: path.inspect }
end
end
private
def find(path)
@files.find { |file| file.path == path }
end
def all_children_of(files)
children = files.collect(&:children).flatten
if children.empty?
[]
else
children + all_children_of(children)
end
end
end
puppet-8.4.0/lib/puppet/file_system/posix.rb 0000644 0052762 0001160 00000002303 14552052437 021032 0 ustar jenkins jenkins # frozen_string_literal: true
class Puppet::FileSystem::Posix < Puppet::FileSystem::FileImpl
def binread(path)
path.binread
end
# Provide an encoding agnostic version of compare_stream
#
# The FileUtils implementation in Ruby 2.0+ was modified in a manner where
# it cannot properly compare File and StringIO instances. To sidestep that
# issue this method reimplements the faster 2.0 version that will correctly
# compare binary File and StringIO streams.
def compare_stream(path, stream)
::File.open(path, 'rb') do |this|
bsize = stream_blksize(this, stream)
sa = String.new.force_encoding('ASCII-8BIT')
sb = String.new.force_encoding('ASCII-8BIT')
loop do
this.read(bsize, sa)
stream.read(bsize, sb)
return true if sa.empty? && sb.empty?
break if sa != sb
end
false
end
end
private
def stream_blksize(*streams)
streams.each do |s|
next unless s.respond_to?(:stat)
size = blksize(s.stat)
return size if size
end
default_blksize()
end
def blksize(st)
s = st.blksize
return nil unless s
return nil if s == 0
s
end
def default_blksize
1024
end
end
puppet-8.4.0/lib/puppet/file_system/jruby.rb 0000644 0052762 0001160 00000001446 14552052437 021032 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/file_system/posix'
class Puppet::FileSystem::JRuby < Puppet::FileSystem::Posix
def unlink(*paths)
File.unlink(*paths)
rescue Errno::ENOENT
# JRuby raises ENOENT if the path doesn't exist or the parent directory
# doesn't allow execute/traverse. If it's the former, `stat` will raise
# ENOENT, if it's the later, it'll raise EACCES
# See https://github.com/jruby/jruby/issues/5617
stat(*paths)
end
def replace_file(path, mode = nil, &block)
# MRI Ruby rename checks if destination is a directory and raises, while
# JRuby removes the directory and replaces the file.
if directory?(path)
raise Errno::EISDIR, _("Is a directory: %{directory}") % { directory: path }
end
super
end
end
puppet-8.4.0/lib/puppet/module.rb 0000644 0052762 0001160 00000032362 14552052437 016642 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../puppet/util/logging'
require_relative 'module/task'
require_relative 'module/plan'
require_relative '../puppet/util/json'
require 'semantic_puppet/gem_version'
# Support for modules
class Puppet::Module
class Error < Puppet::Error; end
class MissingModule < Error; end
class IncompatibleModule < Error; end
class UnsupportedPlatform < Error; end
class IncompatiblePlatform < Error; end
class MissingMetadata < Error; end
class FaultyMetadata < Error; end
class InvalidName < Error; end
class InvalidFilePattern < Error; end
include Puppet::Util::Logging
FILETYPES = {
"manifests" => "manifests",
"files" => "files",
"templates" => "templates",
"plugins" => "lib",
"pluginfacts" => "facts.d",
"locales" => "locales",
"scripts" => "scripts",
}
# Find and return the +module+ that +path+ belongs to. If +path+ is
# absolute, or if there is no module whose name is the first component
# of +path+, return +nil+
def self.find(modname, environment = nil)
return nil unless modname
# Unless a specific environment is given, use the current environment
env = environment ? Puppet.lookup(:environments).get!(environment) : Puppet.lookup(:current_environment)
env.module(modname)
end
def self.is_module_directory?(name, path)
# it must be a directory
fullpath = File.join(path, name)
return false unless Puppet::FileSystem.directory?(fullpath)
return is_module_directory_name?(name)
end
def self.is_module_directory_name?(name)
# it must match an installed module name according to forge validator
return true if name =~ /^[a-z][a-z0-9_]*$/
return false
end
def self.is_module_namespaced_name?(name)
# it must match the full module name according to forge validator
return true if name =~ /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
return false
end
# @api private
def self.parse_range(range)
SemanticPuppet::VersionRange.parse(range)
end
attr_reader :name, :environment, :path, :metadata
attr_writer :environment
attr_accessor :dependencies, :forge_name
attr_accessor :source, :author, :version, :license, :summary, :description, :project_page
def initialize(name, path, environment)
@name = name
@path = path
@environment = environment
assert_validity
load_metadata
@absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(manifests)
end
# @deprecated The puppetversion module metadata field is no longer used.
def puppetversion
nil
end
# @deprecated The puppetversion module metadata field is no longer used.
def puppetversion=(something)
end
# @deprecated The puppetversion module metadata field is no longer used.
def validate_puppet_version
return
end
def has_metadata?
begin
load_metadata
@metadata.is_a?(Hash) && !@metadata.empty?
rescue Puppet::Module::MissingMetadata
false
end
end
FILETYPES.each do |type, location|
# A boolean method to let external callers determine if
# we have files of a given type.
define_method(type + '?') do
type_subpath = subpath(location)
unless Puppet::FileSystem.exist?(type_subpath)
Puppet.debug { "No #{type} found in subpath '#{type_subpath}' (file / directory does not exist)" }
return false
end
return true
end
# A method for returning a given file of a given type.
# e.g., file = mod.manifest("my/manifest.pp")
#
# If the file name is nil, then the base directory for the
# file type is passed; this is used for fileserving.
define_method(type.sub(/s$/, '')) do |file|
# If 'file' is nil then they're asking for the base path.
# This is used for things like fileserving.
if file
full_path = File.join(subpath(location), file)
else
full_path = subpath(location)
end
return nil unless Puppet::FileSystem.exist?(full_path)
return full_path
end
# Return the base directory for the given type
define_method(type) do
subpath(location)
end
end
def tasks_directory
subpath("tasks")
end
def tasks
return @tasks if instance_variable_defined?(:@tasks)
if Puppet::FileSystem.exist?(tasks_directory)
@tasks = Puppet::Module::Task.tasks_in_module(self)
else
@tasks = []
end
end
# This is a re-implementation of the Filetypes singular type method (e.g.
# `manifest('my/manifest.pp')`. We don't implement the full filetype "API" for
# tasks since tasks don't map 1:1 onto files.
def task_file(name)
# If 'file' is nil then they're asking for the base path.
# This is used for things like fileserving.
if name
full_path = File.join(tasks_directory, name)
else
full_path = tasks_directory
end
if Puppet::FileSystem.exist?(full_path)
return full_path
else
return nil
end
end
def plans_directory
subpath("plans")
end
def plans
return @plans if instance_variable_defined?(:@plans)
if Puppet::FileSystem.exist?(plans_directory)
@plans = Puppet::Module::Plan.plans_in_module(self)
else
@plans = []
end
end
# This is a re-implementation of the Filetypes singular type method (e.g.
# `manifest('my/manifest.pp')`. We don't implement the full filetype "API" for
# plans.
def plan_file(name)
# If 'file' is nil then they're asking for the base path.
# This is used for things like fileserving.
if name
full_path = File.join(plans_directory, name)
else
full_path = plans_directory
end
if Puppet::FileSystem.exist?(full_path)
return full_path
else
return nil
end
end
def license_file
return @license_file if defined?(@license_file)
return @license_file = nil unless path
@license_file = File.join(path, "License")
end
def read_metadata
md_file = metadata_file
return {} if md_file.nil?
content = File.read(md_file, :encoding => 'utf-8')
content.empty? ? {} : Puppet::Util::Json.load(content)
rescue Errno::ENOENT
{}
rescue Puppet::Util::Json::ParseError => e
# TRANSLATORS 'metadata.json' is a specific file name and should not be translated.
msg = _("%{name} has an invalid and unparsable metadata.json file. The parse error: %{error}") % { name: name, error: e.message }
case Puppet[:strict]
when :off
Puppet.debug(msg)
when :warning
Puppet.warning(msg)
when :error
raise FaultyMetadata, msg
end
{}
end
def load_metadata
return if instance_variable_defined?(:@metadata)
@metadata = data = read_metadata
return if data.empty?
@forge_name = data['name'].tr('-', '/') if data['name']
[:source, :author, :version, :license, :dependencies].each do |attr|
value = data[attr.to_s]
raise MissingMetadata, "No #{attr} module metadata provided for #{self.name}" if value.nil?
if attr == :dependencies
unless value.is_a?(Array)
raise MissingMetadata, "The value for the key dependencies in the file metadata.json of the module #{self.name} must be an array, not: '#{value}'"
end
value.each do |dep|
name = dep['name']
dep['name'] = name.tr('-', '/') unless name.nil?
dep['version_requirement'] ||= '>= 0.0.0'
end
end
send(attr.to_s + "=", value)
end
end
# Return the list of manifests matching the given glob pattern,
# defaulting to 'init.pp' for empty modules.
def match_manifests(rest)
if rest
wanted_manifests = wanted_manifests_from(rest)
searched_manifests = wanted_manifests.glob.reject { |f| FileTest.directory?(f) }
else
searched_manifests = []
end
# (#4220) Always ensure init.pp in case class is defined there.
init_manifest = manifest("init.pp")
if !init_manifest.nil? && !searched_manifests.include?(init_manifest)
searched_manifests.unshift(init_manifest)
end
searched_manifests
end
def all_manifests
return [] unless Puppet::FileSystem.exist?(manifests)
Dir.glob(File.join(manifests, '**', '*.pp'))
end
def metadata_file
return @metadata_file if defined?(@metadata_file)
return @metadata_file = nil unless path
@metadata_file = File.join(path, "metadata.json")
end
def hiera_conf_file
unless defined?(@hiera_conf_file)
@hiera_conf_file = path.nil? ? nil : File.join(path, Puppet::Pops::Lookup::HieraConfig::CONFIG_FILE_NAME)
end
@hiera_conf_file
end
def has_hiera_conf?
hiera_conf_file.nil? ? false : Puppet::FileSystem.exist?(hiera_conf_file)
end
def modulepath
File.dirname(path) if path
end
# Find all plugin directories. This is used by the Plugins fileserving mount.
def plugin_directory
subpath("lib")
end
def plugin_fact_directory
subpath("facts.d")
end
# @return [String]
def locale_directory
subpath("locales")
end
# Returns true if the module has translation files for the
# given locale.
# @param [String] locale the two-letter language code to check
# for translations
# @return true if the module has a directory for the locale, false
# false otherwise
def has_translations?(locale)
return Puppet::FileSystem.exist?(File.join(locale_directory, locale))
end
def has_external_facts?
File.directory?(plugin_fact_directory)
end
def supports(name, version = nil)
@supports ||= []
@supports << [name, version]
end
def to_s
result = "Module #{name}"
result += "(#{path})" if path
result
end
def dependencies_as_modules
dependent_modules = []
dependencies and dependencies.each do |dep|
_, dep_name = dep["name"].split('/')
found_module = environment.module(dep_name)
dependent_modules << found_module if found_module
end
dependent_modules
end
def required_by
environment.module_requirements[self.forge_name] || {}
end
# Identify and mark unmet dependencies. A dependency will be marked unmet
# for the following reasons:
#
# * not installed and is thus considered missing
# * installed and does not meet the version requirements for this module
# * installed and doesn't use semantic versioning
#
# Returns a list of hashes representing the details of an unmet dependency.
#
# Example:
#
# [
# {
# :reason => :missing,
# :name => 'puppetlabs-mysql',
# :version_constraint => 'v0.0.1',
# :mod_details => {
# :installed_version => '0.0.1'
# }
# :parent => {
# :name => 'puppetlabs-bacula',
# :version => 'v1.0.0'
# }
# }
# ]
#
def unmet_dependencies
unmet_dependencies = []
return unmet_dependencies unless dependencies
dependencies.each do |dependency|
name = dependency['name']
version_string = dependency['version_requirement'] || '>= 0.0.0'
dep_mod = begin
environment.module_by_forge_name(name)
rescue
nil
end
error_details = {
:name => name,
:version_constraint => version_string.gsub(/^(?=\d)/, "v"),
:parent => {
:name => self.forge_name,
:version => self.version.gsub(/^(?=\d)/, "v")
},
:mod_details => {
:installed_version => dep_mod.nil? ? nil : dep_mod.version
}
}
unless dep_mod
error_details[:reason] = :missing
unmet_dependencies << error_details
next
end
if version_string
begin
required_version_semver_range = self.class.parse_range(version_string)
actual_version_semver = SemanticPuppet::Version.parse(dep_mod.version)
rescue ArgumentError
error_details[:reason] = :non_semantic_version
unmet_dependencies << error_details
next
end
unless required_version_semver_range.include? actual_version_semver
error_details[:reason] = :version_mismatch
unmet_dependencies << error_details
next
end
end
end
unmet_dependencies
end
def ==(other)
self.name == other.name &&
self.version == other.version &&
self.path == other.path &&
self.environment == other.environment
end
private
def wanted_manifests_from(pattern)
begin
extended = File.extname(pattern).empty? ? "#{pattern}.pp" : pattern
relative_pattern = Puppet::FileSystem::PathPattern.relative(extended)
rescue Puppet::FileSystem::PathPattern::InvalidPattern => error
raise Puppet::Module::InvalidFilePattern.new(
"The pattern \"#{pattern}\" to find manifests in the module \"#{name}\" " +
"is invalid and potentially unsafe.", error)
end
relative_pattern.prefix_with(@absolute_path_to_manifests)
end
def subpath(type)
File.join(path, type)
end
def assert_validity
if !Puppet::Module.is_module_directory_name?(@name) && !Puppet::Module.is_module_namespaced_name?(@name)
raise InvalidName, _(<<-ERROR_STRING).chomp % { name: @name }
Invalid module name '%{name}'; module names must match either:
An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or-
A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
ERROR_STRING
end
end
end
puppet-8.4.0/lib/puppet/application/ 0000755 0052762 0001160 00000000000 14552052637 017327 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/application/module.rb 0000644 0052762 0001160 00000000234 14552052437 021136 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
class Puppet::Application::Module < Puppet::Application::FaceBase
end
puppet-8.4.0/lib/puppet/application/plugin.rb 0000644 0052762 0001160 00000000274 14552052437 021153 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
class Puppet::Application::Plugin < Puppet::Application::FaceBase
environment_mode :not_required
end
puppet-8.4.0/lib/puppet/application/help.rb 0000644 0052762 0001160 00000000273 14552052437 020604 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
class Puppet::Application::Help < Puppet::Application::FaceBase
environment_mode :not_required
end
puppet-8.4.0/lib/puppet/application/facts.rb 0000644 0052762 0001160 00000000762 14552052437 020757 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/indirection_base'
class Puppet::Application::Facts < Puppet::Application::IndirectionBase
# Allows `puppet facts` actions to be run against environments that
# don't exist locally, such as using the `--environment` flag to make a REST
# request to a specific environment on a master. There is no way to set this
# behavior per-action, so it must be set for the face as a whole.
environment_mode :not_required
end
puppet-8.4.0/lib/puppet/application/lookup.rb 0000644 0052762 0001160 00000040264 14552052437 021171 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/pops'
require_relative '../../puppet/node'
require_relative '../../puppet/parser/compiler'
class Puppet::Application::Lookup < Puppet::Application
RUN_HELP = _("Run 'puppet lookup --help' for more details").freeze
DEEP_MERGE_OPTIONS = '--knock-out-prefix, --sort-merged-arrays, and --merge-hash-arrays'
TRUSTED_INFORMATION_FACTS = ["hostname", "domain", "fqdn", "clientcert"].freeze
run_mode :server
# Options for lookup
option('--merge TYPE') do |arg|
options[:merge] = arg
end
option('--debug', '-d')
option('--verbose', '-v')
option('--render-as FORMAT') do |format|
options[:render_as] = format.downcase.to_sym
end
option('--type TYPE_STRING') do |arg|
options[:type] = arg
end
option('--compile', '-c')
option('--knock-out-prefix PREFIX_STRING') do |arg|
options[:prefix] = arg
end
option('--sort-merged-arrays')
option('--merge-hash-arrays')
option('--explain')
option('--explain-options')
option('--default VALUE') do |arg|
options[:default_value] = arg
end
# not yet supported
option('--trusted')
# Options for facts/scope
option('--node NODE_NAME') do |arg|
options[:node] = arg
end
option('--facts FACT_FILE') do |arg|
options[:fact_file] = arg
end
def app_defaults
super.merge({
:facts_terminus => 'yaml'
})
end
def setup_logs
# This sets up logging based on --debug or --verbose if they are set in `options`
set_log_level
# This uses console for everything that is not a compilation
Puppet::Util::Log.newdestination(:console)
end
def setup_terminuses
require_relative '../../puppet/file_serving/content'
require_relative '../../puppet/file_serving/metadata'
Puppet::FileServing::Content.indirection.terminus_class = :file_server
Puppet::FileServing::Metadata.indirection.terminus_class = :file_server
Puppet::FileBucket::File.indirection.terminus_class = :file
end
def setup
setup_logs
exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
if options[:node]
Puppet::Util.skip_external_facts do
Puppet.settings.use :main, :server, :ssl, :metrics
end
else
Puppet.settings.use :main, :server, :ssl, :metrics
end
setup_terminuses
end
def summary
_("Interactive Hiera lookup")
end
def help
<<~HELP
puppet-lookup(8) -- #{summary}
========
SYNOPSIS
--------
Does Hiera lookups from the command line.
Since this command needs access to your Hiera data, make sure to run it on a
node that has a copy of that data. This usually means logging into a Puppet
Server node and running 'puppet lookup' with sudo.
The most common version of this command is:
'puppet lookup --node --environment --explain'
USAGE
-----
puppet lookup [--help] [--type ] [--merge first|unique|hash|deep]
[--knock-out-prefix ] [--sort-merged-arrays]
[--merge-hash-arrays] [--explain] [--environment ]
[--default ] [--node ] [--facts ]
[--compile]
[--render-as s|json|yaml|binary|msgpack]
DESCRIPTION
-----------
The lookup command is a CLI for Puppet's 'lookup()' function. It searches your
Hiera data and returns a value for the requested lookup key, so you can test and
explore your data. It is a modern replacement for the 'hiera' command.
Lookup uses the setting for global hiera.yaml from puppet's config,
and the environment to find the environment level hiera.yaml as well as the
resulting modulepath for the environment (for hiera.yaml files in modules).
Hiera usually relies on a node's facts to locate the relevant data sources. By
default, 'puppet lookup' uses facts from the node you run the command on, but
you can get data for any other node with the '--node ' option. If
possible, the lookup command will use the requested node's real stored facts
from PuppetDB; if PuppetDB isn't configured or you want to provide arbitrary
fact values, you can pass alternate facts as a JSON or YAML file with '--facts
'.
If you're debugging your Hiera data and want to see where values are coming
from, use the '--explain' option.
If '--explain' isn't specified, lookup exits with 0 if a value was found and 1
otherwise. With '--explain', lookup always exits with 0 unless there is a major
error.
You can provide multiple lookup keys to this command, but it only returns a
value for the first found key, omitting the rest.
For more details about how Hiera works, see the Hiera documentation:
https://puppet.com/docs/puppet/latest/hiera_intro.html
OPTIONS
-------
* --help:
Print this help message.
* --explain
Explain the details of how the lookup was performed and where the final value
came from (or the reason no value was found).
* --node
Specify which node to look up data for; defaults to the node where the command
is run. Since Hiera's purpose is to provide different values for different
nodes (usually based on their facts), you'll usually want to use some specific
node's facts to explore your data. If the node where you're running this
command is configured to talk to PuppetDB, the command will use the requested
node's most recent facts. Otherwise, you can override facts with the '--facts'
option.
* --facts
Specify a .json or .yaml file of key => value mappings to override the facts
for this lookup. Any facts not specified in this file maintain their
original value.
* --environment
Like with most Puppet commands, you can specify an environment on the command
line. This is important for lookup because different environments can have
different Hiera data. This environment will be always be the one used regardless
of any other factors.
* --merge first|unique|hash|deep:
Specify the merge behavior, overriding any merge behavior from the data's
lookup_options. 'first' returns the first value found. 'unique' appends
everything to a merged, deduplicated array. 'hash' performs a simple hash
merge by overwriting keys of lower lookup priority. 'deep' performs a deep
merge on values of Array and Hash type. There are additional options that can
be used with 'deep'.
* --knock-out-prefix
Can be used with the 'deep' merge strategy. Specifies a prefix to indicate a
value should be removed from the final result.
* --sort-merged-arrays
Can be used with the 'deep' merge strategy. When this flag is used, all
merged arrays are sorted.
* --merge-hash-arrays
Can be used with the 'deep' merge strategy. When this flag is used, hashes
WITHIN arrays are deep-merged with their counterparts by position.
* --explain-options
Explain whether a lookup_options hash affects this lookup, and how that hash
was assembled. (lookup_options is how Hiera configures merge behavior in data.)
* --default
A value to return if Hiera can't find a value in data. For emulating calls to
the 'lookup()' function that include a default.
* --type :
Assert that the value has the specified type. For emulating calls to the
'lookup()' function that include a data type.
* --compile
Perform a full catalog compilation prior to the lookup. If your hierarchy and
data only use the $facts, $trusted, and $server_facts variables, you don't
need this option; however, if your Hiera configuration uses arbitrary
variables set by a Puppet manifest, you might need this option to get accurate
data. No catalog compilation takes place unless this flag is given.
* --render-as s|json|yaml|binary|msgpack
Specify the output format of the results; "s" means plain text. The default
when producing a value is yaml and the default when producing an explanation
is s.
EXAMPLE
-------
To look up 'key_name' using the Puppet Server node's facts:
$ puppet lookup key_name
To look up 'key_name' using the Puppet Server node's arbitrary variables from a manifest, and
classify the node if applicable:
$ puppet lookup key_name --compile
To look up 'key_name' using the Puppet Server node's facts, overridden by facts given in a file:
$ puppet lookup key_name --facts fact_file.yaml
To look up 'key_name' with agent.local's facts:
$ puppet lookup --node agent.local key_name
To get the first value found for 'key_name_one' and 'key_name_two'
with agent.local's facts while merging values and knocking out
the prefix 'foo' while merging:
$ puppet lookup --node agent.local --merge deep --knock-out-prefix foo key_name_one key_name_two
To lookup 'key_name' with agent.local's facts, and return a default value of
'bar' if nothing was found:
$ puppet lookup --node agent.local --default bar key_name
To see an explanation of how the value for 'key_name' would be found, using
agent.local's facts:
$ puppet lookup --node agent.local --explain key_name
COPYRIGHT
---------
Copyright (c) 2015 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def main
keys = command_line.args
if (options[:sort_merged_arrays] || options[:merge_hash_arrays] || options[:prefix]) && options[:merge] != 'deep'
raise _("The options %{deep_merge_opts} are only available with '--merge deep'\n%{run_help}") % { deep_merge_opts: DEEP_MERGE_OPTIONS, run_help: RUN_HELP }
end
use_default_value = !options[:default_value].nil?
merge_options = nil
merge = options[:merge]
unless merge.nil?
strategies = Puppet::Pops::MergeStrategy.strategy_keys
unless strategies.include?(merge.to_sym)
strategies = strategies.map {|k| "'#{k}'"}
raise _("The --merge option only accepts %{strategies}, or %{last_strategy}\n%{run_help}") % { strategies: strategies[0...-1].join(', '), last_strategy: strategies.last, run_help: RUN_HELP }
end
if merge == 'deep'
merge_options = {'strategy' => 'deep',
'sort_merged_arrays' => !options[:sort_merged_arrays].nil?,
'merge_hash_arrays' => !options[:merge_hash_arrays].nil?}
if options[:prefix]
merge_options['knockout_prefix'] = options[:prefix]
end
else
merge_options = {'strategy' => merge}
end
end
explain_data = !!options[:explain]
explain_options = !!options[:explain_options]
only_explain_options = explain_options && !explain_data
if keys.empty?
if only_explain_options
# Explain lookup_options for lookup of an unqualified value.
keys = Puppet::Pops::Lookup::GLOBAL
else
raise _('No keys were given to lookup.')
end
end
explain = explain_data || explain_options
# Format defaults to text (:s) when producing an explanation and :yaml when producing the value
format = options[:render_as] || (explain ? :s : :yaml)
renderer = Puppet::Network::FormatHandler.format(format)
raise _("Unknown rendering format '%{format}'") % { format: format } if renderer.nil?
generate_scope do |scope|
lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, explain ? Puppet::Pops::Lookup::Explainer.new(explain_options, only_explain_options) : nil)
begin
type = options.include?(:type) ? Puppet::Pops::Types::TypeParser.singleton.parse(options[:type], scope) : nil
result = Puppet::Pops::Lookup.lookup(keys, type, options[:default_value], use_default_value, merge_options, lookup_invocation)
puts renderer.render(result) unless explain
rescue Puppet::DataBinding::LookupError => e
lookup_invocation.report_text { e.message }
exit(1) unless explain
end
puts format == :s ? lookup_invocation.explainer.explain : renderer.render(lookup_invocation.explainer.to_hash) if explain
end
exit(0)
end
def generate_scope
if options[:node]
node = options[:node]
else
node = Puppet[:node_name_value]
# If we want to lookup the node we are currently on
# we must returning these settings to their default values
Puppet.settings[:facts_terminus] = 'facter'
end
fact_file = options[:fact_file]
if fact_file
if fact_file.end_with?('.json')
given_facts = Puppet::Util::Json.load_file(fact_file)
elsif fact_file.end_with?('.yml', '.yaml')
given_facts = Puppet::Util::Yaml.safe_load_file(fact_file)
else
given_facts = Puppet::Util::Json.load_file_if_valid(fact_file)
given_facts = Puppet::Util::Yaml.safe_load_file_if_valid(fact_file) unless given_facts
end
unless given_facts.instance_of?(Hash)
raise _("Incorrectly formatted data in %{fact_file} given via the --facts flag (only accepts yaml and json files)") % { fact_file: fact_file }
end
if TRUSTED_INFORMATION_FACTS.any? { |key| given_facts.key? key }
unless TRUSTED_INFORMATION_FACTS.all? { |key| given_facts.key? key }
raise _("When overriding any of the %{trusted_facts_list} facts with %{fact_file} "\
"given via the --facts flag, they must all be overridden.") % { fact_file: fact_file ,trusted_facts_list: TRUSTED_INFORMATION_FACTS.join(',')}
end
end
end
unless node.is_a?(Puppet::Node) # to allow unit tests to pass a node instance
facts = retrieve_node_facts(node, given_facts)
ni = Puppet::Node.indirection
tc = ni.terminus_class
if options[:compile]
if tc == :plain
node = ni.find(node, facts: facts, environment: Puppet[:environment])
else
begin
service = Puppet.runtime[:http]
session = service.create_session
cert = session.route_to(:ca)
_, x509 = cert.get_certificate(node)
cert = OpenSSL::X509::Certificate.new(x509)
Puppet::SSL::Oids.register_puppet_oids
trusted = Puppet::Context::TrustedInformation.remote(true, facts.values['certname'] || node, Puppet::SSL::Certificate.from_instance(cert))
Puppet.override(trusted_information: trusted) do
node = ni.find(node, facts: facts, environment: Puppet[:environment])
end
rescue
Puppet.warning _("CA is not available, the operation will continue without using trusted facts.")
node = ni.find(node, facts: facts, environment: Puppet[:environment])
end
end
else
ni.terminus_class = :plain
node = ni.find(node, facts: facts, environment: Puppet[:environment])
ni.terminus_class = tc
end
else
node.add_extra_facts(given_facts) if given_facts
end
node.environment = Puppet[:environment] if Puppet.settings.set_by_cli?(:environment)
Puppet[:code] = 'undef' unless options[:compile]
compiler = Puppet::Parser::Compiler.new(node)
if options[:node]
Puppet::Util.skip_external_facts do
compiler.compile { |catalog| yield(compiler.topscope); catalog }
end
else
compiler.compile { |catalog| yield(compiler.topscope); catalog }
end
end
def retrieve_node_facts(node, given_facts)
facts = Puppet::Node::Facts.indirection.find(node, :environment => Puppet.lookup(:current_environment))
facts = Puppet::Node::Facts.new(node, {}) if facts.nil?
facts.add_extra_values(given_facts) if given_facts
if facts.values.empty?
raise _("No facts available for target node: %{node}") % { node: node}
end
facts
end
end
puppet-8.4.0/lib/puppet/application/filebucket.rb 0000644 0052762 0001160 00000024447 14552052437 022002 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
class Puppet::Application::Filebucket < Puppet::Application
environment_mode :not_required
option("--bucket BUCKET","-b")
option("--debug","-d")
option("--fromdate FROMDATE","-f")
option("--todate TODATE","-t")
option("--local","-l")
option("--remote","-r")
option("--verbose","-v")
attr :args
def summary
_("Store and retrieve files in a filebucket")
end
def digest_algorithm
Puppet.default_digest_algorithm
end
def help
<<~HELP
puppet-filebucket(8) -- #{summary}
========
SYNOPSIS
--------
A stand-alone Puppet filebucket client.
USAGE
-----
puppet filebucket [-h|--help] [-V|--version] [-d|--debug]
[-v|--verbose] [-l|--local] [-r|--remote] [-s|--server ]
[-f|--fromdate ] [-t|--todate ] [-b|--bucket ]
...
Puppet filebucket can operate in three modes, with only one mode per call:
backup:
Send one or more files to the specified file bucket. Each sent file is
printed with its resulting #{digest_algorithm} sum.
get:
Return the text associated with an #{digest_algorithm} sum. The text is printed to
stdout, and only one file can be retrieved at a time.
restore:
Given a file path and an #{digest_algorithm} sum, store the content associated with
the sum into the specified file path. You can specify an entirely new
path to this argument; you are not restricted to restoring the content
to its original location.
diff:
Print a diff in unified format between two checksums in the filebucket
or between a checksum and its matching file.
list:
List all files in the current local filebucket. Listing remote
filebuckets is not allowed.
DESCRIPTION
-----------
This is a stand-alone filebucket client for sending files to a local or
central filebucket.
Note that 'filebucket' defaults to using a network-based filebucket
available on the server named 'puppet'. To use this, you'll have to be
running as a user with valid Puppet certificates. Alternatively, you can
use your local file bucket by specifying '--local', or by specifying
'--bucket' with a local path.
> **Note**: Enabling and using the backup option, and by extension the
filebucket resource, requires appropriate planning and management to ensure
that sufficient disk space is available for the file backups. Generally, you
can implement this using one of the following two options:
- Use a `find` command and `crontab` entry to retain only the last X days
of file backups. For example:
```shell
find /opt/puppetlabs/server/data/puppetserver/bucket -type f -mtime +45 -atime +45 -print0 | xargs -0 rm
```
- Restrict the directory to a maximum size after which the oldest items are removed.
OPTIONS
-------
Note that any setting that's valid in the configuration
file is also a valid long argument. For example, 'ssldir' is a valid
setting, so you can specify '--ssldir ' as an
argument.
See the configuration file documentation at
https://puppet.com/docs/puppet/latest/configuration.html for the
full list of acceptable parameters. A commented list of all
configuration options can also be generated by running puppet with
'--genconfig'.
* --bucket:
Specify a local filebucket path. This overrides the default path
set in '$clientbucketdir'.
* --debug:
Enable full debugging.
* --fromdate:
(list only) Select bucket files from 'fromdate'.
* --help:
Print this help message.
* --local:
Use the local filebucket. This uses the default configuration
information and the bucket located at the '$clientbucketdir'
setting by default. If '--bucket' is set, puppet uses that
path instead.
* --remote:
Use a remote filebucket. This uses the default configuration
information and the bucket located at the '$bucketdir' setting
by default.
* --server_list:
A list of comma separated servers; only the first entry is used for file storage.
This setting takes precidence over `server`.
* --server:
The server to use for file storage. This setting is only used if `server_list`
is not set.
* --todate:
(list only) Select bucket files until 'todate'.
* --verbose:
Print extra information.
* --version:
Print version information.
EXAMPLES
--------
## Backup a file to the filebucket, then restore it to a temporary directory
$ puppet filebucket backup /etc/passwd
/etc/passwd: 429b225650b912a2ee067b0a4cf1e949
$ puppet filebucket restore /tmp/passwd 429b225650b912a2ee067b0a4cf1e949
## Diff between two files in the filebucket
$ puppet filebucket -l diff d43a6ecaa892a1962398ac9170ea9bf2 7ae322f5791217e031dc60188f4521ef
1a2
> again
## Diff between the file in the filebucket and a local file
$ puppet filebucket -l diff d43a6ecaa892a1962398ac9170ea9bf2 /tmp/testFile
1a2
> again
## Backup a file to the filebucket and observe that it keeps each backup separate
$ puppet filebucket -l list
d43a6ecaa892a1962398ac9170ea9bf2 2015-05-11 09:27:56 /tmp/TestFile
$ echo again >> /tmp/TestFile
$ puppet filebucket -l backup /tmp/TestFile
/tmp/TestFile: 7ae322f5791217e031dc60188f4521ef
$ puppet filebucket -l list
d43a6ecaa892a1962398ac9170ea9bf2 2015-05-11 09:27:56 /tmp/TestFile
7ae322f5791217e031dc60188f4521ef 2015-05-11 09:52:15 /tmp/TestFile
## List files in a filebucket within date ranges
$ puppet filebucket -l -f 2015-01-01 -t 2015-01-11 list
$ puppet filebucket -l -f 2015-05-10 list
d43a6ecaa892a1962398ac9170ea9bf2 2015-05-11 09:27:56 /tmp/TestFile
7ae322f5791217e031dc60188f4521ef 2015-05-11 09:52:15 /tmp/TestFile
$ puppet filebucket -l -f "2015-05-11 09:30:00" list
7ae322f5791217e031dc60188f4521ef 2015-05-11 09:52:15 /tmp/TestFile
$ puppet filebucket -l -t "2015-05-11 09:30:00" list
d43a6ecaa892a1962398ac9170ea9bf2 2015-05-11 09:27:56 /tmp/TestFile
## Manage files in a specific local filebucket
$ puppet filebucket -b /tmp/TestBucket backup /tmp/TestFile2
/tmp/TestFile2: d41d8cd98f00b204e9800998ecf8427e
$ puppet filebucket -b /tmp/TestBucket list
d41d8cd98f00b204e9800998ecf8427e 2015-05-11 09:33:22 /tmp/TestFile2
## From a Puppet Server, list files in the server bucketdir
$ puppet filebucket -b $(puppet config print bucketdir --section server) list
d43a6ecaa892a1962398ac9170ea9bf2 2015-05-11 09:27:56 /tmp/TestFile
7ae322f5791217e031dc60188f4521ef 2015-05-11 09:52:15 /tmp/TestFile
AUTHOR
------
Luke Kanies
COPYRIGHT
---------
Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def run_command
@args = command_line.args
command = args.shift
return send(command) if %w{get backup restore diff list}.include? command
help
end
def get
digest = args.shift
out = @client.getfile(digest)
print out
end
def backup
raise _("You must specify a file to back up") unless args.length > 0
args.each do |file|
unless Puppet::FileSystem.exist?(file)
$stderr.puts _("%{file}: no such file") % { file: file }
next
end
unless FileTest.readable?(file)
$stderr.puts _("%{file}: cannot read file") % { file: file }
next
end
digest = @client.backup(file)
puts "#{file}: #{digest}"
end
end
def list
fromdate = options[:fromdate]
todate = options[:todate]
out = @client.list(fromdate, todate)
print out
end
def restore
file = args.shift
digest = args.shift
@client.restore(file, digest)
end
def diff
raise Puppet::Error, _("Need exactly two arguments: filebucket diff ") unless args.count == 2
left = args.shift
right = args.shift
if Puppet::FileSystem.exist?(left)
# It's a file
file_a = left
checksum_a = nil
else
file_a = nil
checksum_a = left
end
if Puppet::FileSystem.exist?(right)
# It's a file
file_b = right
checksum_b = nil
else
file_b = nil
checksum_b = right
end
if (checksum_a || file_a) && (checksum_b || file_b)
Puppet.info(_("Comparing %{checksum_a} %{checksum_b} %{file_a} %{file_b}") % { checksum_a: checksum_a, checksum_b: checksum_b, file_a: file_a, file_b: file_b })
print @client.diff(checksum_a, checksum_b, file_a, file_b)
else
raise Puppet::Error, _("Need exactly two arguments: filebucket diff ")
end
end
def setup
Puppet::Log.newdestination(:console)
@client = nil
@server = nil
Signal.trap(:INT) do
$stderr.puts _("Cancelling")
exit(1)
end
if options[:debug]
Puppet::Log.level = :debug
elsif options[:verbose]
Puppet::Log.level = :info
end
exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
require_relative '../../puppet/file_bucket/dipper'
begin
if options[:local] or options[:bucket]
path = options[:bucket] || Puppet[:clientbucketdir]
@client = Puppet::FileBucket::Dipper.new(:Path => path)
else
session = Puppet.lookup(:http_session)
api = session.route_to(:puppet)
@client = Puppet::FileBucket::Dipper.new(Server: api.url.host, Port: api.url.port)
end
rescue => detail
Puppet.log_exception(detail)
exit(1)
end
end
end
puppet-8.4.0/lib/puppet/application/ssl.rb 0000644 0052762 0001160 00000026616 14552052437 020466 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/ssl/oids'
class Puppet::Application::Ssl < Puppet::Application
run_mode :agent
def summary
_("Manage SSL keys and certificates for puppet SSL clients")
end
def help
<<~HELP
puppet-ssl(8) -- #{summary}
========
SYNOPSIS
--------
Manage SSL keys and certificates for SSL clients needing
to communicate with a puppet infrastructure.
USAGE
-----
puppet ssl [-h|--help] [-v|--verbose] [-d|--debug] [--localca] [--target CERTNAME]
OPTIONS
-------
* --help:
Print this help message.
* --verbose:
Print extra information.
* --debug:
Enable full debugging.
* --localca
Also clean the local CA certificate and CRL.
* --target CERTNAME
Clean the specified device certificate instead of this host's certificate.
ACTIONS
-------
* bootstrap:
Perform all of the steps necessary to request and download a client
certificate. If autosigning is disabled, then puppet will wait every
`waitforcert` seconds for its certificate to be signed. To only attempt
once and never wait, specify a time of 0. Since `waitforcert` is a
Puppet setting, it can be specified as a time interval, such as 30s,
5m, 1h.
* submit_request:
Generate a certificate signing request (CSR) and submit it to the CA. If
a private and public key pair already exist, they will be used to generate
the CSR. Otherwise a new key pair will be generated. If a CSR has already
been submitted with the given `certname`, then the operation will fail.
* generate_request:
Generate a certificate signing request (CSR). If
a private and public key pair already exist, they will be used to generate
the CSR. Otherwise a new key pair will be generated.
* download_cert:
Download a certificate for this host. If the current private key matches
the downloaded certificate, then the certificate will be saved and used
for subsequent requests. If there is already an existing certificate, it
will be overwritten.
* verify:
Verify the private key and certificate are present and match, verify the
certificate is issued by a trusted CA, and check revocation status.
* clean:
Remove the private key and certificate related files for this host. If
`--localca` is specified, then also remove this host's local copy of the
CA certificate(s) and CRL bundle. if `--target CERTNAME` is specified, then
remove the files for the specified device on this host instead of this host.
* show:
Print the full-text version of this host's certificate.
HELP
end
option('--target CERTNAME') do |arg|
options[:target] = arg.to_s
end
option('--localca')
option('--verbose', '-v')
option('--debug', '-d')
def initialize(command_line = Puppet::Util::CommandLine.new)
super(command_line)
@cert_provider = Puppet::X509::CertProvider.new
@ssl_provider = Puppet::SSL::SSLProvider.new
@machine = Puppet::SSL::StateMachine.new
@session = Puppet.runtime[:http].create_session
end
def setup_logs
set_log_level(options)
Puppet::Util::Log.newdestination(:console)
end
def main
if command_line.args.empty?
raise Puppet::Error, _("An action must be specified.")
end
if options[:target]
# Override the following, as per lib/puppet/application/device.rb
Puppet[:certname] = options[:target]
Puppet[:confdir] = File.join(Puppet[:devicedir], Puppet[:certname])
Puppet[:vardir] = File.join(Puppet[:devicedir], Puppet[:certname])
Puppet.settings.use(:main, :agent, :device)
else
Puppet.settings.use(:main, :agent)
end
Puppet::SSL::Oids.register_puppet_oids
Puppet::SSL::Oids.load_custom_oid_file(Puppet[:trusted_oid_mapping_file])
certname = Puppet[:certname]
action = command_line.args.first
case action
when 'submit_request'
ssl_context = @machine.ensure_ca_certificates
if submit_request(ssl_context)
cert = download_cert(ssl_context)
unless cert
Puppet.info(_("The certificate for '%{name}' has not yet been signed") % { name: certname })
end
end
when 'download_cert'
ssl_context = @machine.ensure_ca_certificates
cert = download_cert(ssl_context)
unless cert
raise Puppet::Error, _("The certificate for '%{name}' has not yet been signed") % { name: certname }
end
when 'generate_request'
generate_request(certname)
when 'verify'
verify(certname)
when 'clean'
possible_extra_args = command_line.args.drop(1)
unless possible_extra_args.empty?
raise Puppet::Error, _(<<~END) % { args: possible_extra_args.join(' ')}
Extra arguments detected: %{args}
Did you mean to run:
puppetserver ca clean --certname
Or:
puppet ssl clean --target
END
end
clean(certname)
when 'bootstrap'
if !Puppet::Util::Log.sendlevel?(:info)
Puppet::Util::Log.level = :info
end
@machine.ensure_client_certificate
Puppet.notice(_("Completed SSL initialization"))
when 'show'
show(certname)
else
raise Puppet::Error, _("Unknown action '%{action}'") % { action: action }
end
end
def show(certname)
password = @cert_provider.load_private_key_password
ssl_context = @ssl_provider.load_context(certname: certname, password: password)
puts ssl_context.client_cert.to_text
end
def submit_request(ssl_context)
key = @cert_provider.load_private_key(Puppet[:certname])
unless key
key = create_key(Puppet[:certname])
@cert_provider.save_private_key(Puppet[:certname], key)
end
csr = @cert_provider.create_request(Puppet[:certname], key)
route = create_route(ssl_context)
route.put_certificate_request(Puppet[:certname], csr, ssl_context: ssl_context)
@cert_provider.save_request(Puppet[:certname], csr)
Puppet.notice _("Submitted certificate request for '%{name}' to %{url}") % { name: Puppet[:certname], url: route.url }
rescue Puppet::HTTP::ResponseError => e
if e.response.code == 400
raise Puppet::Error.new(_("Could not submit certificate request for '%{name}' to %{url} due to a conflict on the server") % { name: Puppet[:certname], url: route.url })
else
raise Puppet::Error.new(_("Failed to submit certificate request: %{message}") % { message: e.message }, e)
end
rescue => e
raise Puppet::Error.new(_("Failed to submit certificate request: %{message}") % { message: e.message }, e)
end
def generate_request(certname)
key = @cert_provider.load_private_key(certname)
unless key
key = create_key(certname)
@cert_provider.save_private_key(certname, key)
end
csr = @cert_provider.create_request(certname, key)
@cert_provider.save_request(certname, csr)
Puppet.notice _("Generated certificate request in '%{path}'") % { path: @cert_provider.to_path(Puppet[:requestdir], certname) }
rescue => e
raise Puppet::Error.new(_("Failed to generate certificate request: %{message}") % { message: e.message }, e)
end
def download_cert(ssl_context)
key = @cert_provider.load_private_key(Puppet[:certname])
# try to download cert
route = create_route(ssl_context)
Puppet.info _("Downloading certificate '%{name}' from %{url}") % { name: Puppet[:certname], url: route.url }
_, x509 = route.get_certificate(Puppet[:certname], ssl_context: ssl_context)
cert = OpenSSL::X509::Certificate.new(x509)
Puppet.notice _("Downloaded certificate '%{name}' with fingerprint %{fingerprint}") % { name: Puppet[:certname], fingerprint: fingerprint(cert) }
# verify client cert before saving
@ssl_provider.create_context(
cacerts: ssl_context.cacerts, crls: ssl_context.crls, private_key: key, client_cert: cert
)
@cert_provider.save_client_cert(Puppet[:certname], cert)
@cert_provider.delete_request(Puppet[:certname])
cert
rescue Puppet::HTTP::ResponseError => e
if e.response.code == 404
return nil
else
raise Puppet::Error.new(_("Failed to download certificate: %{message}") % { message: e.message }, e)
end
rescue => e
raise Puppet::Error.new(_("Failed to download certificate: %{message}") % { message: e.message }, e)
end
def verify(certname)
password = @cert_provider.load_private_key_password
ssl_context = @ssl_provider.load_context(certname: certname, password: password)
# print from root to client
ssl_context.client_chain.reverse.each_with_index do |cert, i|
digest = Puppet::SSL::Digest.new('SHA256', cert.to_der)
if i == ssl_context.client_chain.length - 1
Puppet.notice("Verified client certificate '#{cert.subject.to_utf8}' fingerprint #{digest}")
else
Puppet.notice("Verified CA certificate '#{cert.subject.to_utf8}' fingerprint #{digest}")
end
end
end
def clean(certname)
# make sure cert has been removed from the CA
if certname == Puppet[:ca_server]
cert = nil
begin
ssl_context = @machine.ensure_ca_certificates
route = create_route(ssl_context)
_, cert = route.get_certificate(certname, ssl_context: ssl_context)
rescue Puppet::HTTP::ResponseError => e
if e.response.code.to_i != 404
raise Puppet::Error.new(_("Failed to connect to the CA to determine if certificate %{certname} has been cleaned") % { certname: certname }, e)
end
rescue => e
raise Puppet::Error.new(_("Failed to connect to the CA to determine if certificate %{certname} has been cleaned") % { certname: certname }, e)
end
if cert
raise Puppet::Error, _(<<~END) % { certname: certname }
The certificate %{certname} must be cleaned from the CA first. To fix this,
run the following commands on the CA:
puppetserver ca clean --certname %{certname}
puppet ssl clean
END
end
end
paths = {
'private key' => Puppet[:hostprivkey],
'public key' => Puppet[:hostpubkey],
'certificate request' => Puppet[:hostcsr],
'certificate' => Puppet[:hostcert],
'private key password file' => Puppet[:passfile]
}
if options[:localca]
paths['local CA certificate'] = Puppet[:localcacert]
paths['local CRL'] = Puppet[:hostcrl]
end
paths.each_pair do |label, path|
if Puppet::FileSystem.exist?(path)
Puppet::FileSystem.unlink(path)
Puppet.notice _("Removed %{label} %{path}") % { label: label, path: path }
end
end
end
private
def fingerprint(cert)
Puppet::SSL::Digest.new(nil, cert.to_der)
end
def create_route(ssl_context)
@session.route_to(:ca, ssl_context: ssl_context)
end
def create_key(certname)
if Puppet[:key_type] == 'ec'
Puppet.info _("Creating a new EC SSL key for %{name} using curve %{curve}") % { name: certname, curve: Puppet[:named_curve] }
OpenSSL::PKey::EC.generate(Puppet[:named_curve])
else
Puppet.info _("Creating a new SSL key for %{name}") % { name: certname }
OpenSSL::PKey::RSA.new(Puppet[:keylength].to_i)
end
end
end
puppet-8.4.0/lib/puppet/application/agent.rb 0000644 0052762 0001160 00000045521 14552052437 020757 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/daemon'
require_relative '../../puppet/util/pidlock'
require_relative '../../puppet/agent'
require_relative '../../puppet/configurer'
require_relative '../../puppet/ssl/oids'
class Puppet::Application::Agent < Puppet::Application
run_mode :agent
def app_defaults
super.merge({
:catalog_terminus => :rest,
:catalog_cache_terminus => :json,
:node_terminus => :rest,
:facts_terminus => :facter,
})
end
def preinit
# Do an initial trap, so that cancels don't get a stack trace.
Signal.trap(:INT) do
$stderr.puts _("Cancelling startup")
exit(0)
end
{
:waitforcert => nil,
:detailed_exitcodes => false,
:verbose => false,
:debug => false,
:setdest => false,
:enable => false,
:disable => false,
:fqdn => nil,
:serve => [],
:digest => 'SHA256',
:graph => true,
:fingerprint => false,
:sourceaddress => nil,
:start_time => Time.now,
}.each do |opt,val|
options[opt] = val
end
@argv = ARGV.dup
end
option("--disable [MESSAGE]") do |message|
options[:disable] = true
options[:disable_message] = message
end
option("--enable")
option("--debug","-d")
option("--fqdn FQDN","-f")
option("--test","-t")
option("--verbose","-v")
option("--fingerprint")
option("--digest DIGEST")
option("--sourceaddress IP_ADDRESS")
option("--detailed-exitcodes") do |_arg|
options[:detailed_exitcodes] = true
end
option("--logdest DEST", "-l DEST") do |arg|
handle_logdest_arg(arg)
end
option("--waitforcert WAITFORCERT", "-w") do |arg|
options[:waitforcert] = arg.to_i
end
option("--job-id ID") do |arg|
options[:job_id] = arg
end
def summary
_("The puppet agent daemon")
end
def help
<<~HELP
puppet-agent(8) -- #{summary}
========
SYNOPSIS
--------
Retrieves the client configuration from the Puppet master and applies it to
the local host.
This service may be run as a daemon, run periodically using cron (or something
similar), or run interactively for testing purposes.
USAGE
-----
puppet agent [--certname ] [-D|--daemonize|--no-daemonize]
[-d|--debug] [--detailed-exitcodes] [--digest ] [--disable [MESSAGE]] [--enable]
[--fingerprint] [-h|--help] [-l|--logdest syslog|eventlog||console]
[--serverport ] [--noop] [-o|--onetime] [--sourceaddress ] [-t|--test]
[-v|--verbose] [-V|--version] [-w|--waitforcert ]
DESCRIPTION
-----------
This is the main puppet client. Its job is to retrieve the local
machine's configuration from a remote server and apply it. In order to
successfully communicate with the remote server, the client must have a
certificate signed by a certificate authority that the server trusts;
the recommended method for this, at the moment, is to run a certificate
authority as part of the puppet server (which is the default). The
client will connect and request a signed certificate, and will continue
connecting until it receives one.
Once the client has a signed certificate, it will retrieve its
configuration and apply it.
USAGE NOTES
-----------
'puppet agent' does its best to find a compromise between interactive
use and daemon use. If you run it with no arguments and no configuration, it
goes into the background, attempts to get a signed certificate, and retrieves
and applies its configuration every 30 minutes.
Some flags are meant specifically for interactive use --- in particular,
'test', 'tags' and 'fingerprint' are useful.
'--test' runs once in the foreground with verbose logging, then exits.
It also exits if it can't get a valid catalog. `--test` includes the
'--detailed-exitcodes' option by default and exits with one of the following
exit codes:
* 0: The run succeeded with no changes or failures; the system was already in
the desired state.
* 1: The run failed, or wasn't attempted due to another run already in progress.
* 2: The run succeeded, and some resources were changed.
* 4: The run succeeded, and some resources failed.
* 6: The run succeeded, and included both changes and failures.
'--tags' allows you to specify what portions of a configuration you want
to apply. Puppet elements are tagged with all of the class or definition
names that contain them, and you can use the 'tags' flag to specify one
of these names, causing only configuration elements contained within
that class or definition to be applied. This is very useful when you are
testing new configurations --- for instance, if you are just starting to
manage 'ntpd', you would put all of the new elements into an 'ntpd'
class, and call puppet with '--tags ntpd', which would only apply that
small portion of the configuration during your testing, rather than
applying the whole thing.
'--fingerprint' is a one-time flag. In this mode 'puppet agent' runs
once and displays on the console (and in the log) the current certificate
(or certificate request) fingerprint. Providing the '--digest' option
allows you to use a different digest algorithm to generate the fingerprint.
The main use is to verify that before signing a certificate request on
the master, the certificate request the master received is the same as
the one the client sent (to prevent against man-in-the-middle attacks
when signing certificates).
'--skip_tags' is a flag used to filter resources. If this is set, then
only resources not tagged with the specified tags will be applied.
Values must be comma-separated.
OPTIONS
-------
Note that any Puppet setting that's valid in the configuration file is also a
valid long argument. For example, 'server' is a valid setting, so you can
specify '--server ' as an argument. Boolean settings accept a '--no-'
prefix to turn off a behavior, translating into '--setting' and '--no-setting'
pairs, such as `--daemonize` and `--no-daemonize`.
See the configuration file documentation at
https://puppet.com/docs/puppet/latest/configuration.html for the
full list of acceptable settings. A commented list of all settings can also be
generated by running puppet agent with '--genconfig'.
* --certname:
Set the certname (unique ID) of the client. The master reads this
unique identifying string, which is usually set to the node's
fully-qualified domain name, to determine which configurations the
node will receive. Use this option to debug setup problems or
implement unusual node identification schemes.
(This is a Puppet setting, and can go in puppet.conf.)
* --daemonize:
Send the process into the background. This is the default.
(This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
prefix for boolean settings on the command line.)
* --no-daemonize:
Do not send the process into the background.
(This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
prefix for boolean settings on the command line.)
* --debug:
Enable full debugging.
* --detailed-exitcodes:
Provide extra information about the run via exit codes; works only if '--test'
or '--onetime' is also specified. If enabled, 'puppet agent' uses the
following exit codes:
0: The run succeeded with no changes or failures; the system was already in
the desired state.
1: The run failed, or wasn't attempted due to another run already in progress.
2: The run succeeded, and some resources were changed.
4: The run succeeded, and some resources failed.
6: The run succeeded, and included both changes and failures.
* --digest:
Change the certificate fingerprinting digest algorithm. The default is
SHA256. Valid values depends on the version of OpenSSL installed, but
will likely contain MD5, MD2, SHA1 and SHA256.
* --disable:
Disable working on the local system. This puts a lock file in place,
causing 'puppet agent' not to work on the system until the lock file
is removed. This is useful if you are testing a configuration and do
not want the central configuration to override the local state until
everything is tested and committed.
Disable can also take an optional message that will be reported by the
'puppet agent' at the next disabled run.
'puppet agent' uses the same lock file while it is running, so no more
than one 'puppet agent' process is working at a time.
'puppet agent' exits after executing this.
* --enable:
Enable working on the local system. This removes any lock file,
causing 'puppet agent' to start managing the local system again
However, it continues to use its normal scheduling, so it might
not start for another half hour.
'puppet agent' exits after executing this.
* --evaltrace:
Logs each resource as it is being evaluated. This allows you to interactively
see exactly what is being done. (This is a Puppet setting, and can go in
puppet.conf. Note the special 'no-' prefix for boolean settings on the command line.)
* --fingerprint:
Display the current certificate or certificate signing request
fingerprint and then exit. Use the '--digest' option to change the
digest algorithm used.
* --help:
Print this help message
* --job-id:
Attach the specified job id to the catalog request and the report used for
this agent run. This option only works when '--onetime' is used. When using
Puppet Enterprise this flag should not be used as the orchestrator sets the
job-id for you and it must be unique.
* --logdest:
Where to send log messages. Choose between 'syslog' (the POSIX syslog
service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
file. If debugging or verbosity is enabled, this defaults to 'console'.
Otherwise, it defaults to 'syslog' on POSIX systems and 'eventlog' on Windows.
Multiple destinations can be set using a comma separated list
(eg: `/path/file1,console,/path/file2`)"
A path ending with '.json' will receive structured output in JSON format. The
log file will not have an ending ']' automatically written to it due to the
appending nature of logging. It must be appended manually to make the content
valid JSON.
A path ending with '.jsonl' will receive structured output in JSON Lines
format.
* --masterport:
The port on which to contact the Puppet Server.
(This is a Puppet setting, and can go in puppet.conf.
Deprecated in favor of the 'serverport' setting.)
* --noop:
Use 'noop' mode where the daemon runs in a no-op or dry-run mode. This
is useful for seeing what changes Puppet would make without actually
executing the changes.
(This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
prefix for boolean settings on the command line.)
* --onetime:
Run the configuration once. Runs a single (normally daemonized) Puppet
run. Useful for interactively running puppet agent when used in
conjunction with the --no-daemonize option.
(This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
prefix for boolean settings on the command line.)
* --serverport:
The port on which to contact the Puppet Server.
(This is a Puppet setting, and can go in puppet.conf.)
* --sourceaddress:
Set the source IP address for transactions. This defaults to automatically selected.
(This is a Puppet setting, and can go in puppet.conf.)
* --test:
Enable the most common options used for testing. These are 'onetime',
'verbose', 'no-daemonize', 'no-usecacheonfailure', 'detailed-exitcodes',
'no-splay', and 'show_diff'.
* --trace
Prints stack traces on some errors. (This is a Puppet setting, and can go in
puppet.conf. Note the special 'no-' prefix for boolean settings on the command line.)
* --verbose:
Turn on verbose reporting.
* --version:
Print the puppet version number and exit.
* --waitforcert:
This option only matters for daemons that do not yet have certificates
and it is enabled by default, with a value of 120 (seconds). This
causes 'puppet agent' to connect to the server every 2 minutes and ask
it to sign a certificate request. This is useful for the initial setup
of a puppet client. You can turn off waiting for certificates by
specifying a time of 0.
(This is a Puppet setting, and can go in puppet.conf.)
* --write_catalog_summary
After compiling the catalog saves the resource list and classes list to the node
in the state directory named classes.txt and resources.txt
(This is a Puppet setting, and can go in puppet.conf.)
EXAMPLE
-------
$ puppet agent --server puppet.domain.com
DIAGNOSTICS
-----------
Puppet agent accepts the following signals:
* SIGHUP:
Restart the puppet agent daemon.
* SIGINT and SIGTERM:
Shut down the puppet agent daemon.
* SIGUSR1:
Immediately retrieve and apply configurations from the puppet master.
* SIGUSR2:
Close file descriptors for log files and reopen them. Used with logrotate.
AUTHOR
------
Luke Kanies
COPYRIGHT
---------
Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def run_command
if options[:fingerprint]
fingerprint
else
# It'd be nice to daemonize later, but we have to daemonize before
# waiting for certificates so that we don't block
daemon = daemonize_process_when(Puppet[:daemonize])
# Setup signal traps immediately after daemonization so we clean up the daemon
daemon.set_signal_traps
log_config if Puppet[:daemonize]
# Each application is responsible for pushing loaders onto the context.
# Use the current environment that has already been established, though
# it may change later during the configurer run.
env = Puppet.lookup(:current_environment)
Puppet.override(current_environment: env,
loaders: Puppet::Pops::Loaders.new(env, true)) do
if Puppet[:onetime]
onetime(daemon)
else
main(daemon)
end
end
end
end
def log_config
# skip also config reading and parsing if debug is not enabled
return unless Puppet::Util::Log.sendlevel?(:debug)
Puppet.settings.stringify_settings(:agent, :all).each_pair do |k,v|
next if k.include?("password") || v.to_s.empty?
Puppet.debug("Using setting: #{k}=#{v}")
end
end
def fingerprint
Puppet::Util::Log.newdestination(:console)
cert_provider = Puppet::X509::CertProvider.new
client_cert = cert_provider.load_client_cert(Puppet[:certname])
if client_cert
puts Puppet::SSL::Digest.new(options[:digest].to_s, client_cert.to_der).to_s
else
csr = cert_provider.load_request(Puppet[:certname])
if csr
puts Puppet::SSL::Digest.new(options[:digest].to_s, csr.to_der).to_s
else
$stderr.puts _("Fingerprint asked but neither the certificate, nor the certificate request have been issued")
exit(1)
end
end
rescue => e
Puppet.log_exception(e, _("Failed to generate fingerprint: %{message}") % {message: e.message})
exit(1)
end
def onetime(daemon)
begin
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time], :waitforcert => options[:waitforcert]})
rescue => detail
Puppet.log_exception(detail)
end
daemon.stop(:exit => false)
if not exitstatus
exit(1)
elsif options[:detailed_exitcodes] then
exit(exitstatus)
else
exit(0)
end
end
def main(daemon)
Puppet.notice _("Starting Puppet client version %{version}") % { version: Puppet.version }
daemon.start
end
# Enable all of the most common test options.
def setup_test
Puppet.settings.handlearg("--no-usecacheonfailure")
Puppet.settings.handlearg("--no-splay")
Puppet.settings.handlearg("--show_diff")
Puppet.settings.handlearg("--no-daemonize")
options[:verbose] = true
Puppet[:onetime] = true
options[:detailed_exitcodes] = true
end
def setup
raise ArgumentError, _("The puppet agent command does not take parameters") unless command_line.args.empty?
setup_test if options[:test]
setup_logs
exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
Puppet::SSL::Oids.register_puppet_oids
if options[:fqdn]
Puppet[:certname] = options[:fqdn]
end
Puppet.settings.use :main, :agent, :ssl
Puppet::Transaction::Report.indirection.terminus_class = :rest
# we want the last report to be persisted locally
Puppet::Transaction::Report.indirection.cache_class = :yaml
if Puppet[:catalog_cache_terminus]
Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
end
# In fingerprint mode we don't need to set up the whole agent
unless options[:fingerprint]
setup_agent
end
end
private
def enable_disable_client(agent)
if options[:enable]
agent.enable
elsif options[:disable]
agent.disable(options[:disable_message] || 'reason not specified')
end
exit(0)
end
def setup_agent
agent = Puppet::Agent.new(Puppet::Configurer, (not(Puppet[:onetime])))
enable_disable_client(agent) if options[:enable] or options[:disable]
@agent = agent
end
def daemonize_process_when(should_daemonize)
daemon = Puppet::Daemon.new(@agent, Puppet::Util::Pidlock.new(Puppet[:pidfile]))
daemon.argv = @argv
daemon.daemonize if should_daemonize
daemon
end
end
puppet-8.4.0/lib/puppet/application/generate.rb 0000644 0052762 0001160 00000000273 14552052437 021446 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
# The Generate application.
class Puppet::Application::Generate < Puppet::Application::FaceBase
end
puppet-8.4.0/lib/puppet/application/catalog.rb 0000644 0052762 0001160 00000000253 14552052437 021264 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/indirection_base'
class Puppet::Application::Catalog < Puppet::Application::IndirectionBase
end
puppet-8.4.0/lib/puppet/application/config.rb 0000644 0052762 0001160 00000000275 14552052437 021123 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
class Puppet::Application::Config < Puppet::Application::FaceBase
environment_mode :not_required
end
puppet-8.4.0/lib/puppet/application/indirection_base.rb 0000644 0052762 0001160 00000000245 14552052437 023154 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
class Puppet::Application::IndirectionBase < Puppet::Application::FaceBase
end
puppet-8.4.0/lib/puppet/application/doc.rb 0000644 0052762 0001160 00000014446 14552052437 020430 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
class Puppet::Application::Doc < Puppet::Application
run_mode :server
attr_accessor :unknown_args, :manifest
def preinit
{:references => [], :mode => :text, :format => :to_markdown }.each do |name,value|
options[name] = value
end
@unknown_args = []
@manifest = false
end
option("--all","-a")
option("--outputdir OUTPUTDIR","-o")
option("--verbose","-v")
option("--debug","-d")
option("--charset CHARSET")
option("--format FORMAT", "-f") do |arg|
method = "to_#{arg}"
require_relative '../../puppet/util/reference'
if Puppet::Util::Reference.method_defined?(method)
options[:format] = method
else
raise _("Invalid output format %{arg}") % { arg: arg }
end
end
option("--mode MODE", "-m") do |arg|
require_relative '../../puppet/util/reference'
if Puppet::Util::Reference.modes.include?(arg) or arg.intern==:rdoc
options[:mode] = arg.intern
else
raise _("Invalid output mode %{arg}") % { arg: arg }
end
end
option("--list", "-l") do |_arg|
require_relative '../../puppet/util/reference'
refs = Puppet::Util::Reference.references(Puppet.lookup(:current_environment))
puts refs.collect { |r| Puppet::Util::Reference.reference(r).doc }.join("\n")
exit(0)
end
option("--reference REFERENCE", "-r") do |arg|
options[:references] << arg.intern
end
def summary
_("Generate Puppet references")
end
def help
<<~HELP
puppet-doc(8) -- #{summary}
========
SYNOPSIS
--------
Generates a reference for all Puppet types. Largely meant for internal
Puppet Inc. use. (Deprecated)
USAGE
-----
puppet doc [-h|--help] [-l|--list]
[-r|--reference ]
DESCRIPTION
-----------
This deprecated command generates a Markdown document to stdout
describing all installed Puppet types or all allowable arguments to
puppet executables. It is largely meant for internal use and is used to
generate the reference document available on the Puppet Inc. web site.
For Puppet module documentation (and all other use cases) this command
has been superseded by the "puppet-strings"
module - see https://github.com/puppetlabs/puppetlabs-strings for more information.
This command (puppet-doc) will be removed once the
puppetlabs internal documentation processing pipeline is completely based
on puppet-strings.
OPTIONS
-------
* --help:
Print this help message
* --reference:
Build a particular reference. Get a list of references by running
'puppet doc --list'.
EXAMPLE
-------
$ puppet doc -r type > /tmp/type_reference.markdown
AUTHOR
------
Luke Kanies
COPYRIGHT
---------
Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def handle_unknown( opt, arg )
@unknown_args << {:opt => opt, :arg => arg }
true
end
def run_command
return [:rdoc].include?(options[:mode]) ? send(options[:mode]) : other
end
def rdoc
exit_code = 0
files = []
unless @manifest
env = Puppet.lookup(:current_environment)
files += env.modulepath
files << ::File.dirname(env.manifest) if env.manifest != Puppet::Node::Environment::NO_MANIFEST
end
files += command_line.args
Puppet.info _("scanning: %{files}") % { files: files.inspect }
Puppet.settings[:document_all] = options[:all] || false
begin
require_relative '../../puppet/util/rdoc'
if @manifest
Puppet::Util::RDoc.manifestdoc(files)
else
options[:outputdir] = "doc" unless options[:outputdir]
Puppet::Util::RDoc.rdoc(options[:outputdir], files, options[:charset])
end
rescue => detail
Puppet.log_exception(detail, _("Could not generate documentation: %{detail}") % { detail: detail })
exit_code = 1
end
exit exit_code
end
def other
text = ''.dup
with_contents = options[:references].length <= 1
exit_code = 0
require_relative '../../puppet/util/reference'
options[:references].sort_by(&:to_s).each do |name|
section = Puppet::Util::Reference.reference(name)
raise _("Could not find reference %{name}") % { name: name } unless section
begin
# Add the per-section text, but with no ToC
text += section.send(options[:format], with_contents)
rescue => detail
Puppet.log_exception(detail, _("Could not generate reference %{name}: %{detail}") % { name: name, detail: detail })
exit_code = 1
next
end
end
text += Puppet::Util::Reference.footer unless with_contents # We've only got one reference
if options[:mode] == :pdf
Puppet::Util::Reference.pdf(text)
else
puts text
end
exit exit_code
end
def setup
# sole manifest documentation
if command_line.args.size > 0
options[:mode] = :rdoc
@manifest = true
end
if options[:mode] == :rdoc
setup_rdoc
else
setup_reference
end
setup_logging
end
def setup_reference
if options[:all]
# Don't add dynamic references to the "all" list.
require_relative '../../puppet/util/reference'
refs = Puppet::Util::Reference.references(Puppet.lookup(:current_environment))
options[:references] = refs.reject do |ref|
Puppet::Util::Reference.reference(ref).dynamic?
end
end
options[:references] << :type if options[:references].empty?
end
def setup_rdoc
# consume the unknown options
# and feed them as settings
if @unknown_args.size > 0
@unknown_args.each do |option|
# force absolute path for modulepath when passed on commandline
if option[:opt]=="--modulepath"
option[:arg] = option[:arg].split(::File::PATH_SEPARATOR).collect { |p| ::File.expand_path(p) }.join(::File::PATH_SEPARATOR)
end
Puppet.settings.handlearg(option[:opt], option[:arg])
end
end
end
def setup_logging
Puppet::Util::Log.level = :warning
set_log_level
Puppet::Util::Log.newdestination(:console)
end
end
puppet-8.4.0/lib/puppet/application/apply.rb 0000644 0052762 0001160 00000035051 14552052437 021003 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/configurer'
require_relative '../../puppet/util/profiler/aggregate'
class Puppet::Application::Apply < Puppet::Application
require_relative '../../puppet/util/splayer'
include Puppet::Util::Splayer
option("--debug","-d")
option("--execute EXECUTE","-e") do |arg|
options[:code] = arg
end
option("--loadclasses","-L")
option("--test","-t")
option("--verbose","-v")
option("--use-nodes")
option("--detailed-exitcodes")
option("--write-catalog-summary") do |arg|
Puppet[:write_catalog_summary] = arg
end
option("--catalog catalog", "-c catalog") do |arg|
options[:catalog] = arg
end
option("--logdest LOGDEST", "-l") do |arg|
handle_logdest_arg(arg)
end
option("--parseonly") do |_args|
puts "--parseonly has been removed. Please use 'puppet parser validate '"
exit 1
end
def summary
_("Apply Puppet manifests locally")
end
def help
<<~HELP
puppet-apply(8) -- #{summary}
========
SYNOPSIS
--------
Applies a standalone Puppet manifest to the local system.
USAGE
-----
puppet apply [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose]
[-e|--execute] [--detailed-exitcodes] [-L|--loadclasses]
[-l|--logdest syslog|eventlog||console] [--noop]
[--catalog ] [--write-catalog-summary]
DESCRIPTION
-----------
This is the standalone puppet execution tool; use it to apply
individual manifests.
When provided with a modulepath, via command line or config file, puppet
apply can effectively mimic the catalog that would be served by puppet
master with access to the same modules, although there are some subtle
differences. When combined with scheduling and an automated system for
pushing manifests, this can be used to implement a serverless Puppet
site.
Most users should use 'puppet agent' and 'puppet master' for site-wide
manifests.
OPTIONS
-------
Any setting that's valid in the configuration
file is a valid long argument for puppet apply. For example, 'tags' is a
valid setting, so you can specify '--tags ,'
as an argument.
See the configuration file documentation at
https://puppet.com/docs/puppet/latest/configuration.html for the
full list of acceptable parameters. You can generate a commented list of all
configuration options by running puppet with
'--genconfig'.
* --debug:
Enable full debugging.
* --detailed-exitcodes:
Provide extra information about the run via exit codes. If enabled, 'puppet
apply' will use the following exit codes:
0: The run succeeded with no changes or failures; the system was already in
the desired state.
1: The run failed.
2: The run succeeded, and some resources were changed.
4: The run succeeded, and some resources failed.
6: The run succeeded, and included both changes and failures.
* --help:
Print this help message
* --loadclasses:
Load any stored classes. 'puppet agent' caches configured classes
(usually at /etc/puppetlabs/puppet/classes.txt), and setting this option causes
all of those classes to be set in your puppet manifest.
* --logdest:
Where to send log messages. Choose between 'syslog' (the POSIX syslog
service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
file. Defaults to 'console'.
Multiple destinations can be set using a comma separated list
(eg: `/path/file1,console,/path/file2`)"
A path ending with '.json' will receive structured output in JSON format. The
log file will not have an ending ']' automatically written to it due to the
appending nature of logging. It must be appended manually to make the content
valid JSON.
A path ending with '.jsonl' will receive structured output in JSON Lines
format.
* --noop:
Use 'noop' mode where Puppet runs in a no-op or dry-run mode. This
is useful for seeing what changes Puppet will make without actually
executing the changes.
* --execute:
Execute a specific piece of Puppet code
* --test:
Enable the most common options used for testing. These are 'verbose',
'detailed-exitcodes' and 'show_diff'.
* --verbose:
Print extra information.
* --catalog:
Apply a JSON catalog (such as one generated with 'puppet master --compile'). You can
either specify a JSON file or pipe in JSON from standard input.
* --write-catalog-summary
After compiling the catalog saves the resource list and classes list to the node
in the state directory named classes.txt and resources.txt
EXAMPLE
-------
$ puppet apply -l /tmp/manifest.log manifest.pp
$ puppet apply --modulepath=/root/dev/modules -e "include ntpd::server"
$ puppet apply --catalog catalog.json
AUTHOR
------
Luke Kanies
COPYRIGHT
---------
Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def app_defaults
super.merge({
:default_file_terminus => :file_server,
:write_catalog_summary => false
})
end
def run_command
if options[:catalog]
apply
else
main
end
ensure
if @profiler
Puppet::Util::Profiler.remove_profiler(@profiler)
@profiler.shutdown
end
end
def apply
if options[:catalog] == "-"
text = $stdin.read
else
text = Puppet::FileSystem.read(options[:catalog], :encoding => 'utf-8')
end
env = Puppet.lookup(:environments).get(Puppet[:environment])
Puppet.override(:current_environment => env, :loaders => create_loaders(env)) do
catalog = read_catalog(text)
apply_catalog(catalog)
end
end
def main
# rubocop:disable Layout/ExtraSpacing
manifest = get_manifest() # Get either a manifest or nil if apply should use content of Puppet[:code]
splay # splay if needed
facts = get_facts() # facts or nil
node = get_node() # node or error
apply_environment = get_configured_environment(node, manifest)
# rubocop:enable Layout/ExtraSpacing
# TRANSLATORS "puppet apply" is a program command and should not be translated
Puppet.override({:current_environment => apply_environment, :loaders => create_loaders(apply_environment)}, _("For puppet apply")) do
configure_node_facts(node, facts)
# Allow users to load the classes that puppet agent creates.
if options[:loadclasses]
file = Puppet[:classfile]
if Puppet::FileSystem.exist?(file)
unless FileTest.readable?(file)
$stderr.puts _("%{file} is not readable") % { file: file }
exit(63)
end
node.classes = Puppet::FileSystem.read(file, :encoding => 'utf-8').split(/[\s]+/)
end
end
begin
# Compile the catalog
starttime = Time.now
# When compiling, the compiler traps and logs certain errors
# Those that do not lead to an immediate exit are caught by the general
# rule and gets logged.
#
catalog =
begin
Puppet::Resource::Catalog.indirection.find(node.name, :use_node => node)
rescue Puppet::Error
# already logged and handled by the compiler, including Puppet::ParseErrorWithIssue
exit(1)
end
# Resolve all deferred values and replace them / mutate the catalog
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, apply_environment, Puppet[:preprocess_deferred])
# Translate it to a RAL catalog
catalog = catalog.to_ral
catalog.finalize
catalog.retrieval_duration = Time.now - starttime
# We accept either the global option `--write_catalog_summary`
# corresponding to the new setting, or the application option
# `--write-catalog-summary`. The latter is needed to maintain backwards
# compatibility.
#
# Puppet settings parse global options using PuppetOptionParser, but it
# only recognizes underscores, not dashes.
# The base application parses app specific options using ruby's builtin
# OptionParser. As of ruby 2.4, it will accept either underscores or
# dashes, but prefer dashes.
#
# So if underscores are used, the PuppetOptionParser will parse it and
# store that in Puppet[:write_catalog_summary]. If dashes are used,
# OptionParser will parse it, and set Puppet[:write_catalog_summary]. In
# either case, settings will contain the correct value.
if Puppet[:write_catalog_summary]
catalog.write_class_file
catalog.write_resource_file
end
exit_status = apply_catalog(catalog)
if not exit_status
exit(1)
elsif options[:detailed_exitcodes] then
exit(exit_status)
else
exit(0)
end
rescue => detail
Puppet.log_exception(detail)
exit(1)
end
end
end
# Enable all of the most common test options.
def setup_test
Puppet.settings.handlearg("--no-splay")
Puppet.settings.handlearg("--show_diff")
options[:verbose] = true
options[:detailed_exitcodes] = true
end
def setup
setup_test if options[:test]
exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
handle_logdest_arg(Puppet[:logdest])
Puppet::Util::Log.newdestination(:console) unless options[:setdest]
Signal.trap(:INT) do
$stderr.puts _("Exiting")
exit(1)
end
Puppet.settings.use :main, :agent, :ssl
if Puppet[:catalog_cache_terminus]
Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
end
# we want the last report to be persisted locally
Puppet::Transaction::Report.indirection.cache_class = :yaml
set_log_level
if Puppet[:profile]
@profiler = Puppet::Util::Profiler.add_profiler(Puppet::Util::Profiler::Aggregate.new(Puppet.method(:info), "apply"))
end
end
private
def create_loaders(env)
# Ignore both 'cached_puppet_lib' and pcore resource type loaders
Puppet::Pops::Loaders.new(env, false, false)
end
def read_catalog(text)
facts = get_facts()
node = get_node()
configured_environment = get_configured_environment(node)
# TRANSLATORS "puppet apply" is a program command and should not be translated
Puppet.override({:current_environment => configured_environment}, _("For puppet apply")) do
configure_node_facts(node, facts)
# NOTE: Does not set rich_data = true automatically (which would ensure always reading catalog with rich data
# on (seemingly the right thing to do)), but that would remove the ability to test what happens when a
# rich catalog is processed without rich_data being turned on.
format = Puppet::Resource::Catalog.default_format
begin
catalog = Puppet::Resource::Catalog.convert_from(format, text)
rescue => detail
raise Puppet::Error, _("Could not deserialize catalog from %{format}: %{detail}") % { format: format, detail: detail }, detail.backtrace
end
# Resolve all deferred values and replace them / mutate the catalog
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, configured_environment, Puppet[:preprocess_deferred])
catalog.to_ral
end
end
def apply_catalog(catalog)
configurer = Puppet::Configurer.new
configurer.run(:catalog => catalog, :pluginsync => false)
end
# Returns facts or nil
#
def get_facts()
facts = nil
unless Puppet[:node_name_fact].empty?
# Collect our facts.
facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
raise _("Could not find facts for %{node}") % { node: Puppet[:node_name_value] } unless facts
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
facts.name = Puppet[:node_name_value]
end
facts
end
# Returns the node or raises and error if node not found.
#
def get_node()
node = Puppet::Node.indirection.find(Puppet[:node_name_value])
raise _("Could not find node %{node}") % { node: Puppet[:node_name_value] } unless node
node
end
# Returns either a manifest (filename) or nil if apply should use content of Puppet[:code]
#
def get_manifest()
manifest = nil
# Set our code or file to use.
if options[:code] or command_line.args.length == 0
Puppet[:code] = options[:code] || STDIN.read
else
manifest = command_line.args.shift
raise _("Could not find file %{manifest}") % { manifest: manifest } unless Puppet::FileSystem.exist?(manifest)
Puppet.warning(_("Only one file can be applied per run. Skipping %{files}") % { files: command_line.args.join(', ') }) if command_line.args.size > 0
end
manifest
end
# Returns a configured environment, if a manifest is given it overrides what is configured for the environment
# specified by the node (or the current_environment found in the Puppet context).
# The node's resolved environment is modified if needed.
#
def get_configured_environment(node, manifest = nil)
configured_environment = node.environment || Puppet.lookup(:current_environment)
apply_environment = manifest ?
configured_environment.override_with(:manifest => manifest) :
configured_environment
# Modify the node descriptor to use the special apply_environment.
# It is based on the actual environment from the node, or the locally
# configured environment if the node does not specify one.
# If a manifest file is passed on the command line, it overrides
# the :manifest setting of the apply_environment.
node.environment = apply_environment
apply_environment
end
# Mixes the facts into the node, and mixes in server facts
def configure_node_facts(node, facts)
node.merge(facts.values) if facts
# Add server facts so $server_facts[environment] exists when doing a puppet apply
node.add_server_facts({})
end
end
puppet-8.4.0/lib/puppet/application/report.rb 0000644 0052762 0001160 00000000252 14552052437 021164 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/indirection_base'
class Puppet::Application::Report < Puppet::Application::IndirectionBase
end
puppet-8.4.0/lib/puppet/application/resource.rb 0000644 0052762 0001160 00000017217 14552052437 021511 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
class Puppet::Application::Resource < Puppet::Application
environment_mode :not_required
attr_accessor :host, :extra_params
def preinit
@extra_params = [:provider]
end
option("--debug","-d")
option("--verbose","-v")
option("--edit","-e")
option("--to_yaml","-y")
option("--types", "-t") do |_arg|
env = Puppet.lookup(:environments).get(Puppet[:environment]) || create_default_environment
types = []
Puppet::Type.typeloader.loadall(env)
Puppet::Type.eachtype do |t|
next if t.name == :component
types << t.name.to_s
end
puts types.sort
exit(0)
end
option("--param PARAM", "-p") do |arg|
@extra_params << arg.to_sym
end
def summary
_("The resource abstraction layer shell")
end
def help
<<~HELP
puppet-resource(8) -- #{summary}
========
SYNOPSIS
--------
Uses the Puppet RAL to directly interact with the system.
USAGE
-----
puppet resource [-h|--help] [-d|--debug] [-v|--verbose] [-e|--edit]
[-p|--param ] [-t|--types] [-y|--to_yaml]
[] [= ...]
DESCRIPTION
-----------
This command provides simple facilities for converting current system
state into Puppet code, along with some ability to modify the current
state using Puppet's RAL.
By default, you must at least provide a type to list, in which case
puppet resource will tell you everything it knows about all resources of
that type. You can optionally specify an instance name, and puppet
resource will only describe that single instance.
If given a type, a name, and a series of = pairs,
puppet resource will modify the state of the specified resource.
Alternately, if given a type, a name, and the '--edit' flag, puppet
resource will write its output to a file, open that file in an editor,
and then apply the saved file as a Puppet transaction.
OPTIONS
-------
Note that any setting that's valid in the configuration
file is also a valid long argument. For example, 'ssldir' is a valid
setting, so you can specify '--ssldir ' as an
argument.
See the configuration file documentation at
https://puppet.com/docs/puppet/latest/configuration.html for the
full list of acceptable parameters. A commented list of all
configuration options can also be generated by running puppet with
'--genconfig'.
* --debug:
Enable full debugging.
* --edit:
Write the results of the query to a file, open the file in an editor,
and read the file back in as an executable Puppet manifest.
* --help:
Print this help message.
* --param:
Add more parameters to be outputted from queries.
* --types:
List all available types.
* --verbose:
Print extra information.
* --to_yaml:
Output found resources in yaml format, suitable to use with Hiera and
create_resources.
EXAMPLE
-------
This example uses `puppet resource` to return a Puppet configuration for
the user `luke`:
$ puppet resource user luke
user { 'luke':
home => '/home/luke',
uid => '100',
ensure => 'present',
comment => 'Luke Kanies,,,',
gid => '1000',
shell => '/bin/bash',
groups => ['sysadmin','audio','video','puppet']
}
AUTHOR
------
Luke Kanies
COPYRIGHT
---------
Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def main
# If the specified environment does not exist locally, fall back to the default (production) environment
env = Puppet.lookup(:environments).get(Puppet[:environment]) || create_default_environment
Puppet.override(:current_environment => env, :loaders => Puppet::Pops::Loaders.new(env)) do
type, name, params = parse_args(command_line.args)
raise _("Editing with Yaml output is not supported") if options[:edit] and options[:to_yaml]
resources = find_or_save_resources(type, name, params)
if options[:to_yaml]
data = resources.map do |resource|
resource.prune_parameters(:parameters_to_include => @extra_params).to_hiera_hash
end.inject(:merge!)
text = YAML.dump(type.downcase => data)
else
text = resources.map do |resource|
resource.prune_parameters(:parameters_to_include => @extra_params).to_manifest.force_encoding(Encoding.default_external)
end.join("\n")
end
options[:edit] ?
handle_editing(text) :
(puts text)
end
end
def setup
Puppet::Util::Log.newdestination(:console)
set_log_level
end
private
def local_key(type, name)
[type, name].join('/')
end
def handle_editing(text)
require 'tempfile'
# Prefer the current directory, which is more likely to be secure
# and, in the case of interactive use, accessible to the user.
tmpfile = Tempfile.new('x2puppet', Dir.pwd, :encoding => Encoding::UTF_8)
begin
# sync write, so nothing buffers before we invoke the editor.
tmpfile.sync = true
tmpfile.puts text
# edit the content
system(ENV["EDITOR"] || 'vi', tmpfile.path)
# ...and, now, pass that file to puppet to apply. Because
# many editors rename or replace the original file we need to
# feed the pathname, not the file content itself, to puppet.
system('puppet apply -v ' + tmpfile.path)
ensure
# The temporary file will be safely removed.
tmpfile.close(true)
end
end
def parse_args(args)
type = args.shift or raise _("You must specify the type to display")
Puppet::Type.type(type) or raise _("Could not find type %{type}") % { type: type }
name = args.shift
params = {}
args.each do |setting|
if setting =~ /^(\w+)=(.+)$/
params[$1] = $2
else
raise _("Invalid parameter setting %{setting}") % { setting: setting }
end
end
[type, name, params]
end
def create_default_environment
Puppet.debug("Specified environment '#{Puppet[:environment]}' does not exist on the filesystem, defaulting to 'production'")
Puppet[:environment] = :production
basemodulepath = Puppet::Node::Environment.split_path(Puppet[:basemodulepath])
modulepath = Puppet[:modulepath]
modulepath = (modulepath.nil? || modulepath.empty?) ? basemodulepath : Puppet::Node::Environment.split_path(modulepath)
Puppet::Node::Environment.create(Puppet[:environment], modulepath, Puppet::Node::Environment::NO_MANIFEST)
end
def find_or_save_resources(type, name, params)
key = local_key(type, name)
Puppet.override(stringify_rich: true) do
if name
if params.empty?
[ Puppet::Resource.indirection.find( key ) ]
else
resource = Puppet::Resource.new( type, name, :parameters => params )
# save returns [resource that was saved, transaction log from applying the resource]
save_result = Puppet::Resource.indirection.save(resource, key)
[ save_result.first ]
end
else
if type == "file"
raise _("Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc")
end
Puppet::Resource.indirection.search( key, {} )
end
end
end
end
puppet-8.4.0/lib/puppet/application/script.rb 0000644 0052762 0001160 00000021107 14552052437 021157 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/configurer'
require_relative '../../puppet/util/profiler/aggregate'
require_relative '../../puppet/parser/script_compiler'
class Puppet::Application::Script < Puppet::Application
option("--debug","-d")
option("--execute EXECUTE","-e") do |arg|
options[:code] = arg
end
option("--test","-t")
option("--verbose","-v")
option("--logdest LOGDEST", "-l") do |arg|
handle_logdest_arg(arg)
end
def summary
_("Run a puppet manifests as a script without compiling a catalog")
end
def help
<<~HELP
puppet-script(8) -- #{summary}
========
SYNOPSIS
--------
Runs a puppet language script without compiling a catalog.
USAGE
-----
puppet script [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose]
[-e|--execute]
[-l|--logdest syslog|eventlog||console] [--noop]
DESCRIPTION
-----------
This is a standalone puppet script runner tool; use it to run puppet code
without compiling a catalog.
When provided with a modulepath, via command line or config file, puppet
script can load functions, types, tasks and plans from modules.
OPTIONS
-------
Note that any setting that's valid in the configuration
file is also a valid long argument. For example, 'environment' is a
valid setting, so you can specify '--environment mytest'
as an argument.
See the configuration file documentation at
https://puppet.com/docs/puppet/latest/configuration.html for the
full list of acceptable parameters. A commented list of all
configuration options can also be generated by running puppet with
'--genconfig'.
* --debug:
Enable full debugging.
* --help:
Print this help message
* --logdest:
Where to send log messages. Choose between 'syslog' (the POSIX syslog
service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
file. Defaults to 'console'.
Multiple destinations can be set using a comma separated list
(eg: `/path/file1,console,/path/file2`)"
A path ending with '.json' will receive structured output in JSON format. The
log file will not have an ending ']' automatically written to it due to the
appending nature of logging. It must be appended manually to make the content
valid JSON.
A path ending with '.jsonl' will receive structured output in JSON Lines
format.
* --noop:
Use 'noop' mode where Puppet runs in a no-op or dry-run mode. This
is useful for seeing what changes Puppet will make without actually
executing the changes. Applies to tasks only.
* --execute:
Execute a specific piece of Puppet code
* --verbose:
Print extra information.
EXAMPLE
-------
$ puppet script -l /tmp/manifest.log manifest.pp
$ puppet script --modulepath=/root/dev/modules -e 'notice("hello world")'
AUTHOR
------
Henrik Lindberg
COPYRIGHT
---------
Copyright (c) 2017 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def app_defaults
super.merge({
:default_file_terminus => :file_server,
})
end
def run_command
if Puppet.features.bolt?
Puppet.override(:bolt_executor => Bolt::Executor.new) do
main
end
else
raise _("Bolt must be installed to use the script application")
end
end
def main
# The tasks feature is always on
Puppet[:tasks] = true
# Set the puppet code or file to use.
if options[:code] || command_line.args.length == 0
Puppet[:code] = options[:code] || STDIN.read
else
manifest = command_line.args.shift
raise _("Could not find file %{manifest}") % { manifest: manifest } unless Puppet::FileSystem.exist?(manifest)
Puppet.warning(_("Only one file can be used per run. Skipping %{files}") % { files: command_line.args.join(', ') }) if command_line.args.size > 0
end
unless Puppet[:node_name_fact].empty?
# Collect the facts specified for that node
facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
raise _("Could not find facts for %{node}") % { node: Puppet[:node_name_value] } unless facts
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
facts.name = Puppet[:node_name_value]
end
# Find the Node
node = Puppet::Node.indirection.find(Puppet[:node_name_value])
raise _("Could not find node %{node}") % { node: Puppet[:node_name_value] } unless node
configured_environment = node.environment || Puppet.lookup(:current_environment)
apply_environment = manifest ?
configured_environment.override_with(:manifest => manifest) :
configured_environment
# Modify the node descriptor to use the special apply_environment.
# It is based on the actual environment from the node, or the locally
# configured environment if the node does not specify one.
# If a manifest file is passed on the command line, it overrides
# the :manifest setting of the apply_environment.
node.environment = apply_environment
# TRANSLATION, the string "For puppet script" is not user facing
Puppet.override({:current_environment => apply_environment}, "For puppet script") do
# Merge in the facts.
node.merge(facts.values) if facts
# Add server facts so $server_facts[environment] exists when doing a puppet script
# SCRIPT TODO: May be needed when running scripts under orchestrator. Leave it for now.
#
node.add_server_facts({})
begin
# Compile the catalog
# When compiling, the compiler traps and logs certain errors
# Those that do not lead to an immediate exit are caught by the general
# rule and gets logged.
#
begin
# support the following features when evaluating puppet code
# * $facts with facts from host running the script
# * $settings with 'settings::*' namespace populated, and '$settings::all_local' hash
# * $trusted as setup when using puppet apply
# * an environment
#
# fixup trusted information
node.sanitize()
compiler = Puppet::Parser::ScriptCompiler.new(node.environment, node.name)
topscope = compiler.topscope
# When scripting the trusted data are always local, but set them anyway
topscope.set_trusted(node.trusted_data)
# Server facts are always about the local node's version etc.
topscope.set_server_facts(node.server_facts)
# Set $facts for the node running the script
facts_hash = node.facts.nil? ? {} : node.facts.values
topscope.set_facts(facts_hash)
# create the $settings:: variables
topscope.merge_settings(node.environment.name, false)
compiler.compile()
rescue Puppet::Error
# already logged and handled by the compiler, including Puppet::ParseErrorWithIssue
exit(1)
end
exit(0)
rescue => detail
Puppet.log_exception(detail)
exit(1)
end
end
ensure
if @profiler
Puppet::Util::Profiler.remove_profiler(@profiler)
@profiler.shutdown
end
end
def setup
exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
handle_logdest_arg(Puppet[:logdest])
Puppet::Util::Log.newdestination(:console) unless options[:setdest]
Signal.trap(:INT) do
$stderr.puts _("Exiting")
exit(1)
end
# TODO: This skips applying the settings catalog for these settings, but
# the effect of doing this is unknown. It may be that it only works if there is a puppet
# installed where a settings catalog have already been applied...
# This saves 1/5th of the startup time
# Puppet.settings.use :main, :agent, :ssl
# When running a script, the catalog is not relevant, and neither is caching of it
Puppet::Resource::Catalog.indirection.cache_class = nil
# we do not want the last report to be persisted
Puppet::Transaction::Report.indirection.cache_class = nil
set_log_level
if Puppet[:profile]
@profiler = Puppet::Util::Profiler.add_profiler(Puppet::Util::Profiler::Aggregate.new(Puppet.method(:info), "script"))
end
end
end
puppet-8.4.0/lib/puppet/application/face_base.rb 0000644 0052762 0001160 00000023425 14552052437 021550 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/face'
require 'optparse'
require 'pp'
class Puppet::Application::FaceBase < Puppet::Application
option("--debug", "-d") do |_arg|
set_log_level(:debug => true)
end
option("--verbose", "-v") do |_|
set_log_level(:verbose => true)
end
option("--render-as FORMAT") do |format|
self.render_as = format.to_sym
end
option("--help", "-h") do |_arg|
if action && !@is_default_action
# Only invoke help on the action if it was specified, not if
# it was the default action.
puts Puppet::Face[:help, :current].help(face.name, action.name)
else
puts Puppet::Face[:help, :current].help(face.name)
end
exit(0)
end
attr_reader :render_as
attr_accessor :face, :action, :type, :arguments
def render_as=(format)
@render_as = Puppet::Network::FormatHandler.format(format)
@render_as or raise ArgumentError, _("I don't know how to render '%{format}'") % { format: format }
end
def render(result, args_and_options)
hook = action.when_rendering(render_as.name)
if hook
# when defining when_rendering on your action you can optionally
# include arguments and options
if hook.arity > 1
result = hook.call(result, *args_and_options)
else
result = hook.call(result)
end
end
render_as.render(result)
end
def preinit
super
Signal.trap(:INT) do
$stderr.puts _("Cancelling Face")
exit(0)
end
end
def parse_options
# We need to parse enough of the command line out early, to identify what
# the action is, so that we can obtain the full set of options to parse.
# REVISIT: These should be configurable versions, through a global
# '--version' option, but we don't implement that yet... --daniel 2011-03-29
@type = Puppet::Util::ConstantInflector.constant2file(self.class.name.to_s.sub(/.+:/, '')).to_sym
@face = Puppet::Face[@type, :current]
# Now, walk the command line and identify the action. We skip over
# arguments based on introspecting the action and all, and find the first
# non-option word to use as the action.
action_name = nil
index = -1
until action_name or (index += 1) >= command_line.args.length do
item = command_line.args[index]
if item =~ /^-/
option = @face.options.find do |name|
item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/
end
if option
option = @face.get_option(option)
# If we have an inline argument, just carry on. We don't need to
# care about optional vs mandatory in that case because we do a real
# parse later, and that will totally take care of raising the error
# when we get there. --daniel 2011-04-04
if option.takes_argument? and !item.index('=')
index += 1 unless
(option.optional_argument? and command_line.args[index + 1] =~ /^-/)
end
else
option = find_global_settings_argument(item)
if option
unless Puppet.settings.boolean? option.name
# As far as I can tell, we treat non-bool options as always having
# a mandatory argument. --daniel 2011-04-05
# ... But, the mandatory argument will not be the next item if an = is
# employed in the long form of the option. --jeffmccune 2012-09-18
index += 1 unless item =~ /^--#{option.name}=/
end
else
option = find_application_argument(item)
if option
index += 1 if (option[:argument] and not option[:optional])
else
raise OptionParser::InvalidOption.new(item.sub(/=.*$/, ''))
end
end
end
else
# Stash away the requested action name for later, and try to fetch the
# action object it represents; if this is an invalid action name that
# will be nil, and handled later.
action_name = item.to_sym
@action = Puppet::Face.find_action(@face.name, action_name)
@face = @action.face if @action
end
end
if @action.nil?
@action = @face.get_default_action()
if @action
@is_default_action = true
else
# First try to handle global command line options
# But ignoring invalid options as this is a invalid action, and
# we want the error message for that instead.
begin
super
rescue OptionParser::InvalidOption
end
face = @face.name
action = action_name.nil? ? 'default' : "'#{action_name}'"
msg = _("'%{face}' has no %{action} action. See `puppet help %{face}`.") % { face: face, action: action }
Puppet.err(msg)
Puppet::Util::Log.force_flushqueue()
exit false
end
end
# Now we can interact with the default option code to build behaviour
# around the full set of options we now know we support.
@action.options.each do |o|
o = @action.get_option(o) # make it the object.
self.class.option(*o.optparse) # ...and make the CLI parse it.
end
# ...and invoke our parent to parse all the command line options.
super
end
def find_global_settings_argument(item)
Puppet.settings.each do |_name, object|
object.optparse_args.each do |arg|
next unless arg =~ /^-/
# sadly, we have to emulate some of optparse here...
pattern = /^#{arg.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/
pattern.match item and return object
end
end
return nil # nothing found.
end
def find_application_argument(item)
self.class.option_parser_commands.each do |options, _function|
options.each do |option|
next unless option =~ /^-/
pattern = /^#{option.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/
next unless pattern.match(item)
return {
:argument => option =~ /[ =]/,
:optional => option =~ /[ =]\[/
}
end
end
return nil # not found
end
def setup
Puppet::Util::Log.newdestination :console
@arguments = command_line.args
# Note: because of our definition of where the action is set, we end up
# with it *always* being the first word of the remaining set of command
# line arguments. So, strip that off when we construct the arguments to
# pass down to the face action. --daniel 2011-04-04
# Of course, now that we have default actions, we should leave the
# "action" name on if we didn't actually consume it when we found our
# action.
@arguments.delete_at(0) unless @is_default_action
# We copy all of the app options to the end of the call; This allows each
# action to read in the options. This replaces the older model where we
# would invoke the action with options set as global state in the
# interface object. --daniel 2011-03-28
@arguments << options
# If we don't have a rendering format, set one early.
self.render_as ||= (@action.render_as || :console)
end
def main
status = false
# Call the method associated with the provided action (e.g., 'find').
unless @action
puts Puppet::Face[:help, :current].help(@face.name)
raise _("%{face} does not respond to action %{arg}") % { face: face, arg: arguments.first }
end
# We need to do arity checking here because this is generic code
# calling generic methods – that have argument defaulting. We need to
# make sure we don't accidentally pass the options as the first
# argument to a method that takes one argument. eg:
#
# puppet facts find
# => options => {}
# @arguments => [{}]
# => @face.send :bar, {}
#
# def face.bar(argument, options = {})
# => bar({}, {}) # oops! we thought the options were the
# # positional argument!!
#
# We could also fix this by making it mandatory to pass the options on
# every call, but that would make the Ruby API much more annoying to
# work with; having the defaulting is a much nicer convention to have.
#
# We could also pass the arguments implicitly, by having a magic
# 'options' method that was visible in the scope of the action, which
# returned the right stuff.
#
# That sounds attractive, but adds complications to all sorts of
# things, especially when you think about how to pass options when you
# are writing Ruby code that calls multiple faces. Especially if
# faces are involved in that. ;)
#
# --daniel 2011-04-27
if (arity = @action.positional_arg_count) > 0
unless (count = arguments.length) == arity then
raise ArgumentError, n_("puppet %{face} %{action} takes %{arg_count} argument, but you gave %{given_count}", "puppet %{face} %{action} takes %{arg_count} arguments, but you gave %{given_count}", arity - 1) % { face: @face.name, action: @action.name, arg_count: arity-1, given_count: count-1 }
end
end
if @face.deprecated?
Puppet.deprecation_warning(_("'puppet %{face}' is deprecated and will be removed in a future release") % { face: @face.name })
end
result = @face.send(@action.name, *arguments)
puts render(result, arguments) unless result.nil?
status = true
# We need an easy way for the action to set a specific exit code, so we
# rescue SystemExit here; This allows each action to set the desired exit
# code by simply calling Kernel::exit. eg:
#
# exit(2)
#
# --kelsey 2012-02-14
rescue SystemExit => detail
status = detail.status
rescue => detail
Puppet.log_exception(detail)
Puppet.err _("Try 'puppet help %{face} %{action}' for usage") % { face: @face.name, action: @action.name }
ensure
exit status
end
end
puppet-8.4.0/lib/puppet/application/epp.rb 0000644 0052762 0001160 00000000276 14552052437 020443 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
require_relative '../../puppet/face'
class Puppet::Application::Epp < Puppet::Application::FaceBase
end
puppet-8.4.0/lib/puppet/application/node.rb 0000644 0052762 0001160 00000000250 14552052437 020574 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/indirection_base'
class Puppet::Application::Node < Puppet::Application::IndirectionBase
end
puppet-8.4.0/lib/puppet/application/device.rb 0000644 0052762 0001160 00000037645 14552052437 021130 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
require_relative '../../puppet/configurer'
require_relative '../../puppet/util/network_device'
require_relative '../../puppet/ssl/oids'
class Puppet::Application::Device < Puppet::Application
run_mode :agent
attr_accessor :args, :agent, :host
def app_defaults
super.merge({
:catalog_terminus => :rest,
:catalog_cache_terminus => :json,
:node_terminus => :rest,
:facts_terminus => :network_device,
})
end
def preinit
# Do an initial trap, so that cancels don't get a stack trace.
Signal.trap(:INT) do
$stderr.puts _("Cancelling startup")
exit(0)
end
{
:apply => nil,
:waitforcert => nil,
:detailed_exitcodes => false,
:verbose => false,
:debug => false,
:centrallogs => false,
:setdest => false,
:resource => false,
:facts => false,
:target => nil,
:to_yaml => false,
}.each do |opt,val|
options[opt] = val
end
@args = {}
end
option("--centrallogging")
option("--debug","-d")
option("--resource","-r")
option("--facts","-f")
option("--to_yaml","-y")
option("--verbose","-v")
option("--detailed-exitcodes") do |_arg|
options[:detailed_exitcodes] = true
end
option("--libdir LIBDIR") do |arg|
options[:libdir] = arg
end
option("--apply MANIFEST") do |arg|
options[:apply] = arg.to_s
end
option("--logdest DEST", "-l DEST") do |arg|
handle_logdest_arg(arg)
end
option("--waitforcert WAITFORCERT", "-w") do |arg|
options[:waitforcert] = arg.to_i
end
option("--port PORT","-p") do |arg|
@args[:Port] = arg
end
option("--target DEVICE", "-t") do |arg|
options[:target] = arg.to_s
end
def summary
_("Manage remote network devices")
end
def help
<<~HELP
puppet-device(8) -- #{summary}
========
SYNOPSIS
--------
Retrieves catalogs from the Puppet master and applies them to remote devices.
This subcommand can be run manually; or periodically using cron,
a scheduled task, or a similar tool.
USAGE
-----
puppet device [-h|--help] [-v|--verbose] [-d|--debug]
[-l|--logdest syslog||console] [--detailed-exitcodes]
[--deviceconfig ] [-w|--waitforcert ]
[--libdir ]
[-a|--apply ] [-f|--facts] [-r|--resource [name]]
[-t|--target ] [--user=] [-V|--version]
DESCRIPTION
-----------
Devices require a proxy Puppet agent to request certificates, collect facts,
retrieve and apply catalogs, and store reports.
USAGE NOTES
-----------
Devices managed by the puppet-device subcommand on a Puppet agent are
configured in device.conf, which is located at $confdir/device.conf by default,
and is configurable with the $deviceconfig setting.
The device.conf file is an INI-like file, with one section per device:
[]
type
url
debug
The section name specifies the certname of the device.
The values for the type and url properties are specific to each type of device.
The optional debug property specifies transport-level debugging,
and is limited to telnet and ssh transports.
See https://puppet.com/docs/puppet/latest/config_file_device.html for details.
OPTIONS
-------
Note that any setting that's valid in the configuration file is also a valid
long argument. For example, 'server' is a valid configuration parameter, so
you can specify '--server ' as an argument.
* --help, -h:
Print this help message
* --verbose, -v:
Turn on verbose reporting.
* --debug, -d:
Enable full debugging.
* --logdest, -l:
Where to send log messages. Choose between 'syslog' (the POSIX syslog
service), 'console', or the path to a log file. If debugging or verbosity is
enabled, this defaults to 'console'. Otherwise, it defaults to 'syslog'.
Multiple destinations can be set using a comma separated list
(eg: `/path/file1,console,/path/file2`)"
A path ending with '.json' will receive structured output in JSON format. The
log file will not have an ending ']' automatically written to it due to the
appending nature of logging. It must be appended manually to make the content
valid JSON.
* --detailed-exitcodes:
Provide transaction information via exit codes. If this is enabled, an exit
code of '1' means at least one device had a compile failure, an exit code of
'2' means at least one device had resource changes, and an exit code of '4'
means at least one device had resource failures. Exit codes of '3', '5', '6',
or '7' means that a bitwise combination of the preceding exit codes happened.
* --deviceconfig:
Path to the device config file for puppet device.
Default: $confdir/device.conf
* --waitforcert, -w:
This option only matters for targets that do not yet have certificates
and it is enabled by default, with a value of 120 (seconds). This causes
+puppet device+ to poll the server every 2 minutes and ask it to sign a
certificate request. This is useful for the initial setup of a target.
You can turn off waiting for certificates by specifying a time of 0.
* --libdir:
Override the per-device libdir with a local directory. Specifying a libdir also
disables pluginsync. This is useful for testing.
A path ending with '.jsonl' will receive structured output in JSON Lines
format.
* --apply:
Apply a manifest against a remote target. Target must be specified.
* --facts:
Displays the facts of a remote target. Target must be specified.
* --resource:
Displays a resource state as Puppet code, roughly equivalent to
`puppet resource`. Can be filtered by title. Requires --target be specified.
* --target:
Target a specific device/certificate in the device.conf. Doing so will perform a
device run against only that device/certificate.
* --to_yaml:
Output found resources in yaml format, suitable to use with Hiera and
create_resources.
* --user:
The user to run as.
EXAMPLE
-------
$ puppet device --target remotehost --verbose
AUTHOR
------
Brice Figureau
COPYRIGHT
---------
Copyright (c) 2011-2018 Puppet Inc., LLC
Licensed under the Apache 2.0 License
HELP
end
def main
if options[:resource] and !options[:target]
raise _("resource command requires target")
end
if options[:facts] and !options[:target]
raise _("facts command requires target")
end
unless options[:apply].nil?
raise _("missing argument: --target is required when using --apply") if options[:target].nil?
raise _("%{file} does not exist, cannot apply") % { file: options[:apply] } unless File.file?(options[:apply])
end
libdir = Puppet[:libdir]
vardir = Puppet[:vardir]
confdir = Puppet[:confdir]
ssldir = Puppet[:ssldir]
certname = Puppet[:certname]
env = Puppet::Node::Environment.remote(Puppet[:environment])
returns = Puppet.override(:current_environment => env, :loaders => Puppet::Pops::Loaders.new(env)) do
# find device list
require_relative '../../puppet/util/network_device/config'
devices = Puppet::Util::NetworkDevice::Config.devices.dup
if options[:target]
devices.select! { |key, _value| key == options[:target] }
end
if devices.empty?
if options[:target]
raise _("Target device / certificate '%{target}' not found in %{config}") % { target: options[:target], config: Puppet[:deviceconfig] }
else
Puppet.err _("No device found in %{config}") % { config: Puppet[:deviceconfig] }
exit(1)
end
end
devices.collect do |_devicename,device|
# TODO when we drop support for ruby < 2.5 we can remove the extra block here
begin
device_url = URI.parse(device.url)
# Handle nil scheme & port
scheme = "#{device_url.scheme}://" if device_url.scheme
port = ":#{device_url.port}" if device_url.port
# override local $vardir and $certname
Puppet[:ssldir] = ::File.join(Puppet[:deviceconfdir], device.name, 'ssl')
Puppet[:confdir] = ::File.join(Puppet[:devicedir], device.name)
Puppet[:libdir] = options[:libdir] || ::File.join(Puppet[:devicedir], device.name, 'lib')
Puppet[:vardir] = ::File.join(Puppet[:devicedir], device.name)
Puppet[:certname] = device.name
ssl_context = nil
# create device directory under $deviceconfdir
Puppet::FileSystem.dir_mkpath(Puppet[:ssldir]) unless Puppet::FileSystem.dir_exist?(Puppet[:ssldir])
# this will reload and recompute default settings and create device-specific sub vardir
Puppet.settings.use :main, :agent, :ssl
# Workaround for PUP-8736: store ssl certs outside the cache directory to prevent accidental removal and keep the old path as symlink
optssldir = File.join(Puppet[:confdir], 'ssl')
Puppet::FileSystem.symlink(Puppet[:ssldir], optssldir) unless Puppet::FileSystem.exist?(optssldir)
unless options[:resource] || options[:facts] || options[:apply]
# Since it's too complicated to fix properly in the default settings, we workaround for PUP-9642 here.
# See https://github.com/puppetlabs/puppet/pull/7483#issuecomment-483455997 for details.
# This has to happen after `settings.use` above, so the directory is created and before `setup_host` below, where the SSL
# routines would fail with access errors
if Puppet.features.root? && !Puppet::Util::Platform.windows?
user = Puppet::Type.type(:user).new(name: Puppet[:user]).exists? ? Puppet[:user] : nil
group = Puppet::Type.type(:group).new(name: Puppet[:group]).exists? ? Puppet[:group] : nil
Puppet.debug("Fixing perms for #{user}:#{group} on #{Puppet[:confdir]}")
FileUtils.chown(user, group, Puppet[:confdir]) if user || group
end
ssl_context = setup_context
unless options[:libdir]
Puppet.override(ssl_context: ssl_context) do
Puppet::Configurer::PluginHandler.new.download_plugins(env) if Puppet::Configurer.should_pluginsync?
end
end
end
# this inits the device singleton, so that the facts terminus
# and the various network_device provider can use it
Puppet::Util::NetworkDevice.init(device)
if options[:resource]
type, name = parse_args(command_line.args)
Puppet.info _("retrieving resource: %{resource} from %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { resource: type, target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
resources = find_resources(type, name)
if options[:to_yaml]
data = resources.map do |resource|
resource.prune_parameters(:parameters_to_include => @extra_params).to_hiera_hash
end.inject(:merge!)
text = YAML.dump(type.downcase => data)
else
text = resources.map do |resource|
resource.prune_parameters(:parameters_to_include => @extra_params).to_manifest.force_encoding(Encoding.default_external)
end.join("\n")
end
(puts text)
0
elsif options[:facts]
Puppet.info _("retrieving facts from %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { resource: type, target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
remote_facts = Puppet::Node::Facts.indirection.find(name, :environment => env)
# Give a proper name to the facts
remote_facts.name = remote_facts.values['clientcert']
renderer = Puppet::Network::FormatHandler.format(:console)
puts renderer.render(remote_facts)
0
elsif options[:apply]
# avoid reporting to server
Puppet::Transaction::Report.indirection.terminus_class = :yaml
Puppet::Resource::Catalog.indirection.cache_class = nil
require_relative '../../puppet/application/apply'
begin
Puppet[:node_terminus] = :plain
Puppet[:catalog_terminus] = :compiler
Puppet[:catalog_cache_terminus] = nil
Puppet[:facts_terminus] = :network_device
Puppet.override(:network_device => true) do
Puppet::Application::Apply.new(Puppet::Util::CommandLine.new('puppet', ["apply", options[:apply]])).run_command
end
end
else
Puppet.info _("starting applying configuration to %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
overrides = {}
overrides[:ssl_context] = ssl_context if ssl_context
Puppet.override(overrides) do
configurer = Puppet::Configurer.new
configurer.run(:network_device => true, :pluginsync => false)
end
end
rescue => detail
Puppet.log_exception(detail)
# If we rescued an error, then we return 1 as the exit code
1
ensure
Puppet[:libdir] = libdir
Puppet[:vardir] = vardir
Puppet[:confdir] = confdir
Puppet[:ssldir] = ssldir
Puppet[:certname] = certname
end
end
end
if ! returns or returns.compact.empty?
exit(1)
elsif options[:detailed_exitcodes]
# Bitwise OR the return codes together, puppet style
exit(returns.compact.reduce(:|))
elsif returns.include? 1
exit(1)
else
exit(0)
end
end
def parse_args(args)
type = args.shift or raise _("You must specify the type to display")
Puppet::Type.type(type) or raise _("Could not find type %{type}") % { type: type }
name = args.shift
[type, name]
end
def find_resources(type, name)
key = [type, name].join('/')
if name
[ Puppet::Resource.indirection.find( key ) ]
else
Puppet::Resource.indirection.search( key, {} )
end
end
def setup_context
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert)
sm.ensure_client_certificate
end
def setup
setup_logs
Puppet::SSL::Oids.register_puppet_oids
# setup global device-specific defaults; creates all necessary directories, etc
Puppet.settings.use :main, :agent, :device, :ssl
if options[:apply] || options[:facts] || options[:resource]
Puppet::Util::Log.newdestination(:console)
else
args[:Server] = Puppet[:server]
if options[:centrallogs]
logdest = args[:Server]
logdest += ":" + args[:Port] if args.include?(:Port)
Puppet::Util::Log.newdestination(logdest)
end
Puppet::Transaction::Report.indirection.terminus_class = :rest
if Puppet[:catalog_cache_terminus]
Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus].intern
end
end
end
end
puppet-8.4.0/lib/puppet/application/describe.rb 0000644 0052762 0001160 00000013011 14552052437 021426 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application'
class Formatter
def initialize(width)
@width = width
end
def wrap(txt, opts)
return "" unless txt && !txt.empty?
work = (opts[:scrub] ? scrub(txt) : txt)
indent = (opts[:indent] ? opts[:indent] : 0)
textLen = @width - indent
patt = Regexp.new("\\A(.{0,#{textLen}})[ \n]")
prefix = " " * indent
res = []
while work.length > textLen
if work =~ patt
res << $1
work.slice!(0, $MATCH.length)
else
res << work.slice!(0, textLen)
end
end
res << work if work.length.nonzero?
prefix + res.join("\n#{prefix}")
end
def header(txt, sep = "-")
"\n#{txt}\n" + sep * txt.size
end
private
def scrub(text)
# For text with no carriage returns, there's nothing to do.
return text if text !~ /\n/
# If we can match an indentation, then just remove that same level of
# indent from every line.
if text =~ /^(\s+)/
indent = $1
return text.gsub(/^#{indent}/,'')
else
return text
end
end
end
class TypeDoc
def initialize
@format = Formatter.new(76)
@types = {}
Puppet::Type.loadall
Puppet::Type.eachtype { |type|
next if type.name == :component
@types[type.name] = type
}
end
def list_types
puts "These are the types known to puppet:\n"
@types.keys.sort_by(&:to_s).each do |name|
type = @types[name]
s = type.doc.gsub(/\s+/, " ")
if s.empty?
s = ".. no documentation .."
else
n = s.index(".") || s.length
if n > 45
s = s[0, 45] + " ..."
else
s = s[0, n]
end
end
printf "%-15s - %s\n", name, s
end
end
def format_type(name, opts)
name = name.to_sym
unless @types.has_key?(name)
puts "Unknown type #{name}"
return
end
type = @types[name]
puts @format.header(name.to_s, "=")
puts @format.wrap(type.doc, :indent => 0, :scrub => true) + "\n\n"
puts @format.header("Parameters")
if opts[:parameters]
format_attrs(type, [:property, :param])
else
list_attrs(type, [:property, :param])
end
if opts[:meta]
puts @format.header("Meta Parameters")
if opts[:parameters]
format_attrs(type, [:meta])
else
list_attrs(type, [:meta])
end
end
if type.providers.size > 0
puts @format.header("Providers")
if opts[:providers]
format_providers(type)
else
list_providers(type)
end
end
end
# List details about attributes
def format_attrs(type, attrs)
docs = {}
type.allattrs.each do |name|
kind = type.attrtype(name)
docs[name] = type.attrclass(name).doc if attrs.include?(kind) && name != :provider
end
docs.sort { |a,b|
a[0].to_s <=> b[0].to_s
}.each { |name, doc|
print "\n- **#{name}**"
if type.key_attributes.include?(name) and name != :name
puts " (*namevar*)"
else
puts ""
end
puts @format.wrap(doc, :indent => 4, :scrub => true)
}
end
# List the names of attributes
def list_attrs(type, attrs)
params = []
type.allattrs.each do |name|
kind = type.attrtype(name)
params << name.to_s if attrs.include?(kind) && name != :provider
end
puts @format.wrap(params.sort.join(", "), :indent => 4)
end
def format_providers(type)
type.providers.sort_by(&:to_s).each { |prov|
puts "\n- **#{prov}**"
puts @format.wrap(type.provider(prov).doc, :indent => 4, :scrub => true)
}
end
def list_providers(type)
list = type.providers.sort_by(&:to_s).join(", ")
puts @format.wrap(list, :indent => 4)
end
end
class Puppet::Application::Describe < Puppet::Application
banner "puppet describe [options] [type]"
option("--short", "-s", "Only list parameters without detail") do |_arg|
options[:parameters] = false
end
option("--providers","-p")
option("--list", "-l")
option("--meta","-m")
def summary
_("Display help about resource types")
end
def help
<<~HELP
puppet-describe(8) -- #{summary}
========
SYNOPSIS
--------
Prints help about Puppet resource types, providers, and metaparameters.
USAGE
-----
puppet describe [-h|--help] [-s|--short] [-p|--providers] [-l|--list] [-m|--meta]
OPTIONS
-------
* --help:
Print this help text
* --providers:
Describe providers in detail for each type
* --list:
List all types
* --meta:
List all metaparameters
* --short:
List only parameters without detail
EXAMPLE
-------
$ puppet describe --list
$ puppet describe file --providers
$ puppet describe user -s -m
AUTHOR
------
David Lutterkort
COPYRIGHT
---------
Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
HELP
end
def preinit
options[:parameters] = true
end
def main
doc = TypeDoc.new
if options[:list]
doc.list_types
else
options[:types].each { |name| doc.format_type(name, options) }
end
end
def setup
options[:types] = command_line.args.dup
handle_help(nil) unless options[:list] || options[:types].size > 0
$stderr.puts "Warning: ignoring types when listing all types" if options[:list] && options[:types].size > 0
end
end
puppet-8.4.0/lib/puppet/application/parser.rb 0000644 0052762 0001160 00000000301 14552052437 021140 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/application/face_base'
require_relative '../../puppet/face'
class Puppet::Application::Parser < Puppet::Application::FaceBase
end
puppet-8.4.0/lib/puppet/reports/ 0000755 0052762 0001160 00000000000 14552052637 016522 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/reports/store.rb 0000644 0052762 0001160 00000003665 14552052437 020213 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet'
require 'fileutils'
require_relative '../../puppet/util'
SEPARATOR = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join
Puppet::Reports.register_report(:store) do
desc "Store the yaml report on disk. Each host sends its report as a YAML dump
and this just stores the file on disk, in the `reportdir` directory.
These files collect quickly -- one every half hour -- so it is a good idea
to perform some maintenance on them if you use this report (it's the only
default report)."
def process
validate_host(host)
dir = File.join(Puppet[:reportdir], host)
if ! Puppet::FileSystem.exist?(dir)
FileUtils.mkdir_p(dir)
FileUtils.chmod_R(0750, dir)
end
# Now store the report.
now = Time.now.gmtime
name = %w{year month day hour min}.collect do |method|
# Make sure we're at least two digits everywhere
"%02d" % now.send(method).to_s
end.join("") + ".yaml"
file = File.join(dir, name)
begin
Puppet::FileSystem.replace_file(file, 0640) do |fh|
fh.print to_yaml
end
rescue => detail
Puppet.log_exception(detail, "Could not write report for #{host} at #{file}: #{detail}")
end
# Only testing cares about the return value
file
end
# removes all reports for a given host?
def self.destroy(host)
validate_host(host)
dir = File.join(Puppet[:reportdir], host)
if Puppet::FileSystem.exist?(dir)
Dir.entries(dir).each do |file|
next if ['.','..'].include?(file)
file = File.join(dir, file)
Puppet::FileSystem.unlink(file) if File.file?(file)
end
Dir.rmdir(dir)
end
end
def validate_host(host)
if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/)
raise ArgumentError, _("Invalid node name %{host}") % { host: host.inspect }
end
end
module_function :validate_host
end
puppet-8.4.0/lib/puppet/reports/http.rb 0000644 0052762 0001160 00000003322 14552052437 020024 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet'
require_relative '../../puppet/network/http_pool'
require 'uri'
Puppet::Reports.register_report(:http) do
desc <<-DESC
Send reports via HTTP or HTTPS. This report processor submits reports as
POST requests to the address in the `reporturl` setting. When a HTTPS URL
is used, the remote server must present a certificate issued by the Puppet
CA or the connection will fail validation. The body of each POST request
is the YAML dump of a Puppet::Transaction::Report object, and the
Content-Type is set as `application/x-yaml`.
DESC
def process
url = URI.parse(Puppet[:reporturl])
headers = { "Content-Type" => "application/x-yaml" }
# This metric_id option is silently ignored by Puppet's http client
# (Puppet::Network::HTTP) but is used by Puppet Server's http client
# (Puppet::Server::HttpClient) to track metrics on the request made to the
# `reporturl` to store a report.
options = {
:metric_id => [:puppet, :report, :http],
:include_system_store => Puppet[:report_include_system_store],
}
# Puppet's http client implementation accepts userinfo in the URL
# but puppetserver's does not. So pass credentials explicitly.
if url.user && url.password
options[:basic_auth] = {
user: url.user,
password: url.password
}
end
client = Puppet.runtime[:http]
client.post(url, self.to_yaml, headers: headers, options: options) do |response|
unless response.success?
Puppet.err _("Unable to submit report to %{url} [%{code}] %{message}") % { url: Puppet[:reporturl].to_s, code: response.code, message: response.reason }
end
end
end
end
puppet-8.4.0/lib/puppet/reports/log.rb 0000644 0052762 0001160 00000000564 14552052437 017633 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/reports'
Puppet::Reports.register_report(:log) do
desc "Send all received logs to the local log destinations. Usually
the log destination is syslog."
def process
self.logs.each do |log|
log.source = "//#{self.host}/#{log.source}"
Puppet::Util::Log.newmessage(log)
end
end
end
puppet-8.4.0/lib/puppet/vendor/ 0000755 0052762 0001160 00000000000 14552052637 016321 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/vendor/require_vendored.rb 0000644 0052762 0001160 00000000324 14552052437 022205 0 ustar jenkins jenkins # This adds upfront requirements on vendored code found under lib/vendor/x
# Add one requirement per vendored package (or a comment if it is loaded on demand).
# The vendored library 'rgen' is loaded on demand.
puppet-8.4.0/lib/puppet/module/ 0000755 0052762 0001160 00000000000 14552052637 016311 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/module/plan.rb 0000644 0052762 0001160 00000012052 14552052437 017566 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/util/logging'
class Puppet::Module
class Plan
class Error < Puppet::Error
attr_accessor :kind, :details
def initialize(message, kind, details = nil)
super(message)
@details = details || {}
@kind = kind
end
def to_h
{
msg: message,
kind: kind,
details: details
}
end
end
class InvalidName < Error
def initialize(name, msg)
super(msg, 'puppet.plans/invalid-name')
end
end
class InvalidFile < Error
def initialize(msg)
super(msg, 'puppet.plans/invalid-file')
end
end
class InvalidPlan < Error
end
class InvalidMetadata < Error
end
class PlanNotFound < Error
def initialize(plan_name, module_name)
msg = _("Plan %{plan_name} not found in module %{module_name}.") %
{plan_name: plan_name, module_name: module_name}
super(msg, 'puppet.plans/plan-not-found', { 'name' => plan_name })
end
end
ALLOWED_EXTENSIONS = %w{.pp .yaml}
RESERVED_WORDS = %w{and application attr case class consumes default else
elsif environment false function if import in inherits node or private
produces site true type undef unless}
RESERVED_DATA_TYPES = %w{any array boolean catalogentry class collection
callable data default enum float hash integer numeric optional pattern
resource runtime scalar string struct tuple type undef variant}
def self.is_plan_name?(name)
return true if name =~ /^[a-z][a-z0-9_]*$/
return false
end
# Determine whether a plan file has a legal name and extension
def self.is_plans_filename?(path)
name = File.basename(path, '.*')
ext = File.extname(path)
return [false, _("Plan names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")] unless is_plan_name?(name)
unless ALLOWED_EXTENSIONS.include? ext
return [false, _("Plan name cannot have extension %{ext}, must be .pp or .yaml") % { ext: ext }]
end
if RESERVED_WORDS.include?(name)
return [false, _("Plan name cannot be a reserved word, but was '%{name}'") % { name: name }]
end
if RESERVED_DATA_TYPES.include?(name)
return [false, _("Plan name cannot be a Puppet data type, but was '%{name}'") % { name: name }]
end
return [true]
end
# Executables list should contain the full path of all possible implementation files
def self.find_implementations(name, plan_files)
basename = name.split('::')[1] || 'init'
# If implementations isn't defined, then we use executables matching the
# plan name, and only one may exist.
implementations = plan_files.select { |impl| File.basename(impl, '.*') == basename }
# Select .pp before .yaml, since .pp comes before .yaml alphabetically.
chosen = implementations.sort.first
[{ "name" => File.basename(chosen), "path" => chosen }]
end
private_class_method :find_implementations
def self.find_files(name, plan_files)
find_implementations(name, plan_files)
end
def self.plans_in_module(pup_module)
# Search e.g. 'modules//plans' for all plans
plan_files = Dir.glob(File.join(pup_module.plans_directory, '*'))
.keep_if { |f| valid, _ = is_plans_filename?(f); valid }
plans = plan_files.group_by { |f| plan_name_from_path(f) }
plans.map do |plan, plan_filenames|
new_with_files(pup_module, plan, plan_filenames)
end
end
attr_reader :name, :module, :metadata_file
# file paths must be relative to the modules plan directory
def initialize(pup_module, plan_name, plan_files)
valid, reason = Puppet::Module::Plan.is_plans_filename?(plan_files.first)
unless valid
raise InvalidName.new(plan_name, reason)
end
name = plan_name == "init" ? pup_module.name : "#{pup_module.name}::#{plan_name}"
@module = pup_module
@name = name
@metadata_file = metadata_file
@plan_files = plan_files || []
end
def metadata
# Nothing to go here unless plans eventually support metadata.
@metadata ||= {}
end
def files
@files ||= self.class.find_files(@name, @plan_files)
end
def validate
files
true
end
def ==(other)
self.name == other.name &&
self.module == other.module
end
def environment_name
@module.environment.respond_to?(:name) ? @module.environment.name : 'production'
end
private :environment_name
def self.new_with_files(pup_module, name, plan_files)
Puppet::Module::Plan.new(pup_module, name, plan_files)
end
private_class_method :new_with_files
# Abstracted here so we can add support for subdirectories later
def self.plan_name_from_path(path)
return File.basename(path, '.*')
end
private_class_method :plan_name_from_path
end
end
puppet-8.4.0/lib/puppet/module/task.rb 0000644 0052762 0001160 00000025344 14552052437 017606 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/util/logging'
class Puppet::Module
class Task
class Error < Puppet::Error
attr_accessor :kind, :details
def initialize(message, kind, details = nil)
super(message)
@details = details || {}
@kind = kind
end
def to_h
{
msg: message,
kind: kind,
details: details
}
end
end
class InvalidName < Error
def initialize(name)
msg = _("Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
super(msg, 'puppet.tasks/invalid-name')
end
end
class InvalidFile < Error
def initialize(msg)
super(msg, 'puppet.tasks/invalid-file')
end
end
class InvalidTask < Error
end
class InvalidMetadata < Error
end
class TaskNotFound < Error
def initialize(task_name, module_name)
msg = _("Task %{task_name} not found in module %{module_name}.") %
{task_name: task_name, module_name: module_name}
super(msg, 'puppet.tasks/task-not-found', { 'name' => task_name })
end
end
FORBIDDEN_EXTENSIONS = %w{.conf .md}
MOUNTS = %w[files lib scripts tasks]
def self.is_task_name?(name)
return true if name =~ /^[a-z][a-z0-9_]*$/
return false
end
def self.is_tasks_file?(path)
File.file?(path) && is_tasks_filename?(path)
end
# Determine whether a file has a legal name for either a task's executable or metadata file.
def self.is_tasks_filename?(path)
name_less_extension = File.basename(path, '.*')
return false if not is_task_name?(name_less_extension)
FORBIDDEN_EXTENSIONS.each do |ext|
return false if path.end_with?(ext)
end
return true
end
def self.get_file_details(path, mod)
# This gets the path from the starting point onward
# For files this should be the file subpath from the metadata
# For directories it should be the directory subpath plus whatever we globbed
# Partition matches on the first instance it finds of the parameter
name = "#{mod.name}#{path.partition(mod.path).last}"
{ "name" => name, "path" => path }
end
private_class_method :get_file_details
# Find task's required lib files and retrieve paths for both 'files' and 'implementation:files' metadata keys
def self.find_extra_files(metadata, envname = nil)
return [] if metadata.nil?
files = metadata.fetch('files', [])
unless files.is_a?(Array)
msg = _("The 'files' task metadata expects an array, got %{files}.") % {files: files}
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
impl_files = metadata.fetch('implementations', []).flat_map do |impl|
file_array = impl.fetch('files', [])
unless file_array.is_a?(Array)
msg = _("The 'files' task metadata expects an array, got %{files}.") % {files: file_array}
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
file_array
end
combined_files = files + impl_files
combined_files.uniq.flat_map do |file|
module_name, mount, endpath = file.split("/", 3)
# If there's a mount directory with no trailing slash this will be nil
# We want it to be empty to construct a path
endpath ||= ''
pup_module = Puppet::Module.find(module_name, envname)
if pup_module.nil?
msg = _("Could not find module %{module_name} containing task file %{filename}" %
{module_name: module_name, filename: endpath})
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
unless MOUNTS.include? mount
msg = _("Files must be saved in module directories that Puppet makes available via mount points: %{mounts}" %
{mounts: MOUNTS.join(', ')})
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
path = File.join(pup_module.path, mount, endpath)
unless File.absolute_path(path) == File.path(path).chomp('/')
msg = _("File pathnames cannot include relative paths")
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
unless File.exist?(path)
msg = _("Could not find %{path} on disk" % { path: path })
raise InvalidFile.new(msg)
end
last_char = file[-1] == '/'
if File.directory?(path)
unless last_char
msg = _("Directories specified in task metadata must include a trailing slash: %{dir}" % { dir: file } )
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
dir_files = Dir.glob("#{path}**/*").select { |f| File.file?(f) }
dir_files.map { |f| get_file_details(f, pup_module) }
else
if last_char
msg = _("Files specified in task metadata cannot include a trailing slash: %{file}" % { file: file } )
raise InvalidMetadata.new(msg, 'puppet.task/invalid-metadata')
end
get_file_details(path, pup_module)
end
end
end
private_class_method :find_extra_files
# Executables list should contain the full path of all possible implementation files
def self.find_implementations(name, directory, metadata, executables)
basename = name.split('::')[1] || 'init'
# If 'implementations' is defined, it needs to mention at least one
# implementation, and everything it mentions must exist.
metadata ||= {}
if metadata.key?('implementations')
unless metadata['implementations'].is_a?(Array)
msg = _("Task metadata for task %{name} does not specify implementations as an array" % { name: name })
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
implementations = metadata['implementations'].map do |impl|
unless impl['requirements'].is_a?(Array) || impl['requirements'].nil?
msg = _("Task metadata for task %{name} does not specify requirements as an array" % { name: name })
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
end
path = executables.find { |real_impl| File.basename(real_impl) == impl['name'] }
unless path
msg = _("Task metadata for task %{name} specifies missing implementation %{implementation}" % { name: name, implementation: impl['name'] })
raise InvalidTask.new(msg, 'puppet.tasks/missing-implementation', { missing: [impl['name']] } )
end
{ "name" => impl['name'], "path" => path }
end
return implementations
end
# If implementations isn't defined, then we use executables matching the
# task name, and only one may exist.
implementations = executables.select { |impl| File.basename(impl, '.*') == basename }
if implementations.empty?
msg = _('No source besides task metadata was found in directory %{directory} for task %{name}') %
{ name: name, directory: directory }
raise InvalidTask.new(msg, 'puppet.tasks/no-implementation')
elsif implementations.length > 1
msg =_("Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them") %
{ name: name, directory: implementations[0] }
raise InvalidTask.new(msg, 'puppet.tasks/multiple-implementations')
end
[{ "name" => File.basename(implementations.first), "path" => implementations.first }]
end
private_class_method :find_implementations
def self.find_files(name, directory, metadata, executables, envname = nil)
# PXP agent relies on 'impls' (which is the task file) being first if there is no metadata
find_implementations(name, directory, metadata, executables) + find_extra_files(metadata, envname)
end
def self.is_tasks_metadata_filename?(name)
is_tasks_filename?(name) && name.end_with?('.json')
end
def self.is_tasks_executable_filename?(name)
is_tasks_filename?(name) && !name.end_with?('.json')
end
def self.tasks_in_module(pup_module)
task_files = Dir.glob(File.join(pup_module.tasks_directory, '*'))
.keep_if { |f| is_tasks_file?(f) }
module_executables = task_files.reject(&method(:is_tasks_metadata_filename?)).map.to_a
tasks = task_files.group_by { |f| task_name_from_path(f) }
tasks.map do |task, executables|
new_with_files(pup_module, task, executables, module_executables)
end
end
attr_reader :name, :module, :metadata_file
# file paths must be relative to the modules task directory
def initialize(pup_module, task_name, module_executables, metadata_file = nil)
if !Puppet::Module::Task.is_task_name?(task_name)
raise InvalidName, _("Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
end
name = task_name == "init" ? pup_module.name : "#{pup_module.name}::#{task_name}"
@module = pup_module
@name = name
@metadata_file = metadata_file
@module_executables = module_executables || []
end
def self.read_metadata(file)
if file
content = Puppet::FileSystem.read(file, :encoding => 'utf-8')
content.empty? ? {} : Puppet::Util::Json.load(content)
end
rescue SystemCallError, IOError => err
msg = _("Error reading metadata: %{message}" % {message: err.message})
raise InvalidMetadata.new(msg, 'puppet.tasks/unreadable-metadata')
rescue Puppet::Util::Json::ParseError => err
raise InvalidMetadata.new(err.message, 'puppet.tasks/unparseable-metadata')
end
def metadata
@metadata ||= self.class.read_metadata(@metadata_file)
end
def files
@files ||= self.class.find_files(@name, @module.tasks_directory, metadata, @module_executables, environment_name)
end
def validate
files
true
end
def ==(other)
self.name == other.name &&
self.module == other.module
end
def environment_name
@module.environment.respond_to?(:name) ? @module.environment.name : 'production'
end
private :environment_name
def self.new_with_files(pup_module, name, task_files, module_executables)
metadata_file = task_files.find { |f| is_tasks_metadata_filename?(f) }
Puppet::Module::Task.new(pup_module, name, module_executables, metadata_file)
end
private_class_method :new_with_files
# Abstracted here so we can add support for subdirectories later
def self.task_name_from_path(path)
return File.basename(path, '.*')
end
private_class_method :task_name_from_path
end
end
puppet-8.4.0/lib/puppet/scheduler/ 0000755 0052762 0001160 00000000000 14552052637 017002 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/scheduler/splay_job.rb 0000644 0052762 0001160 00000001104 14552052437 021303 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet::Scheduler
class SplayJob < Job
attr_reader :splay
def initialize(run_interval, splay_limit, &block)
@splay = calculate_splay(splay_limit)
super(run_interval, &block)
end
def interval_to_next_from(time)
if last_run
super
else
(start_time + splay) - time
end
end
def ready?(time)
if last_run
super
else
start_time + splay <= time
end
end
private
def calculate_splay(limit)
rand(limit + 1)
end
end
end
puppet-8.4.0/lib/puppet/scheduler/timer.rb 0000644 0052762 0001160 00000000314 14552052437 020443 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet::Scheduler
class Timer
def wait_for(seconds)
if seconds > 0
sleep(seconds)
end
end
def now
Time.now
end
end
end
puppet-8.4.0/lib/puppet/scheduler/scheduler.rb 0000644 0052762 0001160 00000002062 14552052437 021303 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet::Scheduler
class Scheduler
def initialize(timer=Puppet::Scheduler::Timer.new)
@timer = timer
end
def run_loop(jobs)
mark_start_times(jobs, @timer.now)
while not enabled(jobs).empty?
@timer.wait_for(min_interval_to_next_run_from(jobs, @timer.now))
run_ready(jobs, @timer.now)
end
end
private
def enabled(jobs)
jobs.select(&:enabled?)
end
def mark_start_times(jobs, start_time)
jobs.each do |job|
job.start_time = start_time
end
end
def min_interval_to_next_run_from(jobs, from_time)
enabled(jobs).map do |j|
j.interval_to_next_from(from_time)
end.min
end
def run_ready(jobs, at_time)
enabled(jobs).each do |j|
# This check intentionally happens right before each run,
# instead of filtering on ready schedulers, since one may adjust
# the readiness of a later one
if j.ready?(at_time)
j.run(at_time)
end
end
end
end
end
puppet-8.4.0/lib/puppet/scheduler/job.rb 0000644 0052762 0001160 00000001617 14552052437 020104 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet::Scheduler
class Job
attr_reader :run_interval
attr_accessor :last_run
attr_accessor :start_time
def initialize(run_interval, &block)
self.run_interval = run_interval
@last_run = nil
@run_proc = block
@enabled = true
end
def run_interval=(interval)
@run_interval = [interval, 0].max
end
def ready?(time)
if @last_run
@last_run + @run_interval <= time
else
true
end
end
def enabled?
@enabled
end
def enable
@enabled = true
end
def disable
@enabled = false
end
def interval_to_next_from(time)
if ready?(time)
0
else
@run_interval - (time - @last_run)
end
end
def run(now)
@last_run = now
if @run_proc
@run_proc.call(self)
end
end
end
end
puppet-8.4.0/lib/puppet/parser/ 0000755 0052762 0001160 00000000000 14552052637 016320 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/parser/files.rb 0000644 0052762 0001160 00000006145 14552052437 017753 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet::Parser::Files
module_function
# Return a list of manifests as absolute filenames matching the given
# pattern.
#
# @param pattern [String] A reference for a file in a module. It is the
# format "/"
# @param environment [Puppet::Node::Environment] the environment of modules
#
# @return [Array(String, Array)] the module name and the list of files found
# @api private
def find_manifests_in_modules(pattern, environment)
module_name, file_pattern = split_file_path(pattern)
mod = environment.module(module_name)
if mod
[mod.name, mod.match_manifests(file_pattern)]
else
[nil, []]
end
end
# Find the path to the given file selector. Files can be selected in
# one of two ways:
# * absolute path: the path is simply returned
# * modulename/filename selector: a file is found in the file directory
# of the named module.
#
# The check for file existence is performed on the node compiling the
# manifest. A node running "puppet apply" compiles its own manifest, but
# a node running "puppet agent" depends on the configured puppetserver
# for compiling. In either case, a nil is returned if no file is found.
#
# @param template [String] the file selector
# @param environment [Puppet::Node::Environment] the environment in which to search
# @return [String, nil] the absolute path to the file or nil if there is no file found
#
# @api private
def find_file(file, environment)
find_in_module(file, environment) do |mod,module_file|
mod.file(module_file)
end
end
# Find the path to the given template selector. Templates can be selected in
# a couple of ways:
# * absolute path: the path is simply returned
# * modulename/filename selector: a file is found in the template directory
# of the named module.
#
# In the last two cases a nil is returned if there isn't a file found. In the
# first case (absolute path), there is no existence check done and so the
# path will be returned even if there isn't a file available.
#
# @param template [String] the template selector
# @param environment [Puppet::Node::Environment] the environment in which to search
# @return [String, nil] the absolute path to the template file or nil if there is no file found
#
# @api private
def find_template(template, environment)
find_in_module(template, environment) do |mod,template_file|
mod.template(template_file)
end
end
# @api private
def find_in_module(reference, environment)
if Puppet::Util.absolute_path?(reference)
reference
else
path, file = split_file_path(reference)
mod = environment.module(path)
if file && mod
yield(mod, file)
else
nil
end
end
end
# Split the path into the module and the rest of the path, or return
# nil if the path is empty or absolute (starts with a /).
# @api private
def split_file_path(path)
if path == "" || Puppet::Util.absolute_path?(path)
nil
else
path.split(File::SEPARATOR, 2)
end
end
end
puppet-8.4.0/lib/puppet/parser/parser_factory.rb 0000644 0052762 0001160 00000001567 14552052437 021677 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet; end
module Puppet::Parser
# The ParserFactory makes selection of parser possible.
# Currently, it is possible to switch between two different parsers:
# * classic_parser, the parser in 3.1
# * eparser, the Expression Based Parser
#
class ParserFactory
# Produces a parser instance for the given environment
def self.parser
evaluating_parser
end
# Creates an instance of an E4ParserAdapter that adapts an
# EvaluatingParser to the 3x way of parsing.
#
def self.evaluating_parser
unless defined?(Puppet::Parser::E4ParserAdapter)
require_relative '../../puppet/parser/e4_parser_adapter'
require_relative '../../puppet/pops/parser/code_merger'
end
E4ParserAdapter.new
end
def self.code_merger
Puppet::Pops::Parser::CodeMerger.new
end
end
end
puppet-8.4.0/lib/puppet/parser/templatewrapper.rb 0000644 0052762 0001160 00000005506 14552052437 022065 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/parser/files'
require 'erb'
require_relative '../../puppet/file_system'
# A simple wrapper for templates, so they don't have full access to
# the scope objects.
#
# @api private
class Puppet::Parser::TemplateWrapper
include Puppet::Util
Puppet::Util.logmethods(self)
def initialize(scope)
@__scope__ = scope
end
# @return [String] The full path name of the template that is being executed
# @api public
def file
@__file__
end
# @return [Puppet::Parser::Scope] The scope in which the template is evaluated
# @api public
def scope
@__scope__
end
# Find which line in the template (if any) we were called from.
# @return [String] the line number
# @api private
def script_line
identifier = Regexp.escape(@__file__ || "(erb)")
(caller.find { |l| l =~ /#{identifier}:/ }||"")[/:(\d+):/,1]
end
private :script_line
# Should return true if a variable is defined, false if it is not
# @api public
def has_variable?(name)
scope.include?(name.to_s)
end
# @return [Array] The list of defined classes
# @api public
def classes
scope.catalog.classes
end
# @return [Array] The tags defined in the current scope
# @api public
def tags
raise NotImplementedError, "Call 'all_tags' instead."
end
# @return [Array] All the defined tags
# @api public
def all_tags
scope.catalog.tags
end
# @api private
def file=(filename)
@__file__ = Puppet::Parser::Files.find_template(filename, scope.compiler.environment)
unless @__file__
raise Puppet::ParseError, _("Could not find template '%{filename}'") % { filename: filename }
end
end
# @api private
def result(string = nil)
if string
template_source = "inline template"
else
string = Puppet::FileSystem.read_preserve_line_endings(@__file__)
template_source = @__file__
end
# Expose all the variables in our scope as instance variables of the
# current object, making it possible to access them without conflict
# to the regular methods.
escaped_template_source = template_source.gsub(/%/, '%%')
benchmark(:debug, _("Bound template variables for %{template_source} in %%{seconds} seconds") % { template_source: escaped_template_source }) do
scope.to_hash.each do |name, value|
realname = name.gsub(/[^\w]/, "_")
instance_variable_set("@#{realname}", value)
end
end
result = nil
benchmark(:debug, _("Interpolated template %{template_source} in %%{seconds} seconds") % { template_source: escaped_template_source }) do
template = Puppet::Util.create_erb(string)
template.filename = @__file__
result = template.result(binding)
end
result
end
def to_s
"template[#{(@__file__ ? @__file__ : "inline")}]"
end
end
puppet-8.4.0/lib/puppet/parser/e4_parser_adapter.rb 0000644 0052762 0001160 00000002722 14552052437 022232 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/pops'
module Puppet
module Parser
# Adapts an egrammar/eparser to respond to the public API of the classic parser
# and makes use of the new evaluator.
#
class E4ParserAdapter
def initialize
@file = ''
@string = ''
@use = :unspecified
end
def file=(file)
@file = file
@use = :file
end
def parse(string = nil)
self.string= string if string
parser = Pops::Parser::EvaluatingParser.singleton
model =
if @use == :string
# Parse with a source_file to set in created AST objects (it was either given, or it may be unknown
# if caller did not set a file and the present a string.
#
parser.parse_string(@string, @file || "unknown-source-location")
else
parser.parse_file(@file)
end
# the parse_result may be
# * empty / nil (no input)
# * a Model::Program
# * a Model::Expression
#
args = {}
Pops::Model::AstTransformer.new(@file).merge_location(args, model)
ast_code =
if model.is_a? Pops::Model::Program
AST::PopsBridge::Program.new(model, args)
else
args[:value] = model
AST::PopsBridge::Expression.new(args)
end
# Create the "main" class for the content - this content will get merged with all other "main" content
AST::Hostclass.new('', :code => ast_code)
end
def string=(string)
@string = string
@use = :string
end
end
end
end
puppet-8.4.0/lib/puppet/parser/resource/ 0000755 0052762 0001160 00000000000 14552052637 020147 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/parser/resource/param.rb 0000644 0052762 0001160 00000001533 14552052437 021574 0 ustar jenkins jenkins # frozen_string_literal: true
# The parameters we stick in Resources.
class Puppet::Parser::Resource::Param
include Puppet::Util
include Puppet::Util::Errors
attr_accessor :name, :value, :source, :add, :file, :line
def initialize(name: nil, value: nil, source: nil, line: nil, file: nil, add: nil)
@value = value
@source = source
@line = line
@file = file
@add = add
unless name
# This must happen after file and line are set to have them reported in the error
self.fail(Puppet::ResourceError, "'name' is a required option for #{self.class}")
end
@name = name.intern
end
def line_to_i
line ? Integer(line) : nil
end
def to_s
"#{self.name} => #{self.value}"
end
def self.from_param(param, value)
new_param = param.dup
new_param.value = value
return new_param
end
end
puppet-8.4.0/lib/puppet/parser/compiler.rb 0000644 0052762 0001160 00000051274 14552052437 020466 0 ustar jenkins jenkins # frozen_string_literal: true
require 'forwardable'
require_relative '../../puppet/node'
require_relative '../../puppet/resource/catalog'
require_relative '../../puppet/util/errors'
require_relative '../../puppet/loaders'
require_relative '../../puppet/pops'
# Maintain a graph of scopes, along with a bunch of data
# about the individual catalog we're compiling.
class Puppet::Parser::Compiler
include Puppet::Parser::AbstractCompiler
extend Forwardable
include Puppet::Util
include Puppet::Util::Errors
include Puppet::Pops::Evaluator::Runtime3Support
def self.compile(node, code_id = nil)
node.environment.check_for_reparse
errors = node.environment.validation_errors
if !errors.empty?
errors.each { |e| Puppet.err(e) } if errors.size > 1
errmsg = [
_("Compilation has been halted because: %{error}") % { error: errors.first },
_("For more information, see https://puppet.com/docs/puppet/latest/environments_about.html"),
]
raise(Puppet::Error, errmsg.join(' '))
end
new(node, :code_id => code_id).compile {|resulting_catalog| resulting_catalog.to_resource }
rescue Puppet::ParseErrorWithIssue => detail
detail.node = node.name
Puppet.log_exception(detail)
raise
rescue => detail
message = _("%{message} on node %{node}") % { message: detail, node: node.name }
Puppet.log_exception(detail, message)
raise Puppet::Error, message, detail.backtrace
end
attr_reader :node, :facts, :collections, :catalog, :resources, :relationships, :topscope
attr_reader :qualified_variables
# Access to the configured loaders for 4x
# @return [Puppet::Pops::Loader::Loaders] the configured loaders
# @api private
attr_reader :loaders
# The id of code input to the compiler.
# @api private
attr_accessor :code_id
# Add a collection to the global list.
def_delegator :@collections, :<<, :add_collection
def_delegator :@relationships, :<<, :add_relationship
# Store a resource override.
def add_override(override)
# If possible, merge the override in immediately.
resource = @catalog.resource(override.ref)
if resource
resource.merge(override)
else
# Otherwise, store the override for later; these
# get evaluated in Resource#finish.
@resource_overrides[override.ref] << override
end
end
def add_resource(scope, resource)
@resources << resource
# Note that this will fail if the resource is not unique.
@catalog.add_resource(resource)
if not resource.class? and resource[:stage]
# TRANSLATORS "stage" is a keyword in Puppet and should not be translated
raise ArgumentError, _("Only classes can set 'stage'; normal resources like %{resource} cannot change run stage") % { resource: resource }
end
# Stages should not be inside of classes. They are always a
# top-level container, regardless of where they appear in the
# manifest.
return if resource.stage?
# This adds a resource to the class it lexically appears in in the
# manifest.
unless resource.class?
@catalog.add_edge(scope.resource, resource)
end
end
# Store the fact that we've evaluated a class
def add_class(name)
@catalog.add_class(name) unless name == ""
end
# Add a catalog validator that will run at some stage to this compiler
# @param catalog_validators [Class] The catalog validator class to add
def add_catalog_validator(catalog_validators)
@catalog_validators << catalog_validators
nil
end
def add_catalog_validators
add_catalog_validator(CatalogValidator::RelationshipValidator)
end
# Return a list of all of the defined classes.
def_delegator :@catalog, :classes, :classlist
def with_context_overrides(description = '', &block)
Puppet.override( @context_overrides , description, &block)
end
# Compiler our catalog. This mostly revolves around finding and evaluating classes.
# This is the main entry into our catalog.
def compile
Puppet.override( @context_overrides , _("For compiling %{node}") % { node: node.name }) do
@catalog.environment_instance = environment
# Set the client's parameters into the top scope.
Puppet::Util::Profiler.profile(_("Compile: Set node parameters"), [:compiler, :set_node_params]) { set_node_parameters }
Puppet::Util::Profiler.profile(_("Compile: Created settings scope"), [:compiler, :create_settings_scope]) { create_settings_scope }
# TRANSLATORS "main" is a function name and should not be translated
Puppet::Util::Profiler.profile(_("Compile: Evaluated main"), [:compiler, :evaluate_main]) { evaluate_main }
Puppet::Util::Profiler.profile(_("Compile: Evaluated AST node"), [:compiler, :evaluate_ast_node]) { evaluate_ast_node }
Puppet::Util::Profiler.profile(_("Compile: Evaluated node classes"), [:compiler, :evaluate_node_classes]) { evaluate_node_classes }
Puppet::Util::Profiler.profile(_("Compile: Evaluated generators"), [:compiler, :evaluate_generators]) { evaluate_generators }
Puppet::Util::Profiler.profile(_("Compile: Validate Catalog pre-finish"), [:compiler, :validate_pre_finish]) do
validate_catalog(CatalogValidator::PRE_FINISH)
end
Puppet::Util::Profiler.profile(_("Compile: Finished catalog"), [:compiler, :finish_catalog]) { finish }
fail_on_unevaluated
Puppet::Util::Profiler.profile(_("Compile: Validate Catalog final"), [:compiler, :validate_final]) do
validate_catalog(CatalogValidator::FINAL)
end
if block_given?
yield @catalog
else
@catalog
end
end
end
def validate_catalog(validation_stage)
@catalog_validators.select { |vclass| vclass.validation_stage?(validation_stage) }.each { |vclass| vclass.new(@catalog).validate }
end
# Constructs the overrides for the context
def context_overrides()
{
:current_environment => environment,
:global_scope => @topscope, # 4x placeholder for new global scope
:loaders => @loaders, # 4x loaders
}
end
def_delegator :@collections, :delete, :delete_collection
# Return the node's environment.
def environment
node.environment
end
# Evaluate all of the classes specified by the node.
# Classes with parameters are evaluated as if they were declared.
# Classes without parameters or with an empty set of parameters are evaluated
# as if they were included. This means classes with an empty set of
# parameters won't conflict even if the class has already been included.
def evaluate_node_classes
if @node.classes.is_a? Hash
classes_with_params, classes_without_params = @node.classes.partition {|_name,params| params and !params.empty?}
# The results from Hash#partition are arrays of pairs rather than hashes,
# so we have to convert to the forms evaluate_classes expects (Hash, and
# Array of class names)
classes_with_params = Hash[classes_with_params]
classes_without_params.map!(&:first)
else
classes_with_params = {}
classes_without_params = @node.classes
end
evaluate_classes(classes_with_params, @node_scope || topscope)
evaluate_classes(classes_without_params, @node_scope || topscope)
end
# If ast nodes are enabled, then see if we can find and evaluate one.
#
# @api private
def evaluate_ast_node
krt = environment.known_resource_types
return unless krt.nodes? # ast_nodes?
# Now see if we can find the node.
astnode = nil
@node.names.each do |name|
astnode = krt.node(name.to_s.downcase)
break if astnode
end
unless (astnode ||= krt.node("default"))
raise Puppet::ParseError, _("Could not find node statement with name 'default' or '%{names}'") % { names: node.names.join(", ") }
end
# Create a resource to model this node, and then add it to the list
# of resources.
resource = astnode.ensure_in_catalog(topscope)
resource.evaluate
@node_scope = topscope.class_scope(astnode)
end
# Evaluates each specified class in turn. If there are any classes that
# can't be found, an error is raised. This method really just creates resource objects
# that point back to the classes, and then the resources are themselves
# evaluated later in the process.
#
def evaluate_classes(classes, scope, lazy_evaluate = true)
raise Puppet::DevError, _("No source for scope passed to evaluate_classes") unless scope.source
class_parameters = nil
# if we are a param class, save the classes hash
# and transform classes to be the keys
if classes.class == Hash
class_parameters = classes
classes = classes.keys
end
hostclasses = classes.collect do |name|
environment.known_resource_types.find_hostclass(name) or raise Puppet::Error, _("Could not find class %{name} for %{node}") % { name: name, node: node.name }
end
if class_parameters
resources = ensure_classes_with_parameters(scope, hostclasses, class_parameters)
if !lazy_evaluate
resources.each(&:evaluate)
end
resources
else
already_included, newly_included = ensure_classes_without_parameters(scope, hostclasses)
if !lazy_evaluate
newly_included.each(&:evaluate)
end
already_included + newly_included
end
end
def evaluate_relationships
@relationships.each { |rel| rel.evaluate(catalog) }
end
# Return a resource by either its ref or its type and title.
def_delegator :@catalog, :resource, :findresource
def initialize(node, code_id: nil)
@node = sanitize_node(node)
@code_id = code_id
initvars
add_catalog_validators
# Resolutions of fully qualified variable names
@qualified_variables = {}
end
# Create a new scope, with either a specified parent scope or
# using the top scope.
def newscope(parent, options = {})
parent ||= topscope
scope = Puppet::Parser::Scope.new(self, **options)
scope.parent = parent
scope
end
# Return any overrides for the given resource.
def resource_overrides(resource)
@resource_overrides[resource.ref]
end
private
def ensure_classes_with_parameters(scope, hostclasses, parameters)
hostclasses.collect do |klass|
klass.ensure_in_catalog(scope, parameters[klass.name] || {})
end
end
def ensure_classes_without_parameters(scope, hostclasses)
already_included = []
newly_included = []
hostclasses.each do |klass|
class_scope = scope.class_scope(klass)
if class_scope
already_included << class_scope.resource
else
newly_included << klass.ensure_in_catalog(scope)
end
end
[already_included, newly_included]
end
# Evaluate our collections and return true if anything returned an object.
# The 'true' is used to continue a loop, so it's important.
def evaluate_collections
return false if @collections.empty?
exceptwrap do
# We have to iterate over a dup of the array because
# collections can delete themselves from the list, which
# changes its length and causes some collections to get missed.
Puppet::Util::Profiler.profile(_("Evaluated collections"), [:compiler, :evaluate_collections]) do
found_something = false
@collections.dup.each do |collection|
found_something = true if collection.evaluate
end
found_something
end
end
end
# Make sure all of our resources have been evaluated into native resources.
# We return true if any resources have, so that we know to continue the
# evaluate_generators loop.
def evaluate_definitions
exceptwrap do
Puppet::Util::Profiler.profile(_("Evaluated definitions"), [:compiler, :evaluate_definitions]) do
urs = unevaluated_resources.each do |resource|
begin
resource.evaluate
rescue Puppet::Pops::Evaluator::PuppetStopIteration => detail
# needs to be handled specifically as the error has the file/line/position where this
# occurred rather than the resource
fail(Puppet::Pops::Issues::RUNTIME_ERROR, detail, {:detail => detail.message}, detail)
rescue Puppet::Error => e
# PuppetError has the ability to wrap an exception, if so, use the wrapped exception's
# call stack instead
fail(Puppet::Pops::Issues::RUNTIME_ERROR, resource, {:detail => e.message}, e.original || e)
end
end
!urs.empty?
end
end
end
# Iterate over collections and resources until we're sure that the whole
# compile is evaluated. This is necessary because both collections
# and defined resources can generate new resources, which themselves could
# be defined resources.
def evaluate_generators
count = 0
loop do
done = true
Puppet::Util::Profiler.profile(_("Iterated (%{count}) on generators") % { count: count + 1 }, [:compiler, :iterate_on_generators]) do
# Call collections first, then definitions.
done = false if evaluate_collections
done = false if evaluate_definitions
end
break if done
count += 1
if count > 1000
raise Puppet::ParseError, _("Somehow looped more than 1000 times while evaluating host catalog")
end
end
end
protected :evaluate_generators
# Find and evaluate our main object, if possible.
def evaluate_main
krt = environment.known_resource_types
@main = krt.find_hostclass('') || krt.add(Puppet::Resource::Type.new(:hostclass, ''))
@topscope.source = @main
@main_resource = Puppet::Parser::Resource.new('class', :main, :scope => @topscope, :source => @main)
@topscope.resource = @main_resource
add_resource(@topscope, @main_resource)
@main_resource.evaluate
end
# Make sure the entire catalog is evaluated.
def fail_on_unevaluated
fail_on_unevaluated_overrides
fail_on_unevaluated_resource_collections
end
# If there are any resource overrides remaining, then we could
# not find the resource they were supposed to override, so we
# want to throw an exception.
def fail_on_unevaluated_overrides
remaining = @resource_overrides.values.flatten.collect(&:ref)
if !remaining.empty?
raise Puppet::ParseError, _("Could not find resource(s) %{resources} for overriding") % { resources: remaining.join(', ') }
end
end
# Make sure there are no remaining collections that are waiting for
# resources that have not yet been instantiated. If this occurs it
# is an error (missing resource - it could not be realized).
#
def fail_on_unevaluated_resource_collections
remaining = @collections.collect(&:unresolved_resources).flatten.compact
if !remaining.empty?
raise Puppet::ParseError, _("Failed to realize virtual resources %{resources}") % { resources: remaining.join(', ') }
end
end
# Make sure all of our resources and such have done any last work
# necessary.
def finish
evaluate_relationships
resources.each do |resource|
# Add in any resource overrides.
overrides = resource_overrides(resource)
if overrides
overrides.each do |over|
resource.merge(over)
end
# Remove the overrides, so that the configuration knows there
# are none left.
overrides.clear
end
resource.finish if resource.respond_to?(:finish)
end
add_resource_metaparams
end
protected :finish
def add_resource_metaparams
main = catalog.resource(:class, :main)
unless main
# TRANSLATORS "main" is a function name and should not be translated
raise _("Couldn't find main")
end
names = Puppet::Type.metaparams.select do |name|
!Puppet::Parser::Resource.relationship_parameter?(name)
end
data = {}
catalog.walk(main, :out) do |source, target|
source_data = data[source] || metaparams_as_data(source, names)
if source_data
# only store anything in the data hash if we've actually got
# data
data[source] ||= source_data
source_data.each do |param, value|
target[param] = value if target[param].nil?
end
data[target] = source_data.merge(metaparams_as_data(target, names))
end
target.merge_tags_from(source)
end
end
def metaparams_as_data(resource, params)
data = nil
params.each do |param|
unless resource[param].nil?
# Because we could be creating a hash for every resource,
# and we actually probably don't often have any data here at all,
# we're optimizing a bit by only creating a hash if there's
# any data to put in it.
data ||= {}
data[param] = resource[param]
end
end
data
end
# Set up all of our internal variables.
def initvars
# The list of overrides. This is used to cache overrides on objects
# that don't exist yet. We store an array of each override.
@resource_overrides = Hash.new do |overs, ref|
overs[ref] = []
end
# The list of collections that have been created. This is a global list,
# but they each refer back to the scope that created them.
@collections = []
# The list of relationships to evaluate.
@relationships = []
# For maintaining the relationship between scopes and their resources.
@catalog = Puppet::Resource::Catalog.new(@node.name, @node.environment, @code_id)
# MOVED HERE - SCOPE IS NEEDED (MOVE-SCOPE)
# Create the initial scope, it is needed early
@topscope = Puppet::Parser::Scope.new(self)
# Initialize loaders and Pcore
@loaders = Puppet::Pops::Loaders.new(environment)
# Need to compute overrides here, and remember them, because we are about to
# enter the magic zone of known_resource_types and initial import.
# Expensive entries in the context are bound lazily.
@context_overrides = context_overrides()
# This construct ensures that initial import (triggered by instantiating
# the structure 'known_resource_types') has a configured context
# It cannot survive the initvars method, and is later reinstated
# as part of compiling...
#
Puppet.override( @context_overrides , _("For initializing compiler")) do
# THE MAGIC STARTS HERE ! This triggers parsing, loading etc.
@catalog.version = environment.known_resource_types.version
@loaders.pre_load
end
@catalog.add_resource(Puppet::Parser::Resource.new("stage", :main, :scope => @topscope))
# local resource array to maintain resource ordering
@resources = []
# Make sure any external node classes are in our class list
if @node.classes.class == Hash
@catalog.add_class(*@node.classes.keys)
else
@catalog.add_class(*@node.classes)
end
@catalog_validators = []
end
def sanitize_node(node)
node.sanitize
node
end
# Set the node's parameters into the top-scope as variables.
def set_node_parameters
node.parameters.each do |param, value|
# We don't want to set @topscope['environment'] from the parameters,
# instead we want to get that from the node's environment itself in
# case a custom node terminus has done any mucking about with
# node.parameters.
next if param.to_s == 'environment'
# Ensure node does not leak Symbol instances in general
@topscope[param.to_s] = value.is_a?(Symbol) ? value.to_s : value
end
@topscope['environment'] = node.environment.name.to_s
# These might be nil.
catalog.client_version = node.parameters["clientversion"]
catalog.server_version = node.parameters["serverversion"]
@topscope.set_trusted(node.trusted_data)
@topscope.set_server_facts(node.server_facts)
facts_hash = node.facts.nil? ? {} : node.facts.values
@topscope.set_facts(facts_hash)
end
SETTINGS = 'settings'
def create_settings_scope
settings_type = create_settings_type
settings_resource = Puppet::Parser::Resource.new('class', SETTINGS, :scope => @topscope)
@catalog.add_resource(settings_resource)
settings_type.evaluate_code(settings_resource)
settings_resource.instance_variable_set(:@evaluated, true) # Prevents settings from being reevaluated
scope = @topscope.class_scope(settings_type)
scope.merge_settings(environment.name)
end
def create_settings_type
environment.lock.synchronize do
resource_types = environment.known_resource_types
settings_type = resource_types.hostclass(SETTINGS)
if settings_type.nil?
settings_type = Puppet::Resource::Type.new(:hostclass, SETTINGS)
resource_types.add(settings_type)
end
settings_type
end
end
# Return an array of all of the unevaluated resources. These will be definitions,
# which need to get evaluated into native resources.
def unevaluated_resources
# The order of these is significant for speed due to short-circuiting
resources.reject { |resource| resource.evaluated? or resource.virtual? or resource.builtin_type? }
end
end
puppet-8.4.0/lib/puppet/parser/relationship.rb 0000644 0052762 0001160 00000005775 14552052437 021362 0 ustar jenkins jenkins # frozen_string_literal: true
class Puppet::Parser::Relationship
attr_accessor :source, :target, :type
PARAM_MAP = {:relationship => :before, :subscription => :notify}
def arrayify(resources, left)
case resources
when Puppet::Pops::Evaluator::Collectors::AbstractCollector
# on the LHS, go as far left as possible, else whatever the collected result is
left ? leftmost_alternative(resources) : resources.collected.values
when Array
resources
else
[resources]
end
end
def evaluate(catalog)
arrayify(source, true).each do |s|
arrayify(target, false).each do |t|
mk_relationship(s, t, catalog)
end
end
end
def initialize(source, target, type)
@source, @target, @type = source, target, type
end
def param_name
PARAM_MAP[type] || raise(ArgumentError, _("Invalid relationship type %{relationship_type}") % { relationship_type: type })
end
def mk_relationship(source, target, catalog)
source_ref = canonical_ref(source)
target_ref = canonical_ref(target)
rel_param = param_name
source_resource = catalog.resource(*source_ref)
unless source_resource
raise ArgumentError, _("Could not find resource '%{source}' for relationship on '%{target}'") % { source: source.to_s, target: target.to_s }
end
unless catalog.resource(*target_ref)
raise ArgumentError, _("Could not find resource '%{target}' for relationship from '%{source}'") % { target: target.to_s, source: source.to_s }
end
Puppet.debug {"Adding relationship from #{source} to #{target} with '#{param_name}'"}
if source_resource[rel_param].class != Array
source_resource[rel_param] = [source_resource[rel_param]].compact
end
source_resource[rel_param] << (target_ref[1].nil? ? target_ref[0] : "#{target_ref[0]}[#{target_ref[1]}]")
end
private
# Finds the leftmost alternative for a collector (if it is empty, try its empty alternative recursively until there is
# either nothing left, or a non empty set is found.
#
def leftmost_alternative(x)
if x.is_a?(Puppet::Pops::Evaluator::Collectors::AbstractCollector)
collected = x.collected
return collected.values unless collected.empty?
adapter = Puppet::Pops::Adapters::EmptyAlternativeAdapter.get(x)
adapter.nil? ? [] : leftmost_alternative(adapter.empty_alternative)
elsif x.is_a?(Array) && x.size == 1 && x[0].is_a?(Puppet::Pops::Evaluator::Collectors::AbstractCollector)
leftmost_alternative(x[0])
else
x
end
end
# Turns a PResourceType or PClassType into an array [type, title] and all other references to [ref, nil]
# This is needed since it is not possible to find resources in the catalog based on the type system types :-(
# (note, the catalog is also used on the agent side)
def canonical_ref(ref)
case ref
when Puppet::Pops::Types::PResourceType
[ref.type_name, ref.title]
when Puppet::Pops::Types::PClassType
['class', ref.class_name]
else
[ref.to_s, nil]
end
end
end
puppet-8.4.0/lib/puppet/parser/ast/ 0000755 0052762 0001160 00000000000 14552052637 017107 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/parser/ast/pops_bridge.rb 0000644 0052762 0001160 00000021612 14552052437 021731 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../../puppet/parser/ast/top_level_construct'
require_relative '../../../puppet/pops'
# The AST::Bridge contains classes that bridges between the new Pops based model
# and the 3.x AST. This is required to be able to reuse the Puppet::Resource::Type which is
# fundamental for the rest of the logic.
#
class Puppet::Parser::AST::PopsBridge
# Bridges to one Pops Model Expression
# The @value is the expression
# This is used to represent the body of a class, definition, or node, and for each parameter's default value
# expression.
#
class Expression < Puppet::Parser::AST::Leaf
def to_s
Puppet::Pops::Model::ModelTreeDumper.new.dump(@value)
end
def source_text
source_adapter = Puppet::Pops::Utils.find_closest_positioned(@value)
source_adapter ? source_adapter.extract_text() : nil
end
def evaluate(scope)
evaluator = Puppet::Pops::Parser::EvaluatingParser.singleton
object = evaluator.evaluate(scope, @value)
evaluator.convert_to_3x(object, scope)
end
# Adapts to 3x where top level constructs needs to have each to iterate over children. Short circuit this
# by yielding self. By adding this there is no need to wrap a pops expression inside an AST::BlockExpression
#
def each
yield self
end
def sequence_with(other)
if value.nil?
# This happens when testing and not having a complete setup
other
else
# When does this happen ? Ever ?
raise "sequence_with called on Puppet::Parser::AST::PopsBridge::Expression - please report use case"
# What should be done if the above happens (We don't want this to happen).
# Puppet::Parser::AST::BlockExpression.new(:children => [self] + other.children)
end
end
# The 3x requires code plugged in to an AST to have this in certain positions in the tree. The purpose
# is to either print the content, or to look for things that needs to be defined. This implementation
# cheats by always returning an empty array. (This allows simple files to not require a "Program" at the top.
#
def children
[]
end
end
class ExpressionSupportingReturn < Expression
def evaluate(scope)
return catch(:return) do
return catch(:next) do
return super(scope)
end
end
end
end
# Bridges the top level "Program" produced by the pops parser.
# Its main purpose is to give one point where all definitions are instantiated (actually defined since the
# Puppet 3x terminology is somewhat misleading - the definitions are instantiated, but instances of the created types
# are not created, that happens when classes are included / required, nodes are matched and when resources are instantiated
# by a resource expression (which is also used to instantiate a host class).
#
class Program < Puppet::Parser::AST::TopLevelConstruct
attr_reader :program_model, :context
def initialize(program_model, context = {})
@program_model = program_model
@context = context
@ast_transformer ||= Puppet::Pops::Model::AstTransformer.new(@context[:file])
end
# This is the 3x API, the 3x AST searches through all code to find the instructions that can be instantiated.
# This Pops-model based instantiation relies on the parser to build this list while parsing (which is more
# efficient as it avoids one full scan of all logic via recursive enumeration/yield)
#
def instantiate(modname)
@program_model.definitions.map do |d|
case d
when Puppet::Pops::Model::HostClassDefinition
instantiate_HostClassDefinition(d, modname)
when Puppet::Pops::Model::ResourceTypeDefinition
instantiate_ResourceTypeDefinition(d, modname)
when Puppet::Pops::Model::NodeDefinition
instantiate_NodeDefinition(d, modname)
else
loaders = Puppet::Pops::Loaders.loaders
loaders.instantiate_definition(d, loaders.find_loader(modname))
# The 3x logic calling this will not know what to do with the result, it is compacted away at the end
nil
end
end.flatten().compact() # flatten since node definition may have returned an array
# Compact since 4x definitions are not understood by compiler
end
def evaluate(scope)
Puppet::Pops::Parser::EvaluatingParser.singleton.evaluate(scope, program_model)
end
# Adapts to 3x where top level constructs needs to have each to iterate over children. Short circuit this
# by yielding self. This means that the HostClass container will call this bridge instance with `instantiate`.
#
def each
yield self
end
# Returns true if this Program only contains definitions
def is_definitions_only?
is_definition?(program_model)
end
private
def is_definition?(o)
case o
when Puppet::Pops::Model::Program
is_definition?(o.body)
when Puppet::Pops::Model::BlockExpression
o.statements.all {|s| is_definition?(s) }
when Puppet::Pops::Model::Definition
true
else
false
end
end
def instantiate_Parameter(o)
# 3x needs parameters as an array of `[name]` or `[name, value_expr]`
if o.value
[o.name, Expression.new(:value => o.value)]
else
[o.name]
end
end
def create_type_map(definition)
result = {}
# No need to do anything if there are no parameters
return result unless definition.parameters.size > 0
# No need to do anything if there are no typed parameters
typed_parameters = definition.parameters.select {|p| p.type_expr }
return result if typed_parameters.empty?
# If there are typed parameters, they need to be evaluated to produce the corresponding type
# instances. This evaluation requires a scope. A scope is not available when doing deserialization
# (there is also no initialized evaluator). When running apply and test however, the environment is
# reused and we may reenter without a scope (which is fine). A debug message is then output in case
# there is the need to track down the odd corner case. See {#obtain_scope}.
#
scope = obtain_scope
if scope
evaluator = Puppet::Pops::Parser::EvaluatingParser.singleton
typed_parameters.each do |p|
result[p.name] = evaluator.evaluate(scope, p.type_expr)
end
end
result
end
# Obtains the scope or issues a warning if :global_scope is not bound
def obtain_scope
scope = Puppet.lookup(:global_scope) do
# This occurs when testing and when applying a catalog (there is no scope available then), and
# when running tests that run a partial setup.
# This is bad if the logic is trying to compile, but a warning can not be issues since it is a normal
# use case that there is no scope when requesting the type in order to just get the parameters.
Puppet.debug {_("Instantiating Resource with type checked parameters - scope is missing, skipping type checking.")}
nil
end
scope
end
# Produces a hash with data for Definition and HostClass
def args_from_definition(o, modname, expr_class = Expression)
args = {
:arguments => o.parameters.collect {|p| instantiate_Parameter(p) },
:argument_types => create_type_map(o),
:module_name => modname
}
unless is_nop?(o.body)
args[:code] = expr_class.new(:value => o.body)
end
@ast_transformer.merge_location(args, o)
end
def instantiate_HostClassDefinition(o, modname)
args = args_from_definition(o, modname, ExpressionSupportingReturn)
args[:parent] = absolute_reference(o.parent_class)
Puppet::Resource::Type.new(:hostclass, o.name, @context.merge(args))
end
def instantiate_ResourceTypeDefinition(o, modname)
instance = Puppet::Resource::Type.new(:definition, o.name, @context.merge(args_from_definition(o, modname, ExpressionSupportingReturn)))
Puppet::Pops::Loaders.register_runtime3_type(instance.name, o.locator.to_uri(o))
instance
end
def instantiate_NodeDefinition(o, modname)
args = { :module_name => modname }
unless is_nop?(o.body)
args[:code] = Expression.new(:value => o.body)
end
unless is_nop?(o.parent)
args[:parent] = @ast_transformer.hostname(o.parent)
end
args = @ast_transformer.merge_location(args, o)
host_matches = @ast_transformer.hostname(o.host_matches)
host_matches.collect do |name|
Puppet::Resource::Type.new(:node, name, @context.merge(args))
end
end
def code()
Expression.new(:value => @value)
end
def is_nop?(o)
@ast_transformer.is_nop?(o)
end
def absolute_reference(ref)
if ref.nil? || ref.empty? || ref.start_with?('::')
ref
else
"::#{ref}"
end
end
end
end
puppet-8.4.0/lib/puppet/parser/ast/resourceparam.rb 0000644 0052762 0001160 00000001535 14552052437 022306 0 ustar jenkins jenkins # frozen_string_literal: true
# The AST object for the parameters inside resource expressions
#
class Puppet::Parser::AST::ResourceParam < Puppet::Parser::AST::Branch
attr_accessor :value, :param, :add
def initialize(argshash)
Puppet.warn_once('deprecations', 'AST::ResourceParam', _('Use of Puppet::Parser::AST::ResourceParam is deprecated and not fully functional'))
super(argshash)
end
def each
[@param, @value].each { |child| yield child }
end
# Return the parameter and the value.
def evaluate(scope)
value = @value.safeevaluate(scope)
return Puppet::Parser::Resource::Param.new(
:name => @param,
:value => value.nil? ? :undef : value,
:source => scope.source,
:line => self.line,
:file => self.file,
:add => self.add
)
end
def to_s
"#{@param} => #{@value}"
end
end
puppet-8.4.0/lib/puppet/parser/ast/block_expression.rb 0000644 0052762 0001160 00000000725 14552052437 023007 0 ustar jenkins jenkins # frozen_string_literal: true
# Evaluates contained expressions, produce result of the last
#
class Puppet::Parser::AST::BlockExpression < Puppet::Parser::AST::Branch
def evaluate(scope)
@children.reduce(nil) { |_, child| child.safeevaluate(scope) }
end
def sequence_with(other)
Puppet::Parser::AST::BlockExpression.new(:children => self.children + other.children)
end
def to_s
"[" + @children.collect { |c| c.to_s }.join(', ') + "]"
end
end
puppet-8.4.0/lib/puppet/parser/ast/top_level_construct.rb 0000644 0052762 0001160 00000000313 14552052437 023524 0 ustar jenkins jenkins # frozen_string_literal: true
# The base class for AST nodes representing top level things:
# hostclasses, definitions, and nodes.
class Puppet::Parser::AST::TopLevelConstruct < Puppet::Parser::AST
end
puppet-8.4.0/lib/puppet/parser/ast/resource_instance.rb 0000644 0052762 0001160 00000000654 14552052437 023152 0 ustar jenkins jenkins # frozen_string_literal: true
# A simple container for a parameter for an object. Consists of a
# title and a set of parameters.
#
class Puppet::Parser::AST::ResourceInstance < Puppet::Parser::AST::Branch
attr_accessor :title, :parameters
def initialize(argshash)
Puppet.warn_once('deprecations', 'AST::ResourceInstance', _('Use of Puppet::Parser::AST::ResourceInstance is deprecated'))
super(argshash)
end
end
puppet-8.4.0/lib/puppet/parser/ast/hostclass.rb 0000644 0052762 0001160 00000001311 14552052437 021431 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../../puppet/parser/ast/top_level_construct'
class Puppet::Parser::AST::Hostclass < Puppet::Parser::AST::TopLevelConstruct
attr_accessor :name, :context
def initialize(name, context = {})
@context = context
@name = name
end
def instantiate(modname)
new_class = Puppet::Resource::Type.new(:hostclass, @name, @context.merge(:module_name => modname))
all_types = [new_class]
if code
code.each do |nested_ast_node|
if nested_ast_node.respond_to? :instantiate
all_types += nested_ast_node.instantiate(modname)
end
end
end
return all_types
end
def code()
@context[:code]
end
end
puppet-8.4.0/lib/puppet/parser/ast/branch.rb 0000644 0052762 0001160 00000001126 14552052437 020667 0 ustar jenkins jenkins # frozen_string_literal: true
# The parent class of all AST objects that contain other AST objects.
# Everything but the really simple objects descend from this. It is
# important to note that Branch objects contain other AST objects only --
# if you want to contain values, use a descendant of the AST::Leaf class.
#
# @api private
class Puppet::Parser::AST::Branch < Puppet::Parser::AST
include Enumerable
attr_accessor :pin, :children
def each
@children.each { |child| yield child }
end
def initialize(children: [], **args)
@children = children
super(**args)
end
end
puppet-8.4.0/lib/puppet/parser/ast/resource.rb 0000644 0052762 0001160 00000005156 14552052437 021270 0 ustar jenkins jenkins # frozen_string_literal: true
# Instruction for Resource instantiation.
# Instantiates resources of both native and user defined types.
#
class Puppet::Parser::AST::Resource < Puppet::Parser::AST::Branch
attr_accessor :type, :instances, :exported, :virtual
def initialize(argshash)
Puppet.warn_once('deprecations', 'AST::Resource', _('Use of Puppet::Parser::AST::Resource is deprecated and not fully functional'))
super(argshash)
end
# Evaluates resources by adding them to the compiler for lazy evaluation
# and returning the produced resource references.
#
def evaluate(scope)
# We want virtual to be true if exported is true. We can't
# just set :virtual => self.virtual in the initialization,
# because sometimes the :virtual attribute is set *after*
# :exported, in which case it clobbers :exported if :exported
# is true. Argh, this was a very tough one to track down.
virt = self.virtual || self.exported
# First level of implicit iteration: build a resource for each
# instance. This handles things like:
# file { '/foo': owner => blah; '/bar': owner => blah }
@instances.map do |instance|
# Evaluate all of the specified params.
paramobjects = instance.parameters.map { |param| param.safeevaluate(scope) }
resource_titles = instance.title.safeevaluate(scope)
# it's easier to always use an array, even for only one name
resource_titles = [resource_titles] unless resource_titles.is_a?(Array)
fully_qualified_type, resource_titles = scope.resolve_type_and_titles(type, resource_titles)
# Second level of implicit iteration; build a resource for each
# title. This handles things like:
# file { ['/foo', '/bar']: owner => blah }
resource_titles.flatten.map do |resource_title|
exceptwrap :type => Puppet::ParseError do
resource = Puppet::Parser::Resource.new(
fully_qualified_type, resource_title,
:parameters => paramobjects,
:file => self.file,
:line => self.line,
:exported => self.exported,
:virtual => virt,
:source => scope.source,
:scope => scope,
:strict => true
)
if resource.resource_type.is_a? Puppet::Resource::Type
resource.resource_type.instantiate_resource(scope, resource)
end
scope.compiler.add_resource(scope, resource)
scope.compiler.evaluate_classes([resource_title], scope, false) if fully_qualified_type == 'class'
resource
end
end
end.flatten.reject { |resource| resource.nil? }
end
end
puppet-8.4.0/lib/puppet/parser/ast/leaf.rb 0000644 0052762 0001160 00000004354 14552052437 020347 0 ustar jenkins jenkins # frozen_string_literal: true
# The base class for all of the leaves of the parse trees. These
# basically just have types and values. Both of these parameters
# are simple values, not AST objects.
#
class Puppet::Parser::AST::Leaf < Puppet::Parser::AST
attr_accessor :value, :type
# Return our value.
def evaluate(scope)
@value
end
def match(value)
@value == value
end
def to_s
@value.to_s unless @value.nil?
end
def initialize(value: nil, file: nil, line: nil, pos: nil)
@value = value
super(file: file, line: line, pos: pos)
end
end
# Host names, either fully qualified or just the short name, or even a regex
#
class Puppet::Parser::AST::HostName < Puppet::Parser::AST::Leaf
def initialize(value: nil, file: nil, line: nil, pos: nil)
super(value: value, file: file, line: line, pos: pos)
# Note that this is an AST::Regex, not a Regexp
unless @value.is_a?(Regex)
@value = @value.to_s.downcase
if @value =~ /[^-\w.]/
raise Puppet::DevError, _("'%{value}' is not a valid hostname") % { value: @value }
end
end
end
# implementing eql? and hash so that when an HostName is stored
# in a hash it has the same hashing properties as the underlying value
def eql?(value)
@value.eql?(value.is_a?(HostName) ? value.value : value)
end
def hash
@value.hash
end
end
class Puppet::Parser::AST::Regex < Puppet::Parser::AST::Leaf
def initialize(value: nil, file: nil, line: nil, pos: nil)
super(value: value, file: file, line: line, pos: pos)
# transform value from hash options unless it is already a regular expression
@value = Regexp.new(@value) unless @value.is_a?(Regexp)
end
# we're returning self here to wrap the regexp and to be used in places
# where a string would have been used, without modifying any client code.
# For instance, in many places we have the following code snippet:
# val = @val.safeevaluate(@scope)
# if val.match(otherval)
# ...
# end
# this way, we don't have to modify this test specifically for handling
# regexes.
#
def evaluate(scope)
self
end
def match(value)
@value.match(value)
end
def to_s
Puppet::Pops::Types::PRegexpType.regexp_to_s_with_delimiters(@value)
end
end
puppet-8.4.0/lib/puppet/parser/ast/node.rb 0000644 0052762 0001160 00000001162 14552052437 020357 0 ustar jenkins jenkins # frozen_string_literal: true
class Puppet::Parser::AST::Node < Puppet::Parser::AST::TopLevelConstruct
attr_accessor :names, :context
def initialize(names, context = {})
raise ArgumentError, _("names should be an array") unless names.is_a? Array
if context[:parent]
raise Puppet::DevError, _("Node inheritance is removed in Puppet 4.0.0. See http://links.puppet.com/puppet-node-inheritance-deprecation")
end
@names = names
@context = context
end
def instantiate(modname)
@names.map { |name| Puppet::Resource::Type.new(:node, name, @context.merge(:module_name => modname)) }
end
end
puppet-8.4.0/lib/puppet/parser/type_loader.rb 0000644 0052762 0001160 00000010507 14552052437 021155 0 ustar jenkins jenkins # frozen_string_literal: true
require 'find'
require 'forwardable'
require_relative '../../puppet/parser/parser_factory'
class Puppet::Parser::TypeLoader
extend Forwardable
class TypeLoaderError < StandardError; end
# Import manifest files that match a given file glob pattern.
#
# @param pattern [String] the file glob to apply when determining which files
# to load
# @param dir [String] base directory to use when the file is not
# found in a module
# @api private
def import(pattern, dir)
modname, files = Puppet::Parser::Files.find_manifests_in_modules(pattern, environment)
if files.empty?
abspat = File.expand_path(pattern, dir)
file_pattern = abspat + (File.extname(abspat).empty? ? '.pp' : '' )
files = Dir.glob(file_pattern).uniq.reject { |f| FileTest.directory?(f) }
modname = nil
if files.empty?
raise_no_files_found(pattern)
end
end
load_files(modname, files)
end
# Load all of the manifest files in all known modules.
# @api private
def import_all
# And then load all files from each module, but (relying on system
# behavior) only load files from the first module of a given name. E.g.,
# given first/foo and second/foo, only files from first/foo will be loaded.
environment.modules.each do |mod|
load_files(mod.name, mod.all_manifests)
end
end
def_delegator :environment, :known_resource_types
def initialize(env)
self.environment = env
end
def environment
@environment
end
def environment=(env)
if env.is_a?(String) or env.is_a?(Symbol)
@environment = Puppet.lookup(:environments).get!(env)
else
@environment = env
end
end
# Try to load the object with the given fully qualified name.
def try_load_fqname(type, fqname)
return nil if fqname == "" # special-case main.
files_to_try_for(fqname).each do |filename|
begin
imported_types = import_from_modules(filename)
result = imported_types.find { |t| t.type == type and t.name == fqname }
if result
Puppet.debug {"Automatically imported #{fqname} from #{filename} into #{environment}"}
return result
end
rescue TypeLoaderError
# I'm not convinced we should just drop these errors, but this
# preserves existing behaviours.
end
end
# Nothing found.
return nil
end
def parse_file(file)
Puppet.debug { "importing '#{file}' in environment #{environment}" }
parser = Puppet::Parser::ParserFactory.parser
parser.file = file
return parser.parse
end
private
def import_from_modules(pattern)
modname, files = Puppet::Parser::Files.find_manifests_in_modules(pattern, environment)
if files.empty?
raise_no_files_found(pattern)
end
load_files(modname, files)
end
def raise_no_files_found(pattern)
raise TypeLoaderError, _("No file(s) found for import of '%{pattern}'") % { pattern: pattern }
end
def load_files(modname, files)
@loaded ||= {}
loaded_asts = []
files.reject { |file| @loaded[file] }.each do |file|
# The squelch_parse_errors use case is for parsing for the purpose of searching
# for information and it should not abort.
# There is currently one user in indirector/resourcetype/parser
#
if Puppet.lookup(:squelch_parse_errors) {|| false }
begin
loaded_asts << parse_file(file)
rescue => e
# Resume from errors so that all parseable files may
# still be parsed. Mark this file as loaded so that
# it would not be parsed next time (handle it as if
# it was successfully parsed).
Puppet.debug { "Unable to parse '#{file}': #{e.message}" }
end
else
loaded_asts << parse_file(file)
end
@loaded[file] = true
end
loaded_asts.collect do |ast|
known_resource_types.import_ast(ast, modname)
end.flatten
end
# Return a list of all file basenames that should be tried in order
# to load the object with the given fully qualified name.
def files_to_try_for(qualified_name)
qualified_name.split('::').inject([]) do |paths, name|
add_path_for_name(paths, name)
end
end
def add_path_for_name(paths, name)
if paths.empty?
[name]
else
paths.unshift(File.join(paths.first, name))
end
end
end
puppet-8.4.0/lib/puppet/parser/script_compiler.rb 0000644 0052762 0001160 00000010046 14552052437 022042 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/loaders'
require_relative '../../puppet/pops'
# A Script "compiler" that does not support catalog operations
#
# The Script compiler is "one shot" - it does not support rechecking if underlying source has changed or
# deal with possible errors in a cached environment.
#
class Puppet::Parser::ScriptCompiler
# Allows the ScriptCompiler to use the 3.x Scope class without being an actual "Compiler"
#
include Puppet::Parser::AbstractCompiler
# @api private
attr_reader :topscope
# @api private
attr_reader :qualified_variables
# Access to the configured loaders for 4x
# @return [Puppet::Pops::Loader::Loaders] the configured loaders
# @api private
attr_reader :loaders
# @api private
attr_reader :environment
# @api private
attr_reader :node_name
def with_context_overrides(description = '', &block)
Puppet.override( @context_overrides , description, &block)
end
# Evaluates the configured setup for a script + code in an environment with modules
#
def compile
Puppet[:strict_variables] = true
Puppet[:strict] = :error
# TRANSLATORS, "For running script" is not user facing
Puppet.override( @context_overrides , "For running script") do
# TRANSLATORS "main" is a function name and should not be translated
result = Puppet::Util::Profiler.profile(_("Script: Evaluated main"), [:script, :evaluate_main]) { evaluate_main }
if block_given?
yield self
else
result
end
end
rescue Puppet::ParseErrorWithIssue => detail
detail.node = node_name
Puppet.log_exception(detail)
raise
rescue => detail
message = "#{detail} on node #{node_name}"
Puppet.log_exception(detail, message)
raise Puppet::Error, message, detail.backtrace
end
# Constructs the overrides for the context
def context_overrides()
{
:current_environment => environment,
:global_scope => @topscope, # 4x placeholder for new global scope
:loaders => @loaders, # 4x loaders
:rich_data => true,
}
end
# Create a script compiler for the given environment where errors are logged as coming
# from the given node_name
#
def initialize(environment, node_name, for_agent=false)
@environment = environment
@node_name = node_name
# Create the initial scope, it is needed early
@topscope = Puppet::Parser::Scope.new(self)
# Initialize loaders and Pcore
if for_agent
@loaders = Puppet::Pops::Loaders.new(environment, true)
else
@loaders = Puppet::Pops::Loaders.new(environment)
end
# Need to compute overrides here, and remember them, because we are about to
# Expensive entries in the context are bound lazily.
@context_overrides = context_overrides()
# Resolutions of fully qualified variable names
@qualified_variables = {}
end
# Having multiple named scopes hanging from top scope is not supported when scripting
# in the regular compiler this is used to create one named scope per class.
# When scripting, the "main class" is just a container of the top level code to evaluate
# and it is not evaluated as a class added to a catalog. Since classes are not supported
# there is no need to support the concept of "named scopes" as all variables are local
# or in the top scope itself (notably, the $settings:: namespace is initialized
# as just a set of variables in that namespace - there is no named scope for 'settings'
# when scripting.
#
# Keeping this method here to get specific error as being unsure if there are functions/logic
# that will call this. The AbstractCompiler defines this method, but maybe it does not
# have to (TODO).
#
def newscope(parent, options = {})
raise _('having multiple named scopes is not supported when scripting')
end
private
# Find and evaluate the top level code.
def evaluate_main
@loaders.pre_load
program = @loaders.load_main_manifest
return program.nil? ? nil : Puppet::Pops::Parser::EvaluatingParser.singleton.evaluator.evaluate(program, @topscope)
end
end
puppet-8.4.0/lib/puppet/parser/catalog_compiler.rb 0000644 0052762 0001160 00000003222 14552052437 022146 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/loaders'
require_relative '../../puppet/pops'
# A Catalog "compiler" that is like the regular compiler but with an API
# that is harmonized with the ScriptCompiler
#
# The Script compiler is "one shot" - it does not support rechecking if underlying source has changed or
# deal with possible errors in a cached environment.
#
class Puppet::Parser::CatalogCompiler < Puppet::Parser::Compiler
# Evaluates the configured setup for a script + code in an environment with modules
#
def compile
Puppet[:strict_variables] = true
Puppet[:strict] = :error
Puppet.override(rich_data: true) do
super
end
rescue Puppet::ParseErrorWithIssue => detail
detail.node = node.name
Puppet.log_exception(detail)
raise
rescue => detail
message = "#{detail} on node #{node.name}"
Puppet.log_exception(detail, message)
raise Puppet::Error, message, detail.backtrace
end
# Evaluates all added constructs, and validates the resulting catalog.
# This can be called whenever a series of evaluation of puppet code strings
# have reached a stable state (essentially that there are no relationships to
# non-existing resources).
#
# Raises an error if validation fails.
#
def compile_additions
evaluate_additions
validate
end
# Evaluates added constructs that are lazily evaluated until all of them have been evaluated.
#
def evaluate_additions
evaluate_generators
finish
end
# Validates the current state of the catalog.
# Does not cause evaluation of lazy constructs.
def validate
validate_catalog(CatalogValidator::FINAL)
end
end
puppet-8.4.0/lib/puppet/parser/functions.rb 0000644 0052762 0001160 00000027036 14552052437 020663 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/util/autoload'
require_relative '../../puppet/parser/scope'
require_relative '../../puppet/pops/adaptable'
require_relative '../../puppet/concurrent/lock'
# A module for managing parser functions. Each specified function
# is added to a central module that then gets included into the Scope
# class.
#
# @api public
module Puppet::Parser::Functions
Environment = Puppet::Node::Environment
class << self
include Puppet::Util
end
# Reset the list of loaded functions.
#
# @api private
def self.reset
# Runs a newfunction to create a function for each of the log levels
root_env = Puppet.lookup(:root_environment)
AnonymousModuleAdapter.clear(root_env)
Puppet::Util::Log.levels.each do |level|
newfunction(level,
:environment => root_env,
:doc => "Log a message on the server at level #{level}.") do |vals|
send(level, vals.join(" "))
end
end
end
class AutoloaderDelegate
attr_reader :delegatee
def initialize
@delegatee = Puppet::Util::Autoload.new(self, "puppet/parser/functions")
end
def loadall(env = Puppet.lookup(:current_environment))
if Puppet[:strict] != :off
Puppet.warn_once('deprecations', 'Puppet::Parser::Functions#loadall', _("The method 'Puppet::Parser::Functions.autoloader#loadall' is deprecated in favor of using 'Scope#call_function'."))
end
@delegatee.loadall(env)
end
def load(name, env = Puppet.lookup(:current_environment))
if Puppet[:strict] != :off
Puppet.warn_once('deprecations', "Puppet::Parser::Functions#load('#{name}')", _("The method 'Puppet::Parser::Functions.autoloader#load(\"%{name}\")' is deprecated in favor of using 'Scope#call_function'.") % {name: name})
end
@delegatee.load(name, env)
end
def loaded?(name)
if Puppet[:strict] != :off
Puppet.warn_once('deprecations', "Puppet::Parser::Functions.loaded?('#{name}')", _("The method 'Puppet::Parser::Functions.autoloader#loaded?(\"%{name}\")' is deprecated in favor of using 'Scope#call_function'.") % {name: name})
end
@delegatee.loaded?(name)
end
end
# Accessor for singleton autoloader
#
# @api private
def self.autoloader
@autoloader ||= AutoloaderDelegate.new
end
# An adapter that ties the anonymous module that acts as the container for all 3x functions to the environment
# where the functions are created. This adapter ensures that the life-cycle of those functions doesn't exceed
# the life-cycle of the environment.
#
# @api private
class AnonymousModuleAdapter < Puppet::Pops::Adaptable::Adapter
attr_accessor :module
def self.create_adapter(env)
adapter = super(env)
adapter.module = Module.new do
@metadata = {}
def self.all_function_info
@metadata
end
def self.get_function_info(name)
@metadata[name]
end
def self.add_function_info(name, info)
@metadata[name] = info
end
end
adapter
end
end
@environment_module_lock = Puppet::Concurrent::Lock.new
# Get the module that functions are mixed into corresponding to an
# environment
#
# @api private
def self.environment_module(env)
@environment_module_lock.synchronize do
AnonymousModuleAdapter.adapt(env).module
end
end
# Create a new Puppet DSL function.
#
# **The {newfunction} method provides a public API.**
#
# This method is used both internally inside of Puppet to define parser
# functions. For example, template() is defined in
# {file:lib/puppet/parser/functions/template.rb template.rb} using the
# {newfunction} method. Third party Puppet modules such as
# [stdlib](https://forge.puppetlabs.com/puppetlabs/stdlib) use this method to
# extend the behavior and functionality of Puppet.
#
# See also [Docs: Custom
# Functions](https://puppet.com/docs/puppet/5.5/lang_write_functions_in_puppet.html)
#
# @example Define a new Puppet DSL Function
# >> Puppet::Parser::Functions.newfunction(:double, :arity => 1,
# :doc => "Doubles an object, typically a number or string.",
# :type => :rvalue) {|i| i[0]*2 }
# => {:arity=>1, :type=>:rvalue,
# :name=>"function_double",
# :doc=>"Doubles an object, typically a number or string."}
#
# @example Invoke the double function from irb as is done in RSpec examples:
# >> require 'puppet_spec/scope'
# >> scope = PuppetSpec::Scope.create_test_scope_for_node('example')
# => Scope()
# >> scope.function_double([2])
# => 4
# >> scope.function_double([4])
# => 8
# >> scope.function_double([])
# ArgumentError: double(): Wrong number of arguments given (0 for 1)
# >> scope.function_double([4,8])
# ArgumentError: double(): Wrong number of arguments given (2 for 1)
# >> scope.function_double(["hello"])
# => "hellohello"
#
# @param [Symbol] name the name of the function represented as a ruby Symbol.
# The {newfunction} method will define a Ruby method based on this name on
# the parser scope instance.
#
# @param [Proc] block the block provided to the {newfunction} method will be
# executed when the Puppet DSL function is evaluated during catalog
# compilation. The arguments to the function will be passed as an array to
# the first argument of the block. The return value of the block will be
# the return value of the Puppet DSL function for `:rvalue` functions.
#
# @option options [:rvalue, :statement] :type (:statement) the type of function.
# Either `:rvalue` for functions that return a value, or `:statement` for
# functions that do not return a value.
#
# @option options [String] :doc ('') the documentation for the function.
# This string will be extracted by documentation generation tools.
#
# @option options [Integer] :arity (-1) the
# [arity](https://en.wikipedia.org/wiki/Arity) of the function. When
# specified as a positive integer the function is expected to receive
# _exactly_ the specified number of arguments. When specified as a
# negative number, the function is expected to receive _at least_ the
# absolute value of the specified number of arguments incremented by one.
# For example, a function with an arity of `-4` is expected to receive at
# minimum 3 arguments. A function with the default arity of `-1` accepts
# zero or more arguments. A function with an arity of 2 must be provided
# with exactly two arguments, no more and no less. Added in Puppet 3.1.0.
#
# @option options [Puppet::Node::Environment] :environment (nil) can
# explicitly pass the environment we wanted the function added to. Only used
# to set logging functions in root environment
#
# @return [Hash] describing the function.
#
# @api public
def self.newfunction(name, options = {}, &block)
name = name.intern
environment = options[:environment] || Puppet.lookup(:current_environment)
Puppet.warning _("Overwriting previous definition for function %{name}") % { name: name } if get_function(name, environment)
arity = options[:arity] || -1
ftype = options[:type] || :statement
unless ftype == :statement or ftype == :rvalue
raise Puppet::DevError, _("Invalid statement type %{type}") % { type: ftype.inspect }
end
# the block must be installed as a method because it may use "return",
# which is not allowed from procs.
real_fname = "real_function_#{name}"
environment_module(environment).send(:define_method, real_fname, &block)
fname = "function_#{name}"
env_module = environment_module(environment)
env_module.send(:define_method, fname) do |*args|
Puppet::Util::Profiler.profile(_("Called %{name}") % { name: name }, [:functions, name]) do
if args[0].is_a? Array
if arity >= 0 and args[0].size != arity
raise ArgumentError, _("%{name}(): Wrong number of arguments given (%{arg_count} for %{arity})") % { name: name, arg_count: args[0].size, arity: arity }
elsif arity < 0 and args[0].size < (arity+1).abs
raise ArgumentError, _("%{name}(): Wrong number of arguments given (%{arg_count} for minimum %{min_arg_count})") % { name: name, arg_count: args[0].size, min_arg_count: (arity+1).abs }
end
r = Puppet::Pops::Evaluator::Runtime3FunctionArgumentConverter.convert_return(self.send(real_fname, args[0]))
# avoid leaking aribtrary value if not being an rvalue function
options[:type] == :rvalue ? r : nil
else
raise ArgumentError, _("custom functions must be called with a single array that contains the arguments. For example, function_example([1]) instead of function_example(1)")
end
end
end
func = {:arity => arity, :type => ftype, :name => fname}
func[:doc] = options[:doc] if options[:doc]
env_module.add_function_info(name, func)
func
end
# Determine if a function is defined
#
# @param [Symbol] name the function
# @param [Puppet::Node::Environment] environment the environment to find the function in
#
# @return [Symbol, false] The name of the function if it's defined,
# otherwise false.
#
# @api public
def self.function(name, environment = Puppet.lookup(:current_environment))
name = name.intern
func = get_function(name, environment)
unless func
autoloader.delegatee.load(name, environment)
func = get_function(name, environment)
end
if func
func[:name]
else
false
end
end
def self.functiondocs(environment = Puppet.lookup(:current_environment))
autoloader.delegatee.loadall(environment)
ret = ''.dup
merged_functions(environment).sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, hash|
ret << "#{name}\n#{"-" * name.to_s.length}\n"
if hash[:doc]
ret << Puppet::Util::Docs.scrub(hash[:doc])
else
ret << "Undocumented.\n"
end
ret << "\n\n- *Type*: #{hash[:type]}\n\n"
end
ret
end
# Determine whether a given function returns a value.
#
# @param [Symbol] name the function
# @param [Puppet::Node::Environment] environment The environment to find the function in
# @return [Boolean] whether it is an rvalue function
#
# @api public
def self.rvalue?(name, environment = Puppet.lookup(:current_environment))
func = get_function(name, environment)
func ? func[:type] == :rvalue : false
end
# Return the number of arguments a function expects.
#
# @param [Symbol] name the function
# @param [Puppet::Node::Environment] environment The environment to find the function in
# @return [Integer] The arity of the function. See {newfunction} for
# the meaning of negative values.
#
# @api public
def self.arity(name, environment = Puppet.lookup(:current_environment))
func = get_function(name, environment)
func ? func[:arity] : -1
end
class << self
private
def merged_functions(environment)
root = environment_module(Puppet.lookup(:root_environment))
env = environment_module(environment)
root.all_function_info.merge(env.all_function_info)
end
def get_function(name, environment)
environment_module(environment).get_function_info(name.intern) || environment_module(Puppet.lookup(:root_environment)).get_function_info(name.intern)
end
end
class Error
def self.is4x(name)
raise Puppet::ParseError, _("%{name}() can only be called using the 4.x function API. See Scope#call_function") % { name: name }
end
end
end
puppet-8.4.0/lib/puppet/parser/ast.rb 0000644 0052762 0001160 00000004062 14552052437 017434 0 ustar jenkins jenkins # frozen_string_literal: true
# The base class for the 3x "parse tree", now only used by the top level
# constructs and the compiler.
# Handles things like file name, line #, and also does the initialization
# for all of the parameters of all of the child objects.
#
class Puppet::Parser::AST
AST = Puppet::Parser::AST
include Puppet::Util::Errors
attr_accessor :parent, :scope, :file, :line, :pos
def inspect
"( #{self.class} #{self} #{@children.inspect} )"
end
# Evaluate the current object. Just a stub method, since the subclass
# should override this method.
def evaluate(scope)
end
# The version of the evaluate method that should be called, because it
# correctly handles errors. It is critical to use this method because
# it can enable you to catch the error where it happens, rather than
# much higher up the stack.
def safeevaluate(scope)
# We duplicate code here, rather than using exceptwrap, because this
# is called so many times during parsing.
begin
return self.evaluate(scope)
rescue Puppet::Pops::Evaluator::PuppetStopIteration => detail
raise detail
# # Only deals with StopIteration from the break() function as a general
# # StopIteration is a general runtime problem
# raise Puppet::ParseError.new(detail.message, detail.file, detail.line, detail)
rescue Puppet::Error => detail
raise adderrorcontext(detail)
rescue => detail
error = Puppet::ParseError.new(detail.to_s, nil, nil, detail)
# We can't use self.fail here because it always expects strings,
# not exceptions.
raise adderrorcontext(error, detail)
end
end
def initialize(file: nil, line: nil, pos: nil)
@file = file
@line = line
@pos = pos
end
end
# And include all of the AST subclasses.
require_relative 'ast/branch'
require_relative 'ast/leaf'
require_relative 'ast/block_expression'
require_relative 'ast/hostclass'
require_relative 'ast/node'
require_relative 'ast/resource'
require_relative 'ast/resource_instance'
require_relative 'ast/resourceparam'
puppet-8.4.0/lib/puppet/parser/resource.rb 0000644 0052762 0001160 00000026272 14552052437 020503 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../puppet/resource'
# The primary difference between this class and its
# parent is that this class has rules on who can set
# parameters
class Puppet::Parser::Resource < Puppet::Resource
require_relative 'resource/param'
require_relative '../../puppet/util/tagging'
include Puppet::Util
include Puppet::Util::Errors
include Puppet::Util::Logging
attr_accessor :source, :scope, :collector_id
attr_accessor :virtual, :override, :translated, :catalog, :evaluated
attr_accessor :file, :line, :kind
attr_reader :exported, :parameters
# Determine whether the provided parameter name is a relationship parameter.
def self.relationship_parameter?(name)
@relationship_names ||= Puppet::Type.relationship_params.collect { |p| p.name }
@relationship_names.include?(name)
end
# Set up some boolean test methods
def translated?; !!@translated; end
def override?; !!@override; end
def evaluated?; !!@evaluated; end
def [](param)
param = param.intern
if param == :title
return self.title
end
if @parameters.has_key?(param)
@parameters[param].value
else
nil
end
end
def eachparam
@parameters.each do |_name, param|
yield param
end
end
def environment
scope.environment
end
# Process the stage metaparameter for a class. A containment edge
# is drawn from the class to the stage. The stage for containment
# defaults to main, if none is specified.
def add_edge_to_stage
return unless self.class?
stage = catalog.resource(:stage, self[:stage] || (scope && scope.resource && scope.resource[:stage]) || :main)
unless stage
raise ArgumentError, _("Could not find stage %{stage} specified by %{resource}") % { stage: self[:stage] || :main, resource: self }
end
self[:stage] ||= stage.title unless stage.title == :main
catalog.add_edge(stage, self)
end
# Retrieve the associated definition and evaluate it.
def evaluate
return if evaluated?
Puppet::Util::Profiler.profile(_("Evaluated resource %{res}") % { res: self }, [:compiler, :evaluate_resource, self]) do
@evaluated = true
if builtin_type?
devfail "Cannot evaluate a builtin type (#{type})"
elsif resource_type.nil?
self.fail "Cannot find definition #{type}"
else
finish_evaluation() # do not finish completely (as that destroys Sensitive data)
resource_type.evaluate_code(self)
end
end
end
# Mark this resource as both exported and virtual,
# or remove the exported mark.
def exported=(value)
if value
@virtual = true
@exported = value
else
@exported = value
end
end
# Finish the evaluation by assigning defaults and scope tags
# @api private
#
def finish_evaluation
return if @evaluation_finished
add_scope_tags
@evaluation_finished = true
end
# Do any finishing work on this object, called before
# storage/translation. The method does nothing the second time
# it is called on the same resource.
#
# @param do_validate [Boolean] true if validation should be performed
#
# @api private
def finish(do_validate = true)
return if finished?
@finished = true
finish_evaluation
replace_sensitive_data
validate if do_validate
end
# Has this resource already been finished?
def finished?
@finished
end
def initialize(type, title, attributes, with_defaults = true)
raise ArgumentError, _('Resources require a hash as last argument') unless attributes.is_a? Hash
raise ArgumentError, _('Resources require a scope') unless attributes[:scope]
super(type, title, attributes)
@source ||= scope.source
if with_defaults
scope.lookupdefaults(self.type).each_pair do |name, param|
unless @parameters.include?(name)
self.debug "Adding default for #{name}"
param = param.dup
@parameters[name] = param
tag(*param.value) if param.name == :tag
end
end
end
end
# Is this resource modeling an isomorphic resource type?
def isomorphic?
if builtin_type?
return resource_type.isomorphic?
else
return true
end
end
# Merge an override resource in. This will throw exceptions if
# any overrides aren't allowed.
def merge(resource)
# Test the resource scope, to make sure the resource is even allowed
# to override.
unless self.source.equal?(resource.source) || resource.source.child_of?(self.source)
raise Puppet::ParseError.new(_("Only subclasses can override parameters"), resource.file, resource.line)
end
if evaluated?
error_location_str = Puppet::Util::Errors.error_location(file, line)
msg = if error_location_str.empty?
_('Attempt to override an already evaluated resource with new values')
else
_('Attempt to override an already evaluated resource, defined at %{error_location}, with new values') % { error_location: error_location_str }
end
strict = Puppet[:strict]
unless strict == :off
if strict == :error
raise Puppet::ParseError.new(msg, resource.file, resource.line)
else
msg += Puppet::Util::Errors.error_location_with_space(resource.file, resource.line)
Puppet.warning(msg)
end
end
end
# Some of these might fail, but they'll fail in the way we want.
resource.parameters.each do |_name, param|
override_parameter(param)
end
end
def name
self[:name] || self.title
end
# A temporary occasion, until I get paths in the scopes figured out.
alias path to_s
# Define a parameter in our resource.
# if we ever receive a parameter named 'tag', set
# the resource tags with its value.
def set_parameter(param, value = nil)
if ! param.is_a?(Puppet::Parser::Resource::Param)
param = param.name if param.is_a?(Puppet::Pops::Resource::Param)
param = Puppet::Parser::Resource::Param.new(
:name => param, :value => value, :source => self.source
)
end
tag(*param.value) if param.name == :tag
# And store it in our parameter hash.
@parameters[param.name] = param
end
alias []= set_parameter
def to_hash
parse_title.merge(@parameters.reduce({}) do |result, (_, param)|
value = param.value
value = (:undef == value) ? nil : value
unless value.nil?
case param.name
when :before, :subscribe, :notify, :require
if value.is_a?(Array)
value = value.flatten.reject {|v| v.nil? || :undef == v }
end
result[param.name] = value
else
result[param.name] = value
end
end
result
end)
end
# Convert this resource to a RAL resource.
def to_ral
copy_as_resource.to_ral
end
# Answers if this resource is tagged with at least one of the tags given in downcased string form.
#
# The method is a faster variant of the tagged? method that does no conversion of its
# arguments.
#
# The match takes into account the tags that a resource will inherit from its container
# but have not been set yet.
# It does *not* take tags set via resource defaults as these will *never* be set on
# the resource itself since all resources always have tags that are automatically
# assigned.
#
# @param tag_array [Array[String]] list tags to look for
# @return [Boolean] true if this instance is tagged with at least one of the provided tags
#
def raw_tagged?(tag_array)
super || ((scope_resource = scope.resource) && !scope_resource.equal?(self) && scope_resource.raw_tagged?(tag_array))
end
def offset
nil
end
def pos
nil
end
private
def add_scope_tags
scope_resource = scope.resource
unless scope_resource.nil? || scope_resource.equal?(self)
merge_tags_from(scope_resource)
end
end
def replace_sensitive_data
parameters.keys.each do |name|
param = parameters[name]
if param.value.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
@sensitive_parameters << name
parameters[name] = Puppet::Parser::Resource::Param.from_param(param, param.value.unwrap)
end
end
end
# Accept a parameter from an override.
def override_parameter(param)
# This can happen if the override is defining a new parameter, rather
# than replacing an existing one.
current = @parameters[param.name]
(set_parameter(param) and return) unless current
# Parameter is already set - if overriding with a default - simply ignore the setting of the default value
return if scope.is_default?(type, param.name, param.value)
# The parameter is already set. Fail if they're not allowed to override it.
unless param.source.child_of?(current.source) || param.source.equal?(current.source) && scope.is_default?(type, param.name, current.value)
error_location_str = Puppet::Util::Errors.error_location(current.file, current.line)
msg = if current.source.to_s == ''
if error_location_str.empty?
_("Parameter '%{name}' is already set on %{resource}; cannot redefine") %
{ name: param.name, resource: ref }
else
_("Parameter '%{name}' is already set on %{resource} at %{error_location}; cannot redefine") %
{ name: param.name, resource: ref, error_location: error_location_str }
end
else
if error_location_str.empty?
_("Parameter '%{name}' is already set on %{resource} by %{source}; cannot redefine") %
{ name: param.name, resource: ref, source: current.source.to_s }
else
_("Parameter '%{name}' is already set on %{resource} by %{source} at %{error_location}; cannot redefine") %
{ name: param.name, resource: ref, source: current.source.to_s, error_location: error_location_str }
end
end
raise Puppet::ParseError.new(msg, param.file, param.line)
end
# If we've gotten this far, we're allowed to override.
# Merge with previous value, if the parameter was generated with the +>
# syntax. It's important that we use a copy of the new param instance
# here, not the old one, and not the original new one, so that the source
# is registered correctly for later overrides but the values aren't
# implicitly shared when multiple resources are overridden at once (see
# ticket #3556).
if param.add
param = param.dup
param.value = [current.value, param.value].flatten
end
set_parameter(param)
end
# Make sure the resource's parameters are all valid for the type.
def validate
if builtin_type?
begin
@parameters.each { |name, _value| validate_parameter(name) }
rescue => detail
self.fail Puppet::ParseError, detail.to_s + " on #{self}", detail
end
else
resource_type.validate_resource(self)
end
end
def extract_parameters(params)
params.each do |param|
# Don't set the same parameter twice
self.fail Puppet::ParseError, _("Duplicate parameter '%{param}' for on %{resource}") % { param: param.name, resource: self } if @parameters[param.name]
set_parameter(param)
end
end
end
puppet-8.4.0/lib/puppet/parser/functions/ 0000755 0052762 0001160 00000000000 14552052637 020330 5 ustar jenkins jenkins puppet-8.4.0/lib/puppet/parser/functions/versioncmp.rb 0000644 0052762 0001160 00000001303 14552052437 023035 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../../puppet/util/package'
Puppet::Parser::Functions::newfunction( :versioncmp, :type => :rvalue, :arity => 2, :doc =>
"Compares two version numbers.
Prototype:
\$result = versioncmp(a, b)
Where a and b are arbitrary version strings.
This function returns:
* `1` if version a is greater than version b
* `0` if the versions are equal
* `-1` if version a is less than version b
Example:
if versioncmp('2.6-1', '2.4.5') > 0 {
notice('2.6-1 is > than 2.4.5')
}
This function uses the same version comparison algorithm used by Puppet's
`package` type.
") do |args|
return Puppet::Util::Package.versioncmp(args[0], args[1])
end
puppet-8.4.0/lib/puppet/parser/functions/hiera_hash.rb 0000644 0052762 0001160 00000010051 14552052437 022743 0 ustar jenkins jenkins # frozen_string_literal: true
require 'hiera_puppet'
module Puppet::Parser::Functions
newfunction(
:hiera_hash,
:type => :rvalue,
:arity => -2,
:doc => <<~DOC
Finds all matches of a key throughout the hierarchy and returns them in a merged hash.
If any of the matched hashes share keys, the final hash uses the value from the
highest priority match. This is called a
[hash merge lookup](https://puppet.com/docs/hiera/latest/lookup_types.html#hash-merge).
The merge strategy is determined by Hiera's
[`:merge_behavior`](https://puppet.com/docs/hiera/latest/configuring.html#mergebehavior)
setting.
The `hiera_hash` function takes up to three arguments, in this order:
1. A string key that Hiera searches for in the hierarchy. **Required**.
2. An optional default value to return if Hiera doesn't find anything matching the key.
* If this argument isn't provided and this function results in a lookup failure, Puppet
fails with a compilation error.
3. The optional name of an arbitrary
[hierarchy level](https://puppet.com/docs/hiera/latest/hierarchy.html) to insert at the
top of the hierarchy. This lets you temporarily modify the hierarchy for a single lookup.
* If Hiera doesn't find a matching key in the overriding hierarchy level, it continues
searching the rest of the hierarchy.
**Example**: Using `hiera_hash`
~~~ yaml
# Assuming hiera.yaml
# :hierarchy:
# - web01.example.com
# - common
# Assuming common.yaml:
# users:
# regular:
# 'cdouglas': 'Carrie Douglas'
# Assuming web01.example.com.yaml:
# users:
# administrators:
# 'aberry': 'Amy Berry'
~~~
~~~ puppet
# Assuming we are not web01.example.com:
$allusers = hiera_hash('users', undef)
# $allusers contains {regular => {"cdouglas" => "Carrie Douglas"},
# administrators => {"aberry" => "Amy Berry"}}
~~~
You can optionally generate the default value with a
[lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html) that
takes one parameter.
**Example**: Using `hiera_hash` with a lambda
~~~ puppet
# Assuming the same Hiera data as the previous example:
$allusers = hiera_hash('users') | $key | { "Key \'${key}\' not found" }
# $allusers contains {regular => {"cdouglas" => "Carrie Douglas"},
# administrators => {"aberry" => "Amy Berry"}}
# If hiera_hash couldn't match its key, it would return the lambda result,
# "Key 'users' not found".
~~~
`hiera_hash` expects that all values returned will be hashes. If any of the values
found in the data sources are strings or arrays, Puppet raises a type mismatch error.
`hiera_hash` is deprecated in favor of using `lookup` and will be removed in 6.0.0.
See https://puppet.com/docs/puppet/#{Puppet.minor_version}/deprecated_language.html.
Replace the calls as follows:
| from | to |
| ---- | ---|
| hiera_hash($key) | lookup($key, { 'merge' => 'hash' }) |
| hiera_hash($key, $default) | lookup($key, { 'default_value' => $default, 'merge' => 'hash' }) |
| hiera_hash($key, $default, $level) | override level not supported |
Note that calls using the 'override level' option are not directly supported by 'lookup' and the produced
result must be post processed to get exactly the same result, for example using simple hash/array `+` or
with calls to stdlib's `deep_merge` function depending on kind of hiera call and setting of merge in hiera.yaml.
See
[the documentation](https://puppet.com/docs/hiera/latest/puppet.html#hiera-lookup-functions)
for more information about Hiera lookup functions.
- Since 4.0.0
DOC
) do |*_args|
Error.is4x('hiera_hash')
end
end
puppet-8.4.0/lib/puppet/parser/functions/binary_file.rb 0000644 0052762 0001160 00000001552 14552052437 023141 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:binary_file,
:type => :rvalue,
:arity => 1,
:doc => <<~DOC
Loads a binary file from a module or file system and returns its contents as a Binary.
The argument to this function should be a `/`
reference, which will load `` from a module's `files`
directory. (For example, the reference `mysql/mysqltuner.pl` will load the
file `/mysql/files/mysqltuner.pl`.)
This function also accepts an absolute file path that allows reading
binary file content from anywhere on disk.
An error is raised if the given file does not exists.
To search for the existence of files, use the `find_file()` function.
- since 4.8.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('binary_file')
end
puppet-8.4.0/lib/puppet/parser/functions/fqdn_rand.rb 0000644 0052762 0001160 00000004250 14552052437 022610 0 ustar jenkins jenkins # frozen_string_literal: true
require 'digest/md5'
require 'digest/sha2'
Puppet::Parser::Functions::newfunction(:fqdn_rand, :arity => -2, :type => :rvalue, :doc =>
"Usage: `fqdn_rand(MAX, [SEED], [DOWNCASE])`. MAX is required and must be a positive
integer; SEED is optional and may be any number or string; DOWNCASE is optional
and should be a boolean true or false.
Generates a random Integer number greater than or equal to 0 and less than MAX,
combining the `$fqdn` fact and the value of SEED for repeatable randomness.
(That is, each node will get a different random number from this function, but
a given node's result will be the same every time unless its hostname changes.) If
DOWNCASE is true, then the `fqdn` fact will be downcased when computing the value
so that the result is not sensitive to the case of the `fqdn` fact.
This function is usually used for spacing out runs of resource-intensive cron
tasks that run on many nodes, which could cause a thundering herd or degrade
other services if they all fire at once. Adding a SEED can be useful when you
have more than one such task and need several unrelated random numbers per
node. (For example, `fqdn_rand(30)`, `fqdn_rand(30, 'expensive job 1')`, and
`fqdn_rand(30, 'expensive job 2')` will produce totally different numbers.)") do |args|
max = args.shift.to_i
initial_seed = args.shift
downcase = !!args.shift
fqdn = self['facts'].dig('networking', 'fqdn')
fqdn = fqdn.downcase if downcase
# Puppet 5.4's fqdn_rand function produces a different value than earlier versions
# for the same set of inputs.
# This causes problems because the values are often written into service configuration files.
# When they change, services get notified and restart.
# Restoring previous fqdn_rand behavior of calculating its seed value using MD5
# when running on a non-FIPS enabled platform and only using SHA256 on FIPS enabled
# platforms.
if Puppet::Util::Platform.fips_enabled?
seed = Digest::SHA256.hexdigest([fqdn,max,initial_seed].join(':')).hex
else
seed = Digest::MD5.hexdigest([fqdn,max,initial_seed].join(':')).hex
end
Puppet::Util.deterministic_rand_int(seed,max)
end
puppet-8.4.0/lib/puppet/parser/functions/hiera.rb 0000644 0052762 0001160 00000007670 14552052437 021755 0 ustar jenkins jenkins # frozen_string_literal: true
require 'hiera_puppet'
module Puppet::Parser::Functions
newfunction(
:hiera,
:type => :rvalue,
:arity => -2,
:doc => <<~DOC
Performs a standard priority lookup of the hierarchy and returns the most specific value
for a given key. The returned value can be any type of data.
The function takes up to three arguments, in this order:
1. A string key that Hiera searches for in the hierarchy. **Required**.
2. An optional default value to return if Hiera doesn't find anything matching the key.
* If this argument isn't provided and this function results in a lookup failure, Puppet
fails with a compilation error.
3. The optional name of an arbitrary
[hierarchy level](https://puppet.com/docs/hiera/latest/hierarchy.html) to insert at the
top of the hierarchy. This lets you temporarily modify the hierarchy for a single lookup.
* If Hiera doesn't find a matching key in the overriding hierarchy level, it continues
searching the rest of the hierarchy.
The `hiera` function does **not** find all matches throughout a hierarchy, instead
returining the first specific value starting at the top of the hierarchy. To search
throughout a hierarchy, use the `hiera_array` or `hiera_hash` functions.
**Example**: Using `hiera`
~~~ yaml
# Assuming hiera.yaml
# :hierarchy:
# - web01.example.com
# - common
# Assuming web01.example.com.yaml:
# users:
# - "Amy Barry"
# - "Carrie Douglas"
# Assuming common.yaml:
users:
admins:
- "Edith Franklin"
- "Ginny Hamilton"
regular:
- "Iris Jackson"
- "Kelly Lambert"
~~~
~~~ puppet
# Assuming we are not web01.example.com:
$users = hiera('users', undef)
# $users contains {admins => ["Edith Franklin", "Ginny Hamilton"],
# regular => ["Iris Jackson", "Kelly Lambert"]}
~~~
You can optionally generate the default value with a
[lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html) that
takes one parameter.
**Example**: Using `hiera` with a lambda
~~~ puppet
# Assuming the same Hiera data as the previous example:
$users = hiera('users') | $key | { "Key \'${key}\' not found" }
# $users contains {admins => ["Edith Franklin", "Ginny Hamilton"],
# regular => ["Iris Jackson", "Kelly Lambert"]}
# If hiera couldn't match its key, it would return the lambda result,
# "Key 'users' not found".
~~~
The returned value's data type depends on the types of the results. In the example
above, Hiera matches the 'users' key and returns it as a hash.
The `hiera` function is deprecated in favor of using `lookup` and will be removed in 6.0.0.
See https://puppet.com/docs/puppet/#{Puppet.minor_version}/deprecated_language.html.
Replace the calls as follows:
| from | to |
| ---- | ---|
| hiera($key) | lookup($key) |
| hiera($key, $default) | lookup($key, { 'default_value' => $default }) |
| hiera($key, $default, $level) | override level not supported |
Note that calls using the 'override level' option are not directly supported by 'lookup' and the produced
result must be post processed to get exactly the same result, for example using simple hash/array `+` or
with calls to stdlib's `deep_merge` function depending on kind of hiera call and setting of merge in hiera.yaml.
See
[the documentation](https://puppet.com/docs/hiera/latest/puppet.html#hiera-lookup-functions)
for more information about Hiera lookup functions.
- Since 4.0.0
DOC
) do |*_args|
Error.is4x('hiera')
end
end
puppet-8.4.0/lib/puppet/parser/functions/create_resources.rb 0000644 0052762 0001160 00000010563 14552052437 024215 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(:create_resources, :arity => -3, :doc => <<-'ENDHEREDOC') do |args|
Converts a hash into a set of resources and adds them to the catalog.
**Note**: Use this function selectively. It's generally better to write resources in
[Puppet](https://puppet.com/docs/puppet/latest/lang_resources.html), as
resources created with `create_resource` are difficult to read and troubleshoot.
This function takes two mandatory arguments: a resource type, and a hash describing
a set of resources. The hash should be in the form `{title => {parameters} }`:
# A hash of user resources:
$myusers = {
'nick' => { uid => '1330',
gid => allstaff,
groups => ['developers', 'operations', 'release'], },
'dan' => { uid => '1308',
gid => allstaff,
groups => ['developers', 'prosvc', 'release'], },
}
create_resources(user, $myusers)
A third, optional parameter may be given, also as a hash:
$defaults = {
'ensure' => present,
'provider' => 'ldap',
}
create_resources(user, $myusers, $defaults)
The values given on the third argument are added to the parameters of each resource
present in the set given on the second argument. If a parameter is present on both
the second and third arguments, the one on the second argument takes precedence.
This function can be used to create defined resources and classes, as well
as native resources.
Virtual and Exported resources may be created by prefixing the type name
with @ or @@ respectively. For example, the $myusers hash may be exported
in the following manner:
create_resources("@@user", $myusers)
The $myusers may be declared as virtual resources using:
create_resources("@user", $myusers)
Note that `create_resources` filters out parameter values that are `undef` so that normal
data binding and Puppet default value expressions are considered (in that order) for the
final value of a parameter (just as when setting a parameter to `undef` in a Puppet language
resource declaration).
ENDHEREDOC
if Puppet[:tasks]
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
Puppet::Pops::Issues::CATALOG_OPERATION_NOT_SUPPORTED_WHEN_SCRIPTING,
{:operation => 'create_resources'})
end
raise ArgumentError, (_("create_resources(): wrong number of arguments (%{count}; must be 2 or 3)") % { count: args.length }) if args.length > 3
raise ArgumentError, (_('create_resources(): second argument must be a hash')) unless args[1].is_a?(Hash)
if args.length == 3
raise ArgumentError, (_('create_resources(): third argument, if provided, must be a hash')) unless args[2].is_a?(Hash)
end
type, instances, defaults = args
defaults ||= {}
type_name = type.sub(/^@{1,2}/, '').downcase
# Get file/line information from the Puppet stack (where call comes from in Puppet source)
# If relayed via other Puppet functions in ruby that do not nest their calls, the source position
# will be in the original Puppet source.
#
file, line = Puppet::Pops::PuppetStack.top_of_stack
if type.start_with? '@@'
exported = true
virtual = true
elsif type.start_with? '@'
virtual = true
end
if type_name == 'class' && (exported || virtual)
# cannot find current evaluator, so use another
evaluator = Puppet::Pops::Parser::EvaluatingParser.new.evaluator
# optionally fails depending on configured severity of issue
evaluator.runtime_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
end
instances.map do |title, params|
# Add support for iteration if title is an array
resource_titles = title.is_a?(Array) ? title : [title]
Puppet::Pops::Evaluator::Runtime3ResourceSupport.create_resources(
file, line,
self,
virtual, exported,
type_name,
resource_titles,
defaults.merge(params).map do |name, value|
value = nil if value == :undef
Puppet::Parser::Resource::Param.new(
:name => name,
:value => value, # wide open to various data types, must be correct
:source => self.source, # TODO: support :line => line, :file => file,
:add => false
)
end.compact
)
end.flatten.compact
end
puppet-8.4.0/lib/puppet/parser/functions/next.rb 0000644 0052762 0001160 00000002717 14552052437 021640 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:next,
:arity => -2,
:doc => <<~DOC
Immediately returns the given optional value from a block (lambda), function, class body or user defined type body.
If a value is not given, an `undef` value is returned. This function does not return to the immediate caller.
The signal produced to return a value bubbles up through
the call stack until reaching a code block (lambda), function, class definition or
definition of a user defined type at which point the value given to the function will
be produced as the result of that body of code. An error is raised
if the signal to return a value reaches the end of the call stack.
**Example:** Using `next` in `each`
```puppet
$data = [1,2,3]
$data.each |$x| { if $x == 2 { next() } notice $x }
```
Would notice the values `1` and `3`
**Example:** Using `next` to produce a value
If logic consists of deeply nested conditionals it may be complicated to get out of the innermost conditional.
A call to `next` can then simplify the logic. This example however, only shows the principle.
```puppet
$data = [1,2,3]
notice $data.map |$x| { if $x == 2 { next($x*100) }; $x*10 }
```
Would notice the value `[10, 200, 30]`
* Also see functions `return` and `break`
* Since 4.8.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('next')
end
puppet-8.4.0/lib/puppet/parser/functions/inline_epp.rb 0000644 0052762 0001160 00000004353 14552052437 023002 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(:inline_epp, :type => :rvalue, :arity => -2, :doc =>
"Evaluates an Embedded Puppet (EPP) template string and returns the rendered
text result as a String.
`inline_epp('', )`
The first argument to this function should be a string containing an EPP
template. In most cases, the last argument is optional; if used, it should be a
[hash](https://puppet.com/docs/puppet/latest/lang_data_hash.html) that contains parameters to
pass to the template.
- See the [template](https://puppet.com/docs/puppet/latest/lang_template.html) documentation
for general template usage information.
- See the [EPP syntax](https://puppet.com/docs/puppet/latest/lang_template_epp.html)
documentation for examples of EPP.
For example, to evaluate an inline EPP template and pass it the `docroot` and
`virtual_docroot` parameters, call the `inline_epp` function like this:
`inline_epp('docroot: <%= $docroot %> Virtual docroot: <%= $virtual_docroot %>',
{ 'docroot' => '/var/www/html', 'virtual_docroot' => '/var/www/example' })`
Puppet produces a syntax error if you pass more parameters than are declared in
the template's parameter tag. When passing parameters to a template that
contains a parameter tag, use the same names as the tag's declared parameters.
Parameters are required only if they are declared in the called template's
parameter tag without default values. Puppet produces an error if the
`inline_epp` function fails to pass any required parameter.
An inline EPP template should be written as a single-quoted string or
[heredoc](https://puppet.com/docs/puppet/latest/lang_data_string.html#heredocs).
A double-quoted string is subject to expression interpolation before the string
is parsed as an EPP template.
For example, to evaluate an inline EPP template using a heredoc, call the
`inline_epp` function like this:
~~~ puppet
# Outputs 'Hello given argument planet!'
inline_epp(@(END), { x => 'given argument' })
<%- | $x, $y = planet | -%>
Hello <%= $x %> <%= $y %>!
END
~~~
- Since 3.5
- Requires [future parser](https://puppet.com/docs/puppet/3.8/experiments_future.html) in Puppet 3.5 to 3.8") do |_arguments|
Puppet::Parser::Functions::Error.is4x('inline_epp')
end
puppet-8.4.0/lib/puppet/parser/functions/sha1.rb 0000644 0052762 0001160 00000000360 14552052437 021506 0 ustar jenkins jenkins # frozen_string_literal: true
require 'digest/sha1'
Puppet::Parser::Functions::newfunction(:sha1, :type => :rvalue, :arity => 1, :doc => "Returns a SHA1 hash value from a provided string.") do |args|
Digest::SHA1.hexdigest(args[0])
end
puppet-8.4.0/lib/puppet/parser/functions/with.rb 0000644 0052762 0001160 00000001666 14552052437 021637 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:with,
:type => :rvalue,
:arity => -1,
:doc => <<~DOC
Call a [lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html)
with the given arguments and return the result. Since a lambda's scope is
local to the lambda, you can use the `with` function to create private blocks
of code within a class using variables whose values cannot be accessed outside
of the lambda.
**Example**: Using `with`
~~~ puppet
# Concatenate three strings into a single string formatted as a list.
$fruit = with("apples", "oranges", "bananas") |$x, $y, $z| {
"${x}, ${y}, and ${z}"
}
$check_var = $x
# $fruit contains "apples, oranges, and bananas"
# $check_var is undefined, as the value of $x is local to the lambda.
~~~
- Since 4.0.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('with')
end
puppet-8.4.0/lib/puppet/parser/functions/shellquote.rb 0000644 0052762 0001160 00000004644 14552052437 023050 0 ustar jenkins jenkins # frozen_string_literal: true
# Copyright (C) 2009 Thomas Bellman
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THOMAS BELLMAN BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of Thomas Bellman shall
# not be used in advertising or otherwise to promote the sale, use or
# other dealings in this Software without prior written authorization
# from Thomas Bellman.
Puppet::Parser::Functions.newfunction(:shellquote, :type => :rvalue, :arity => -1, :doc => "\
Quote and concatenate arguments for use in Bourne shell.
Each argument is quoted separately, and then all are concatenated
with spaces. If an argument is an array, the elements of that
array is interpolated within the rest of the arguments; this makes
it possible to have an array of arguments and pass that array to
shellquote instead of having to specify each argument
individually in the call.
") \
do |args|
safe = 'a-zA-Z0-9@%_+=:,./-' # Safe unquoted
dangerous = '!"`$\\' # Unsafe inside double quotes
result = []
args.flatten.each do |word|
if word.length != 0 and word.count(safe) == word.length
result << word
elsif word.count(dangerous) == 0
result << ('"' + word + '"')
elsif word.count("'") == 0
result << ("'" + word + "'")
else
r = '"'
word.each_byte do |c|
r += "\\" if dangerous.include?(c.chr)
r += c.chr
end
r += '"'
result << r
end
end
return result.join(" ")
end
puppet-8.4.0/lib/puppet/parser/functions/require.rb 0000644 0052762 0001160 00000003204 14552052437 022326 0 ustar jenkins jenkins # frozen_string_literal: true
# Requires the specified classes
Puppet::Parser::Functions::newfunction(
:require,
:arity => -2,
:doc => "Evaluate one or more classes, adding the required class as a dependency.
The relationship metaparameters work well for specifying relationships
between individual resources, but they can be clumsy for specifying
relationships between classes. This function is a superset of the
'include' function, adding a class relationship so that the requiring
class depends on the required class.
Warning: using require in place of include can lead to unwanted dependency cycles.
For instance the following manifest, with 'require' instead of 'include' would produce a nasty dependence cycle, because notify imposes a before between File[/foo] and Service[foo]:
class myservice {
service { foo: ensure => running }
}
class otherstuff {
include myservice
file { '/foo': notify => Service[foo] }
}
Note that this function only works with clients 0.25 and later, and it will
fail if used with earlier clients.
You must use the class's full name;
relative names are not allowed. In addition to names in string form,
you may also directly use Class and Resource Type values that are produced when evaluating
resource and relationship expressions.
- Since 4.0.0 Class and Resource types, absolute names
- Since 4.7.0 Returns an Array[Type[Class]] with references to the required classes
") do |classes|
call_function('require', classes)
Puppet.warn_once('deprecations', '3xfunction#require', _("Calling function_require via the Scope class is deprecated. Use Scope#call_function instead"))
end
puppet-8.4.0/lib/puppet/parser/functions/return.rb 0000644 0052762 0001160 00000005651 14552052437 022201 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:return,
:arity => -2,
:doc => <<~DOC
Immediately returns the given optional value from a function, class body or user defined type body.
If a value is not given, an `undef` value is returned. This function does not return to the immediate caller.
If this function is called from within a lambda, the return action is from the scope of the
function containing the lambda (top scope), not the function accepting the lambda (local scope).
The signal produced to return a value bubbles up through
the call stack until reaching a function, class definition or
definition of a user defined type at which point the value given to the function will
be produced as the result of that body of code. An error is raised
if the signal to return a value reaches the end of the call stack.
**Example:** Using `return`
```puppet
function example($x) {
# handle trivial cases first for better readability of
# what follows
if $x == undef or $x == [] or $x == '' {
return false
}
# complex logic to determine if value is true
true
}
notice example([]) # would notice false
notice example(42) # would notice true
```
**Example:** Using `return` in a class
```puppet
class example($x) {
# handle trivial cases first for better readability of
# what follows
if $x == undef or $x == [] or $x == '' {
# Do some default configuration of this class
notice 'foo'
return()
}
# complex logic configuring the class if something more interesting
# was given in $x
notice 'bar'
}
```
When used like this:
```puppet
class { example: x => [] }
```
The code would notice `'foo'`, but not `'bar'`.
When used like this:
```puppet
class { example: x => [some_value] }
```
The code would notice `'bar'` but not `'foo'`
Note that the returned value is ignored if used in a class or user defined type.
**Example:** Using `return` in a lambda
```puppet
# Concatenate three strings into a single string formatted as a list.
function getFruit() {
with("apples", "oranges", "bananas") |$x, $y, $z| {
return("${x}, ${y}, and ${z}")
}
notice "not reached"
}
$fruit = getFruit()
notice $fruit
# The output contains "apples, oranges, and bananas".
# "not reached" is not output because the function returns its value within the
# calling function's scope, which stops processing the calling function before
# the `notice "not reached"` statement.
# Using `return()` outside of a calling function results in an error.
```
* Also see functions `return` and `break`
* Since 4.8.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('return')
end
puppet-8.4.0/lib/puppet/parser/functions/sha256.rb 0000644 0052762 0001160 00000000366 14552052437 021670 0 ustar jenkins jenkins # frozen_string_literal: true
require 'digest/sha2'
Puppet::Parser::Functions::newfunction(:sha256, :type => :rvalue, :arity => 1, :doc => "Returns a SHA256 hash value from a provided string.") do |args|
Digest::SHA256.hexdigest(args[0])
end
puppet-8.4.0/lib/puppet/parser/functions/then.rb 0000644 0052762 0001160 00000005271 14552052437 021616 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:then,
:type => :rvalue,
:arity => -2,
:doc => <<~DOC
Call a [lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html)
with the given argument unless the argument is undef. Return `undef` if argument is
`undef`, and otherwise the result of giving the argument to the lambda.
This is useful to process a sequence of operations where an intermediate
result may be `undef` (which makes the entire sequence `undef`).
The `then` function is especially useful with the function `dig` which
performs in a similar way "digging out" a value in a complex structure.
**Example:** Using `dig` and `then`
```puppet
$data = {a => { b => [{x => 10, y => 20}, {x => 100, y => 200}]}}
notice $data.dig(a, b, 1, x).then |$x| { $x * 2 }
```
Would notice the value 200
Contrast this with:
```puppet
$data = {a => { b => [{x => 10, y => 20}, {ex => 100, why => 200}]}}
notice $data.dig(a, b, 1, x).then |$x| { $x * 2 }
```
Which would notice `undef` since the last lookup of 'x' results in `undef` which
is returned (without calling the lambda given to the `then` function).
As a result there is no need for conditional logic or a temporary (non local)
variable as the result is now either the wanted value (`x`) multiplied
by 2 or `undef`.
Calls to `then` can be chained. In the next example, a structure is using an offset based on
using 1 as the index to the first element (instead of 0 which is used in the language).
We are not sure if user input actually contains an index at all, or if it is
outside the range of available names.args.
**Example:** Chaining calls to the `then` function
```puppet
# Names to choose from
$names = ['Ringo', 'Paul', 'George', 'John']
# Structure where 'beatle 2' is wanted (but where the number refers
# to 'Paul' because input comes from a source using 1 for the first
# element).
$data = ['singer', { beatle => 2 }]
$picked = assert_type(String,
# the data we are interested in is the second in the array,
# a hash, where we want the value of the key 'beatle'
$data.dig(1, 'beatle')
# and we want the index in $names before the given index
.then |$x| { $names[$x-1] }
# so we can construct a string with that beatle's name
.then |$x| { "Picked Beatle '${x}'" }
)
```
Would notice "Picked Beatle 'Paul'", and would raise an error if the result
was not a String.
* Since 4.5.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('then')
end
puppet-8.4.0/lib/puppet/parser/functions/new.rb 0000644 0052762 0001160 00000113075 14552052437 021453 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:new,
:type => :rvalue,
:arity => -1,
:doc => <<~DOC
Creates a new instance/object of a given data type.
This function makes it possible to create new instances of
concrete data types. If a block is given it is called with the
just created instance as an argument.
Calling this function is equivalent to directly
calling the data type:
**Example:** `new` and calling type directly are equivalent
```puppet
$a = Integer.new("42")
$b = Integer("42")
```
These would both convert the string `"42"` to the decimal value `42`.
**Example:** arguments by position or by name
```puppet
$a = Integer.new("42", 8)
$b = Integer({from => "42", radix => 8})
```
This would convert the octal (radix 8) number `"42"` in string form
to the decimal value `34`.
The new function supports two ways of giving the arguments:
* by name (using a hash with property to value mapping)
* by position (as regular arguments)
Note that it is not possible to create new instances of
some abstract data types (for example `Variant`). The data type `Optional[T]` is an
exception as it will create an instance of `T` or `undef` if the
value to convert is `undef`.
The arguments that can be given is determined by the data type.
> An assertion is always made that the produced value complies with the given type constraints.
**Example:** data type constraints are checked
```puppet
Integer[0].new("-100")
```
Would fail with an assertion error (since value is less than 0).
The following sections show the arguments and conversion rules
per data type built into the Puppet Type System.
### Conversion to Optional[T] and NotUndef[T]
Conversion to these data types is the same as a conversion to the type argument `T`.
In the case of `Optional[T]` it is accepted that the argument to convert may be `undef`.
It is however not acceptable to give other arguments (than `undef`) that cannot be
converted to `T`.
### Conversion to Integer
A new `Integer` can be created from `Integer`, `Float`, `Boolean`, and `String` values.
For conversion from `String` it is possible to specify the radix (base).
```puppet
type Radix = Variant[Default, Integer[2,2], Integer[8,8], Integer[10,10], Integer[16,16]]
function Integer.new(
String $value,
Radix $radix = 10,
Boolean $abs = false
)
function Integer.new(
Variant[Numeric, Boolean] $value,
Boolean $abs = false
)
```
* When converting from `String` the default radix is 10.
* If radix is not specified an attempt is made to detect the radix from the start of the string:
* `0b` or `0B` is taken as radix 2.
* `0x` or `0X` is taken as radix 16.
* `0` as radix 8.
* All others are decimal.
* Conversion from `String` accepts an optional sign in the string.
* For hexadecimal (radix 16) conversion an optional leading "0x", or "0X" is accepted.
* For octal (radix 8) an optional leading "0" is accepted.
* For binary (radix 2) an optional leading "0b" or "0B" is accepted.
* When `radix` is set to `default`, the conversion is based on the leading.
characters in the string. A leading "0" for radix 8, a leading "0x", or "0X" for
radix 16, and leading "0b" or "0B" for binary.
* Conversion from `Boolean` results in 0 for `false` and 1 for `true`.
* Conversion from `Integer`, `Float`, and `Boolean` ignores the radix.
* `Float` value fractions are truncated (no rounding).
* When `abs` is set to `true`, the result will be an absolute integer.
Examples - Converting to Integer:
```puppet
$a_number = Integer("0xFF", 16) # results in 255
$a_number = Integer("010") # results in 8
$a_number = Integer("010", 10) # results in 10
$a_number = Integer(true) # results in 1
$a_number = Integer(-38, 10, true) # results in 38
```
### Conversion to Float
A new `Float` can be created from `Integer`, `Float`, `Boolean`, and `String` values.
For conversion from `String` both float and integer formats are supported.
```puppet
function Float.new(
Variant[Numeric, Boolean, String] $value,
Boolean $abs = true
)
```
* For an integer, the floating point fraction of `.0` is added to the value.
* A `Boolean` `true` is converted to 1.0, and a `false` to 0.0
* In `String` format, integer prefixes for hex and binary are understood (but not octal since
floating point in string format may start with a '0').
* When `abs` is set to `true`, the result will be an absolute floating point value.
### Conversion to Numeric
A new `Integer` or `Float` can be created from `Integer`, `Float`, `Boolean` and
`String` values.
```puppet
function Numeric.new(
Variant[Numeric, Boolean, String] $value,
Boolean $abs = true
)
```
* If the value has a decimal period, or if given in scientific notation
(e/E), the result is a `Float`, otherwise the value is an `Integer`. The
conversion from `String` always uses a radix based on the prefix of the string.
* Conversion from `Boolean` results in 0 for `false` and 1 for `true`.
* When `abs` is set to `true`, the result will be an absolute `Float`or `Integer` value.
Examples - Converting to Numeric
```puppet
$a_number = Numeric(true) # results in 1
$a_number = Numeric("0xFF") # results in 255
$a_number = Numeric("010") # results in 8
$a_number = Numeric("3.14") # results in 3.14 (a float)
$a_number = Numeric(-42.3, true) # results in 42.3
$a_number = Numeric(-42, true) # results in 42
```
### Conversion to Timespan
A new `Timespan` can be created from `Integer`, `Float`, `String`, and `Hash` values. Several variants of the constructor are provided.
#### Timespan from seconds
When a Float is used, the decimal part represents fractions of a second.
```puppet
function Timespan.new(
Variant[Float, Integer] $value
)
```
#### Timespan from days, hours, minutes, seconds, and fractions of a second
The arguments can be passed separately in which case the first four, days, hours, minutes, and seconds are mandatory and the rest are optional.
All values may overflow and/or be negative. The internal 128-bit nano-second integer is calculated as:
```
(((((days * 24 + hours) * 60 + minutes) * 60 + seconds) * 1000 + milliseconds) * 1000 + microseconds) * 1000 + nanoseconds
```
```puppet
function Timespan.new(
Integer $days, Integer $hours, Integer $minutes, Integer $seconds,
Integer $milliseconds = 0, Integer $microseconds = 0, Integer $nanoseconds = 0
)
```
or, all arguments can be passed as a `Hash`, in which case all entries are optional:
```puppet
function Timespan.new(
Struct[{
Optional[negative] => Boolean,
Optional[days] => Integer,
Optional[hours] => Integer,
Optional[minutes] => Integer,
Optional[seconds] => Integer,
Optional[milliseconds] => Integer,
Optional[microseconds] => Integer,
Optional[nanoseconds] => Integer
}] $hash
)
```
#### Timespan from String and format directive patterns
The first argument is parsed using the format optionally passed as a string or array of strings. When an array is used, an attempt
will be made to parse the string using the first entry and then with each entry in succession until parsing succeeds. If the second
argument is omitted, an array of default formats will be used.
An exception is raised when no format was able to parse the given string.
```puppet
function Timespan.new(
String $string, Variant[String[2],Array[String[2], 1]] $format = )
)
```
the arguments may also be passed as a `Hash`:
```puppet
function Timespan.new(
Struct[{
string => String[1],
Optional[format] => Variant[String[2],Array[String[2], 1]]
}] $hash
)
```
The directive consists of a percent (%) character, zero or more flags, optional minimum field width and
a conversion specifier as follows:
```
%[Flags][Width]Conversion
```
##### Flags:
| Flag | Meaning
| ---- | ---------------
| - | Don't pad numerical output
| _ | Use spaces for padding
| 0 | Use zeros for padding
##### Format directives:
| Format | Meaning |
| ------ | ------- |
| D | Number of Days |
| H | Hour of the day, 24-hour clock |
| M | Minute of the hour (00..59) |
| S | Second of the minute (00..59) |
| L | Millisecond of the second (000..999) |
| N | Fractional seconds digits |
The format directive that represents the highest magnitude in the format will be allowed to
overflow. I.e. if no "%D" is used but a "%H" is present, then the hours may be more than 23.
The default array contains the following patterns:
```
['%D-%H:%M:%S', '%D-%H:%M', '%H:%M:%S', '%H:%M']
```
Examples - Converting to Timespan
```puppet
$duration = Timespan(13.5) # 13 seconds and 500 milliseconds
$duration = Timespan({days=>4}) # 4 days
$duration = Timespan(4, 0, 0, 2) # 4 days and 2 seconds
$duration = Timespan('13:20') # 13 hours and 20 minutes (using default pattern)
$duration = Timespan('10:03.5', '%M:%S.%L') # 10 minutes, 3 seconds, and 5 milli-seconds
$duration = Timespan('10:03.5', '%M:%S.%N') # 10 minutes, 3 seconds, and 5 nano-seconds
```
### Conversion to Timestamp
A new `Timestamp` can be created from `Integer`, `Float`, `String`, and `Hash` values. Several variants of the constructor are provided.
#### Timestamp from seconds since epoch (1970-01-01 00:00:00 UTC)
When a Float is used, the decimal part represents fractions of a second.
```puppet
function Timestamp.new(
Variant[Float, Integer] $value
)
```
#### Timestamp from String and patterns consisting of format directives
The first argument is parsed using the format optionally passed as a string or array of strings. When an array is used, an attempt
will be made to parse the string using the first entry and then with each entry in succession until parsing succeeds. If the second
argument is omitted, an array of default formats will be used.
A third optional timezone argument can be provided. The first argument will then be parsed as if it represents a local time in that
timezone. The timezone can be any timezone that is recognized when using the '%z' or '%Z' formats, or the word 'current', in which
case the current timezone of the evaluating process will be used. The timezone argument is case insensitive.
The default timezone, when no argument is provided, or when using the keyword `default`, is 'UTC'.
It is illegal to provide a timezone argument other than `default` in combination with a format that contains '%z' or '%Z' since that
would introduce an ambiguity as to which timezone to use. The one extracted from the string, or the one provided as an argument.
An exception is raised when no format was able to parse the given string.
```puppet
function Timestamp.new(
String $string,
Variant[String[2],Array[String[2], 1]] $format = ,
String $timezone = default)
)
```
the arguments may also be passed as a `Hash`:
```puppet
function Timestamp.new(
Struct[{
string => String[1],
Optional[format] => Variant[String[2],Array[String[2], 1]],
Optional[timezone] => String[1]
}] $hash
)
```
The directive consists of a percent (%) character, zero or more flags, optional minimum field width and
a conversion specifier as follows:
```
%[Flags][Width]Conversion
```
##### Flags:
| Flag | Meaning
| ---- | ---------------
| - | Don't pad numerical output
| _ | Use spaces for padding
| 0 | Use zeros for padding
| # | Change names to upper-case or change case of am/pm
| ^ | Use uppercase
| : | Use colons for %z
##### Format directives (names and padding can be altered using flags):
**Date (Year, Month, Day):**
| Format | Meaning |
| ------ | ------- |
| Y | Year with century, zero-padded to at least 4 digits |
| C | year / 100 (rounded down such as 20 in 2009) |
| y | year % 100 (00..99) |
| m | Month of the year, zero-padded (01..12) |
| B | The full month name ("January") |
| b | The abbreviated month name ("Jan") |
| h | Equivalent to %b |
| d | Day of the month, zero-padded (01..31) |
| e | Day of the month, blank-padded ( 1..31) |
| j | Day of the year (001..366) |
**Time (Hour, Minute, Second, Subsecond):**
| Format | Meaning |
| ------ | ------- |
| H | Hour of the day, 24-hour clock, zero-padded (00..23) |
| k | Hour of the day, 24-hour clock, blank-padded ( 0..23) |
| I | Hour of the day, 12-hour clock, zero-padded (01..12) |
| l | Hour of the day, 12-hour clock, blank-padded ( 1..12) |
| P | Meridian indicator, lowercase ("am" or "pm") |
| p | Meridian indicator, uppercase ("AM" or "PM") |
| M | Minute of the hour (00..59) |
| S | Second of the minute (00..60) |
| L | Millisecond of the second (000..999). Digits under millisecond are truncated to not produce 1000 |
| N | Fractional seconds digits, default is 9 digits (nanosecond). Digits under a specified width are truncated to avoid carry up |
**Time (Hour, Minute, Second, Subsecond):**
| Format | Meaning |
| ------ | ------- |
| z | Time zone as hour and minute offset from UTC (e.g. +0900) |
| :z | hour and minute offset from UTC with a colon (e.g. +09:00) |
| ::z | hour, minute and second offset from UTC (e.g. +09:00:00) |
| Z | Abbreviated time zone name or similar information. (OS dependent) |
**Weekday:**
| Format | Meaning |
| ------ | ------- |
| A | The full weekday name ("Sunday") |
| a | The abbreviated name ("Sun") |
| u | Day of the week (Monday is 1, 1..7) |
| w | Day of the week (Sunday is 0, 0..6) |
**ISO 8601 week-based year and week number:**
The first week of YYYY starts with a Monday and includes YYYY-01-04.
The days in the year before the first week are in the last week of
the previous year.
| Format | Meaning |
| ------ | ------- |
| G | The week-based year |
| g | The last 2 digits of the week-based year (00..99) |
| V | Week number of the week-based year (01..53) |
**Week number:**
The first week of YYYY that starts with a Sunday or Monday (according to %U
or %W). The days in the year before the first week are in week 0.
| Format | Meaning |
| ------ | ------- |
| U | Week number of the year. The week starts with Sunday. (00..53) |
| W | Week number of the year. The week starts with Monday. (00..53) |
**Seconds since the Epoch:**
| Format | Meaning |
| s | Number of seconds since 1970-01-01 00:00:00 UTC. |
**Literal string:**
| Format | Meaning |
| ------ | ------- |
| n | Newline character (\n) |
| t | Tab character (\t) |
| % | Literal "%" character |
**Combination:**
| Format | Meaning |
| ------ | ------- |
| c | date and time (%a %b %e %T %Y) |
| D | Date (%m/%d/%y) |
| F | The ISO 8601 date format (%Y-%m-%d) |
| v | VMS date (%e-%^b-%4Y) |
| x | Same as %D |
| X | Same as %T |
| r | 12-hour time (%I:%M:%S %p) |
| R | 24-hour time (%H:%M) |
| T | 24-hour time (%H:%M:%S) |
The default array contains the following patterns:
When a timezone argument (other than `default`) is explicitly provided:
```
['%FT%T.L', '%FT%T', '%F']
```
otherwise:
```
['%FT%T.%L %Z', '%FT%T %Z', '%F %Z', '%FT%T.L', '%FT%T', '%F']
```
Examples - Converting to Timestamp
```puppet
$ts = Timestamp(1473150899) # 2016-09-06 08:34:59 UTC
$ts = Timestamp({string=>'2015', format=>'%Y'}) # 2015-01-01 00:00:00.000 UTC
$ts = Timestamp('Wed Aug 24 12:13:14 2016', '%c') # 2016-08-24 12:13:14 UTC
$ts = Timestamp('Wed Aug 24 12:13:14 2016 PDT', '%c %Z') # 2016-08-24 19:13:14.000 UTC
$ts = Timestamp('2016-08-24 12:13:14', '%F %T', 'PST') # 2016-08-24 20:13:14.000 UTC
$ts = Timestamp('2016-08-24T12:13:14', default, 'PST') # 2016-08-24 20:13:14.000 UTC
```
### Conversion to Type
A new `Type` can be create from its `String` representation.
**Example:** Creating a type from a string
```puppet
$t = Type.new('Integer[10]')
```
### Conversion to String
Conversion to `String` is the most comprehensive conversion as there are many
use cases where a string representation is wanted. The defaults for the many options
have been chosen with care to be the most basic "value in textual form" representation.
The more advanced forms of formatting are intended to enable writing special purposes formatting
functions in the Puppet language.
A new string can be created from all other data types. The process is performed in
several steps - first the data type of the given value is inferred, then the resulting data type
is used to find the most significant format specified for that data type. And finally,
the found format is used to convert the given value.
The mapping from data type to format is referred to as the *format map*. This map
allows different formatting depending on type.
**Example:** Positive Integers in Hexadecimal prefixed with '0x', negative in Decimal
```puppet
$format_map = {
Integer[default, 0] => "%d",
Integer[1, default] => "%#x"
}
String("-1", $format_map) # produces '-1'
String("10", $format_map) # produces '0xa'
```
A format is specified on the form:
```
%[Flags][Width][.Precision]Format
```
`Width` is the number of characters into which the value should be fitted. This allocated space is
padded if value is shorter. By default it is space padded, and the flag `0` will cause padding with `0`
for numerical formats.
`Precision` is the number of fractional digits to show for floating point, and the maximum characters
included in a string format.
Note that all data type supports the formats `s` and `p` with the meaning "default string representation" and
"default programmatic string representation" (which for example means that a String is quoted in 'p' format).
#### Signatures of String conversion
```puppet
type Format = Pattern[/^%([\s\+\-#0\[\{<\(\|]*)([1-9][0-9]*)?(?:\.([0-9]+))?([a-zA-Z])/]
type ContainerFormat = Struct[{
format => Optional[String],
separator => Optional[String],
separator2 => Optional[String],
string_formats => Hash[Type, Format]
}]
type TypeMap = Hash[Type, Variant[Format, ContainerFormat]]
type Formats = Variant[Default, String[1], TypeMap]
function String.new(
Any $value,
Formats $string_formats
)
```
Where:
* `separator` is the string used to separate entries in an array, or hash (extra space should not be included at
the end), defaults to `","`
* `separator2` is the separator between key and value in a hash entry (space padding should be included as
wanted), defaults to `" => "`.
* `string_formats` is a data type to format map for values contained in arrays and hashes - defaults to `{Any => "%p"}`. Note that
these nested formats are not applicable to data types that are containers; they are always formatted as per the top level
format specification.
**Example:** Simple Conversion to String (using defaults)
```puppet
$str = String(10) # produces '10'
$str = String([10]) # produces '["10"]'
```
**Example:** Simple Conversion to String specifying the format for the given value directly
```puppet
$str = String(10, "%#x") # produces '0x10'
$str = String([10], "%(a") # produces '("10")'
```
**Example:** Specifying type for values contained in an array
```puppet
$formats = {
Array => {
format => '%(a',
string_formats => { Integer => '%#x' }
}
}
$str = String([1,2,3], $formats) # produces '(0x1, 0x2, 0x3)'
```
The given formats are merged with the default formats, and matching of values to convert against format is based on
the specificity of the mapped type; for example, different formats can be used for short and long arrays.
#### Integer to String
| Format | Integer Formats
| ------ | ---------------
| d | Decimal, negative values produces leading '-'.
| x X | Hexadecimal in lower or upper case. Uses ..f/..F for negative values unless + is also used. A `#` adds prefix 0x/0X.
| o | Octal. Uses ..0 for negative values unless `+` is also used. A `#` adds prefix 0.
| b B | Binary with prefix 'b' or 'B'. Uses ..1/..1 for negative values unless `+` is also used.
| c | Numeric value representing a Unicode value, result is a one unicode character string, quoted if alternative flag # is used
| s | Same as d, or d in quotes if alternative flag # is used.
| p | Same as d.
| eEfgGaA | Converts integer to float and formats using the floating point rules.
Defaults to `d`.
#### Float to String
| Format | Float formats
| ------ | -------------
| f | Floating point in non exponential notation.
| e E | Exponential notation with 'e' or 'E'.
| g G | Conditional exponential with 'e' or 'E' if exponent < -4 or >= the precision.
| a A | Hexadecimal exponential form, using 'x'/'X' as prefix and 'p'/'P' before exponent.
| s | Converted to string using format p, then applying string formatting rule, alternate form # quotes result.
| p | Same as f format with minimum significant number of fractional digits, prec has no effect.
| dxXobBc | Converts float to integer and formats using the integer rules.
Defaults to `p`.
#### String to String
| Format | String
| ------ | ------
| s | Unquoted string, verbatim output of control chars.
| p | Programmatic representation - strings are quoted, interior quotes and control chars are escaped.
| C | Each `::` name segment capitalized, quoted if alternative flag `#` is used.
| c | Capitalized string, quoted if alternative flag `#` is used.
| d | Downcased string, quoted if alternative flag `#` is used.
| u | Upcased string, quoted if alternative flag `#` is used.
| t | Trims leading and trailing whitespace from the string, quoted if alternative flag `#` is used.
Defaults to `s` at top level and `p` inside array or hash.
#### Boolean to String
| Format | Boolean Formats
| ---- | -------------------
| t T | String 'true'/'false' or 'True'/'False', first char if alternate form is used (i.e. 't'/'f' or 'T'/'F').
| y Y | String 'yes'/'no', 'Yes'/'No', 'y'/'n' or 'Y'/'N' if alternative flag `#` is used.
| dxXobB | Numeric value 0/1 in accordance with the given format which must be valid integer format.
| eEfgGaA | Numeric value 0.0/1.0 in accordance with the given float format and flags.
| s | String 'true' / 'false'.
| p | String 'true' / 'false'.
#### Regexp to String
| Format | Regexp Formats
| ---- | --------------
| s | No delimiters, quoted if alternative flag `#` is used.
| p | Delimiters `/ /`.
#### Undef to String
| Format | Undef formats
| ------ | -------------
| s | Empty string, or quoted empty string if alternative flag `#` is used.
| p | String 'undef', or quoted '"undef"' if alternative flag `#` is used.
| n | String 'nil', or 'null' if alternative flag `#` is used.
| dxXobB | String 'NaN'.
| eEfgGaA | String 'NaN'.
| v | String 'n/a'.
| V | String 'N/A'.
| u | String 'undef', or 'undefined' if alternative `#` flag is used.
#### Default value to String
| Format | Default formats
| ------ | ---------------
| d D | String 'default' or 'Default', alternative form `#` causes value to be quoted.
| s | Same as d.
| p | Same as d.
#### Binary value to String
| Format | Default formats
| ------ | ---------------
| s | binary as unquoted UTF-8 characters (errors if byte sequence is invalid UTF-8). Alternate form escapes non ascii bytes.
| p | 'Binary("")'
| b | '' - base64 string with newlines inserted
| B | '' - base64 strict string (without newlines inserted)
| u | '' - base64 urlsafe string
| t | 'Binary' - outputs the name of the type only
| T | 'BINARY' - output the name of the type in all caps only
* The alternate form flag `#` will quote the binary or base64 text output.
* The format `%#s` allows invalid UTF-8 characters and outputs all non ascii bytes
as hex escaped characters on the form `\\xHH` where `H` is a hex digit.
* The width and precision values are applied to the text part only in `%p` format.
#### Array & Tuple to String
| Format | Array/Tuple Formats
| ------ | -------------
| a | Formats with `[ ]` delimiters and `,`, alternate form `#` indents nested arrays/hashes.
| s | Same as a.
| p | Same as a.
See "Flags" `<[({\|` for formatting of delimiters, and "Additional parameters for containers; Array and Hash" for
more information about options.
The alternate form flag `#` will cause indentation of nested array or hash containers. If width is also set
it is taken as the maximum allowed length of a sequence of elements (not including delimiters). If this max length
is exceeded, each element will be indented.
#### Hash & Struct to String
| Format | Hash/Struct Formats
| ------ | -------------
| h | Formats with `{ }` delimiters, `,` element separator and ` => ` inner element separator unless overridden by flags.
| s | Same as h.
| p | Same as h.
| a | Converts the hash to an array of [k,v] tuples and formats it using array rule(s).
See "Flags" `<[({\|` for formatting of delimiters, and "Additional parameters for containers; Array and Hash" for
more information about options.
The alternate form flag `#` will format each hash key/value entry indented on a separate line.
#### Type to String
| Format | Array/Tuple Formats
| ------ | -------------
| s | The same as `p`, quoted if alternative flag `#` is used.
| p | Outputs the type in string form as specified by the Puppet Language.
#### Flags
| Flag | Effect
| ------ | ------
| (space) | A space instead of `+` for numeric output (`-` is shown), for containers skips delimiters.
| # | Alternate format; prefix 0x/0x, 0 (octal) and 0b/0B for binary, Floats force decimal '.'. For g/G keep trailing 0.
| + | Show sign +/- depending on value's sign, changes x, X, o, b, B format to not use 2's complement form.
| - | Left justify the value in the given width.
| 0 | Pad with 0 instead of space for widths larger than value.
| <[({\| | Defines an enclosing pair <> [] () {} or \| \| when used with a container type.
### Conversion to Boolean
Accepts a single value as argument:
* Float 0.0 is `false`, all other float values are `true`
* Integer 0 is `false`, all other integer values are `true`
* Strings
* `true` if 'true', 'yes', 'y' (case independent compare)
* `false` if 'false', 'no', 'n' (case independent compare)
* Boolean is already boolean and is simply returned
### Conversion to Array and Tuple
When given a single value as argument:
* A non empty `Hash` is converted to an array matching `Array[Tuple[Any,Any], 1]`.
* An empty `Hash` becomes an empty array.
* An `Array` is simply returned.
* An `Iterable[T]` is turned into an array of `T` instances.
* A `Binary` is converted to an `Array[Integer[0,255]]` of byte values
When given a second Boolean argument:
* if `true`, a value that is not already an array is returned as a one element array.
* if `false`, (the default), converts the first argument as shown above.
**Example:** Ensuring value is an array
```puppet
$arr = Array($value, true)
```
Conversion to a `Tuple` works exactly as conversion to an `Array`, only that the constructed array is
asserted against the given tuple type.
### Conversion to Hash and Struct
Accepts a single value as argument:
* An empty `Array` becomes an empty `Hash`
* An `Array` matching `Array[Tuple[Any,Any], 1]` is converted to a hash where each tuple describes a key/value entry
* An `Array` with an even number of entries is interpreted as `[key1, val1, key2, val2, ...]`
* An `Iterable` is turned into an `Array` and then converted to hash as per the array rules
* A `Hash` is simply returned
Alternatively, a tree can be constructed by giving two values; an array of tuples on the form `[path, value]`
(where the `path` is the path from the root of a tree, and `value` the value at that position in the tree), and
either the option `'tree'` (do not convert arrays to hashes except the top level), or
`'hash_tree'` (convert all arrays to hashes).
The tree/hash_tree forms of Hash creation are suited for transforming the result of an iteration
using `tree_each` and subsequent filtering or mapping.
**Example:** Mapping a hash tree
Mapping an arbitrary structure in a way that keeps the structure, but where some values are replaced
can be done by using the `tree_each` function, mapping, and then constructing a new Hash from the result:
```puppet
# A hash tree with 'water' at different locations
$h = { a => { b => { x => 'water'}}, b => { y => 'water'} }
# a helper function that turns water into wine
function make_wine($x) { if $x == 'water' { 'wine' } else { $x } }
# create a flattened tree with water turned into wine
$flat_tree = $h.tree_each.map |$entry| { [$entry[0], make_wine($entry[1])] }
# create a new Hash and log it
notice Hash($flat_tree, 'hash_tree')
```
Would notice the hash `{a => {b => {x => wine}}, b => {y => wine}}`
Conversion to a `Struct` works exactly as conversion to a `Hash`, only that the constructed hash is
asserted against the given struct type.
### Conversion to a Regexp
A `String` can be converted into a `Regexp`
**Example**: Converting a String into a Regexp
```puppet
$s = '[a-z]+\.com'
$r = Regexp($s)
if('foo.com' =~ $r) {
...
}
```
### Creating a SemVer
A SemVer object represents a single [Semantic Version](http://semver.org/).
It can be created from a String, individual values for its parts, or a hash specifying the value per part.
See the specification at [semver.org](http://semver.org/) for the meaning of the SemVer's parts.
The signatures are:
```puppet
type PositiveInteger = Integer[0,default]
type SemVerQualifier = Pattern[/\A(?[0-9A-Za-z-]+)(?:\.\g)*\Z/]
type SemVerString = String[1]
type SemVerHash =Struct[{
major => PositiveInteger,
minor => PositiveInteger,
patch => PositiveInteger,
Optional[prerelease] => SemVerQualifier,
Optional[build] => SemVerQualifier
}]
function SemVer.new(SemVerString $str)
function SemVer.new(
PositiveInteger $major
PositiveInteger $minor
PositiveInteger $patch
Optional[SemVerQualifier] $prerelease = undef
Optional[SemVerQualifier] $build = undef
)
function SemVer.new(SemVerHash $hash_args)
```
**Examples:** SemVer and SemVerRange usage
```puppet
# As a type, SemVer can describe disjunct ranges which versions can be
# matched against - here the type is constructed with two
# SemVerRange objects.
#
$t = SemVer[
SemVerRange('>=1.0.0 <2.0.0'),
SemVerRange('>=3.0.0 <4.0.0')
]
notice(SemVer('1.2.3') =~ $t) # true
notice(SemVer('2.3.4') =~ $t) # false
notice(SemVer('3.4.5') =~ $t) # true
```
### Creating a SemVerRange
A `SemVerRange` object represents a range of `SemVer`. It can be created from
a `String`, or from two `SemVer` instances, where either end can be given as
a literal `default` to indicate infinity. The string format of a `SemVerRange` is specified by
the [Semantic Version Range Grammar](https://github.com/npm/node-semver#ranges).
> Use of the comparator sets described in the grammar (joining with `||`) is not supported.
The signatures are:
```puppet
type SemVerRangeString = String[1]
type SemVerRangeHash = Struct[{
min => Variant[Default, SemVer],
Optional[max] => Variant[Default, SemVer],
Optional[exclude_max] => Boolean
}]
function SemVerRange.new(
SemVerRangeString $semver_range_string
)
function SemVerRange.new(
Variant[Default,SemVer] $min
Variant[Default,SemVer] $max
Optional[Boolean] $exclude_max = undef
)
function SemVerRange.new(
SemVerRangeHash $semver_range_hash
)
```
For examples of `SemVerRange` use, see "Creating a SemVer".
### Creating a Binary
A `Binary` object represents a sequence of bytes and it can be created from a String in Base64 format,
an Array containing byte values. A Binary can also be created from a Hash containing the value to convert to
a `Binary`.
The signatures are:
```puppet
type ByteInteger = Integer[0,255]
type Base64Format = Enum["%b", "%u", "%B", "%s"]
type StringHash = Struct[{value => String, "format" => Optional[Base64Format]}]
type ArrayHash = Struct[{value => Array[ByteInteger]}]
type BinaryArgsHash = Variant[StringHash, ArrayHash]
function Binary.new(
String $base64_str,
Optional[Base64Format] $format
)
function Binary.new(
Array[ByteInteger] $byte_array
}
# Same as for String, or for Array, but where arguments are given in a Hash.
function Binary.new(BinaryArgsHash $hash_args)
```
The formats have the following meaning:
| format | explanation |
| ---- | ---- |
| B | The data is in base64 strict encoding
| u | The data is in URL safe base64 encoding
| b | The data is in base64 encoding, padding as required by base64 strict, is added by default
| s | The data is a puppet string. The string must be valid UTF-8, or convertible to UTF-8 or an error is raised.
| r | (Ruby Raw) the byte sequence in the given string is used verbatim irrespective of possible encoding errors
* The default format is `%B`.
* Note that the format `%r` should be used sparingly, or not at all. It exists for backwards compatibility reasons when someone receiving
a string from some function and that string should be treated as Binary. Such code should be changed to return a Binary instead of a String.
**Examples:** Creating a Binary
```puppet
# create the binary content "abc"
$a = Binary('YWJj')
# create the binary content from content in a module's file
$b = binary_file('mymodule/mypicture.jpg')
```
* Since 4.5.0
* Binary type since 4.8.0
Creating an instance of a `Type` using the `Init` type.
-------
The type `Init[T]` describes a value that can be used when instantiating a type. When used as the first argument in a call to `new`, it
will dispatch the call to its contained type and optionally augment the parameter list with additional arguments.
**Example:** Creating an instance of Integer using Init[Integer]
```puppet
# The following declaration
$x = Init[Integer].new('128')
# is exactly the same as
$x = Integer.new('128')
```
or, with base 16 and using implicit new
```puppet
# The following declaration
$x = Init[Integer,16]('80')
# is exactly the same as
$x = Integer('80', 16)
```
**Example:** Creating an instance of String using a predefined format
```puppet
$fmt = Init[String,'%#x']
notice($fmt(256)) # will notice '0x100'
```
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('new')
end
puppet-8.4.0/lib/puppet/parser/functions/regsubst.rb 0000644 0052762 0001160 00000005672 14552052437 022523 0 ustar jenkins jenkins # frozen_string_literal: true
# Copyright (C) 2009 Thomas Bellman
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THOMAS BELLMAN BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of Thomas Bellman shall
# not be used in advertising or otherwise to promote the sale, use or
# other dealings in this Software without prior written authorization
# from Thomas Bellman.
module Puppet::Parser::Functions
newfunction(
:regsubst, :type => :rvalue,
:arity => -4,
:doc => "
Perform regexp replacement on a string or array of strings.
* *Parameters* (in order):
* _target_ The string or array of strings to operate on. If an array, the replacement will be performed on each of the elements in the array, and the return value will be an array.
* _regexp_ The regular expression matching the target string. If you want it anchored at the start and or end of the string, you must do that with ^ and $ yourself.
* _replacement_ Replacement string. Can contain backreferences to what was matched using \\0 (whole match), \\1 (first set of parentheses), and so on.
* _flags_ Optional. String of single letter flags for how the regexp is interpreted:
- *E* Extended regexps
- *I* Ignore case in regexps
- *M* Multiline regexps
- *G* Global replacement; all occurrences of the regexp in each target string will be replaced. Without this, only the first occurrence will be replaced.
* _encoding_ Optional. How to handle multibyte characters. A single-character string with the following values:
- *N* None
- *E* EUC
- *S* SJIS
- *U* UTF-8
* *Examples*
Get the third octet from the node's IP address:
$i3 = regsubst($ipaddress,'^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$','\\3')
Put angle brackets around each octet in the node's IP address:
$x = regsubst($ipaddress, '([0-9]+)', '<\\1>', 'G')
") do |_args|
Error.is4x('regsubst')
end
end
puppet-8.4.0/lib/puppet/parser/functions/scanf.rb 0000644 0052762 0001160 00000002361 14552052437 021747 0 ustar jenkins jenkins # frozen_string_literal: true
require 'scanf'
Puppet::Parser::Functions::newfunction(
:scanf,
:type => :rvalue,
:arity => 2,
:doc => <<~DOC
Scans a string and returns an array of one or more converted values based on the given format string.
See the documentation of Ruby's String#scanf method for details about the supported formats (which
are similar but not identical to the formats used in Puppet's `sprintf` function.)
This function takes two mandatory arguments: the first is the string to convert, and the second is
the format string. The result of the scan is an array, with each successfully scanned and transformed value.
The scanning stops if a scan is unsuccessful, and the scanned result up to that point is returned. If there
was no successful scan, the result is an empty array.
```puppet
"42".scanf("%i")
```
You can also optionally pass a lambda to scanf, to do additional validation or processing.
```puppet
"42".scanf("%i") |$x| {
unless $x[0] =~ Integer {
fail "Expected a well formed integer value, got '$x[0]'"
}
$x[0]
}
```
- Since 4.0.0
DOC
) do |args|
data = args[0]
format = args[1]
data.scanf(format)
end
puppet-8.4.0/lib/puppet/parser/functions/hiera_array.rb 0000644 0052762 0001160 00000007300 14552052437 023141 0 ustar jenkins jenkins # frozen_string_literal: true
require 'hiera_puppet'
module Puppet::Parser::Functions
newfunction(
:hiera_array,
:type => :rvalue,
:arity => -2,
:doc => <<~DOC
Finds all matches of a key throughout the hierarchy and returns them as a single flattened
array of unique values. If any of the matched values are arrays, they're flattened and
included in the results. This is called an
[array merge lookup](https://puppet.com/docs/hiera/latest/lookup_types.html#array-merge).
The `hiera_array` function takes up to three arguments, in this order:
1. A string key that Hiera searches for in the hierarchy. **Required**.
2. An optional default value to return if Hiera doesn't find anything matching the key.
* If this argument isn't provided and this function results in a lookup failure, Puppet
fails with a compilation error.
3. The optional name of an arbitrary
[hierarchy level](https://puppet.com/docs/hiera/latest/hierarchy.html) to insert at the
top of the hierarchy. This lets you temporarily modify the hierarchy for a single lookup.
* If Hiera doesn't find a matching key in the overriding hierarchy level, it continues
searching the rest of the hierarchy.
**Example**: Using `hiera_array`
~~~ yaml
# Assuming hiera.yaml
# :hierarchy:
# - web01.example.com
# - common
# Assuming common.yaml:
# users:
# - 'cdouglas = regular'
# - 'efranklin = regular'
# Assuming web01.example.com.yaml:
# users: 'abarry = admin'
~~~
~~~ puppet
$allusers = hiera_array('users', undef)
# $allusers contains ["cdouglas = regular", "efranklin = regular", "abarry = admin"].
~~~
You can optionally generate the default value with a
[lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html) that
takes one parameter.
**Example**: Using `hiera_array` with a lambda
~~~ puppet
# Assuming the same Hiera data as the previous example:
$allusers = hiera_array('users') | $key | { "Key \'${key}\' not found" }
# $allusers contains ["cdouglas = regular", "efranklin = regular", "abarry = admin"].
# If hiera_array couldn't match its key, it would return the lambda result,
# "Key 'users' not found".
~~~
`hiera_array` expects that all values returned will be strings or arrays. If any matched
value is a hash, Puppet raises a type mismatch error.
`hiera_array` is deprecated in favor of using `lookup` and will be removed in 6.0.0.
See https://puppet.com/docs/puppet/#{Puppet.minor_version}/deprecated_language.html.
Replace the calls as follows:
| from | to |
| ---- | ---|
| hiera_array($key) | lookup($key, { 'merge' => 'unique' }) |
| hiera_array($key, $default) | lookup($key, { 'default_value' => $default, 'merge' => 'unique' }) |
| hiera_array($key, $default, $level) | override level not supported |
Note that calls using the 'override level' option are not directly supported by 'lookup' and the produced
result must be post processed to get exactly the same result, for example using simple hash/array `+` or
with calls to stdlib's `deep_merge` function depending on kind of hiera call and setting of merge in hiera.yaml.
See
[the documentation](https://puppet.com/docs/hiera/latest/puppet.html#hiera-lookup-functions)
for more information about Hiera lookup functions.
- Since 4.0.0
DOC
) do |*_args|
Error.is4x('hiera_array')
end
end
puppet-8.4.0/lib/puppet/parser/functions/inline_template.rb 0000644 0052762 0001160 00000002001 14552052437 024015 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(:inline_template, :type => :rvalue, :arity => -2, :doc =>
"Evaluate a template string and return its value. See
[the templating docs](https://puppet.com/docs/puppet/latest/lang_template.html) for
more information. Note that if multiple template strings are specified, their
output is all concatenated and returned as the output of the function.") do |vals|
if Puppet[:tasks]
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
Puppet::Pops::Issues::FEATURE_NOT_SUPPORTED_WHEN_SCRIPTING,
{:feature => 'ERB inline_template'})
end
require 'erb'
vals.collect do |string|
# Use a wrapper, so the template can't get access to the full
# Scope object.
wrapper = Puppet::Parser::TemplateWrapper.new(self)
begin
wrapper.result(string)
rescue => detail
raise Puppet::ParseError, _("Failed to parse inline template: %{detail}") % { detail: detail }, detail.backtrace
end
end.join("")
end
puppet-8.4.0/lib/puppet/parser/functions/digest.rb 0000644 0052762 0001160 00000000603 14552052437 022131 0 ustar jenkins jenkins # frozen_string_literal: true
require_relative '../../../puppet/util/checksums'
Puppet::Parser::Functions::newfunction(:digest, :type => :rvalue, :arity => 1, :doc => "Returns a hash value from a provided string using the digest_algorithm setting from the Puppet config file.") do |args|
algo = Puppet[:digest_algorithm]
Puppet::Util::Checksums.method(algo.intern).call args[0]
end
puppet-8.4.0/lib/puppet/parser/functions/reduce.rb 0000644 0052762 0001160 00000012105 14552052437 022121 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:reduce,
:type => :rvalue,
:arity => -3,
:doc => <<~DOC
Applies a [lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html)
to every value in a data structure from the first argument, carrying over the returned
value of each iteration, and returns the result of the lambda's final iteration. This
lets you create a new value or data structure by combining values from the first
argument's data structure.
This function takes two mandatory arguments, in this order:
1. An array or hash the function will iterate over.
2. A lambda, which the function calls for each element in the first argument. It takes
two mandatory parameters:
1. A memo value that is overwritten after each iteration with the iteration's result.
2. A second value that is overwritten after each iteration with the next value in the
function's first argument.
**Example**: Using the `reduce` function
`$data.reduce |$memo, $value| { ... }`
or
`reduce($data) |$memo, $value| { ... }`
You can also pass an optional "start memo" value as an argument, such as `start` below:
`$data.reduce(start) |$memo, $value| { ... }`
or
`reduce($data, start) |$memo, $value| { ... }`
When the first argument (`$data` in the above example) is an array, Puppet passes each
of the data structure's values in turn to the lambda's parameters. When the first
argument is a hash, Puppet converts each of the hash's values to an array in the form
`[key, value]`.
If you pass a start memo value, Puppet executes the lambda with the provided memo value
and the data structure's first value. Otherwise, Puppet passes the structure's first two
values to the lambda.
Puppet calls the lambda for each of the data structure's remaining values. For each
call, it passes the result of the previous call as the first parameter ($memo in the
above examples) and the next value from the data structure as the second parameter
($value).
If the structure has one value, Puppet returns the value and does not call the lambda.
**Example**: Using the `reduce` function
~~~ puppet
# Reduce the array $data, returning the sum of all values in the array.
$data = [1, 2, 3]
$sum = $data.reduce |$memo, $value| { $memo + $value }
# $sum contains 6
# Reduce the array $data, returning the sum of a start memo value and all values in the
# array.
$data = [1, 2, 3]
$sum = $data.reduce(4) |$memo, $value| { $memo + $value }
# $sum contains 10
# Reduce the hash $data, returning the sum of all values and concatenated string of all
# keys.
$data = {a => 1, b => 2, c => 3}
$combine = $data.reduce |$memo, $value| {
$string = "${memo[0]}${value[0]}"
$number = $memo[1] + $value[1]
[$string, $number]
}
# $combine contains [abc, 6]
~~~
**Example**: Using the `reduce` function with a start memo and two-parameter lambda
~~~ puppet
# Reduce the array $data, returning the sum of all values in the array and starting
# with $memo set to an arbitrary value instead of $data's first value.
$data = [1, 2, 3]
$sum = $data.reduce(4) |$memo, $value| { $memo + $value }
# At the start of the lambda's first iteration, $memo contains 4 and $value contains 1.
# After all iterations, $sum contains 10.
# Reduce the hash $data, returning the sum of all values and concatenated string of
# all keys, and starting with $memo set to an arbitrary array instead of $data's first
# key-value pair.
$data = {a => 1, b => 2, c => 3}
$combine = $data.reduce( [d, 4] ) |$memo, $value| {
$string = "${memo[0]}${value[0]}"
$number = $memo[1] + $value[1]
[$string, $number]
}
# At the start of the lambda's first iteration, $memo contains [d, 4] and $value
# contains [a, 1].
# $combine contains [dabc, 10]
~~~
**Example**: Using the `reduce` function to reduce a hash of hashes
~~~ puppet
# Reduce a hash of hashes $data, merging defaults into the inner hashes.
$data = {
'connection1' => {
'username' => 'user1',
'password' => 'pass1',
},
'connection_name2' => {
'username' => 'user2',
'password' => 'pass2',
},
}
$defaults = {
'maxActive' => '20',
'maxWait' => '10000',
'username' => 'defaultuser',
'password' => 'defaultpass',
}
$merged = $data.reduce( {} ) |$memo, $x| {
$memo + { $x[0] => $defaults + $data[$x[0]] }
}
# At the start of the lambda's first iteration, $memo is set to {}, and $x is set to
# the first [key, value] tuple. The key in $data is, therefore, given by $x[0]. In
# subsequent rounds, $memo retains the value returned by the expression, i.e.
# $memo + { $x[0] => $defaults + $data[$x[0]] }.
~~~
- Since 4.0.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('reduce')
end
puppet-8.4.0/lib/puppet/parser/functions/lookup.rb 0000644 0052762 0001160 00000015267 14552052437 022177 0 ustar jenkins jenkins # frozen_string_literal: true
module Puppet::Parser::Functions
newfunction(:lookup, :type => :rvalue, :arity => -2, :doc => <<~'ENDHEREDOC') do |_args|
Uses the Puppet lookup system to retrieve a value for a given key. By default,
this returns the first value found (and fails compilation if no values are
available), but you can configure it to merge multiple values into one, fail
gracefully, and more.
When looking up a key, Puppet will search up to three tiers of data, in the
following order:
1. Hiera.
2. The current environment's data provider.
3. The indicated module's data provider, if the key is of the form
`::`.
#### Arguments
You must provide the name of a key to look up, and can optionally provide other
arguments. You can combine these arguments in the following ways:
* `lookup( , [], [], [] )`
* `lookup( [], )`
* `lookup( as above ) |$key| { # lambda returns a default value }`
Arguments in `[square brackets]` are optional.
The arguments accepted by `lookup` are as follows:
1. `` (string or array) --- The name of the key to look up.
* This can also be an array of keys. If Puppet doesn't find anything for the
first key, it will try again with the subsequent ones, only resorting to a
default value if none of them succeed.
2. `` (data type) --- A
[data type](https://puppet.com/docs/puppet/latest/lang_data_type.html)
that must match the retrieved value; if not, the lookup (and catalog
compilation) will fail. Defaults to `Data` (accepts any normal value).
3. `` (string or hash; see **"Merge Behaviors"** below) ---
Whether (and how) to combine multiple values. If present, this overrides any
merge behavior specified in the data sources. Defaults to no value; Puppet will
use merge behavior from the data sources if present, and will otherwise do a
first-found lookup.
4. `` (any normal value) --- If present, `lookup` returns this
when it can't find a normal value. Default values are never merged with found
values. Like a normal value, the default must match the value type. Defaults to
no value; if Puppet can't find a normal value, the lookup (and compilation) will
fail.
5. `` (hash) --- Alternate way to set the arguments above, plus
some less-common extra options. If you pass an options hash, you can't combine
it with any regular arguments (except ``). An options hash can have the
following keys:
* `'name'` --- Same as `` (argument 1). You can pass this as an
argument or in the hash, but not both.
* `'value_type'` --- Same as `` (argument 2).
* `'merge'` --- Same as `` (argument 3).
* `'default_value'` --- Same as `` (argument 4).
* `'default_values_hash'` (hash) --- A hash of lookup keys and default
values. If Puppet can't find a normal value, it will check this hash for the
requested key before giving up. You can combine this with `default_value` or
a lambda, which will be used if the key isn't present in this hash. Defaults
to an empty hash.
* `'override'` (hash) --- A hash of lookup keys and override values. Puppet
will check for the requested key in the overrides hash _first;_ if found, it
returns that value as the _final_ value, ignoring merge behavior. Defaults
to an empty hash.
Finally, `lookup` can take a lambda, which must accept a single parameter.
This is yet another way to set a default value for the lookup; if no results are
found, Puppet will pass the requested key to the lambda and use its result as
the default value.
#### Merge Behaviors
Puppet lookup uses a hierarchy of data sources, and a given key might have
values in multiple sources. By default, Puppet returns the first value it finds,
but it can also continue searching and merge all the values together.
> **Note:** Data sources can use the special `lookup_options` metadata key to
request a specific merge behavior for a key. The `lookup` function will use that
requested behavior unless you explicitly specify one.
The valid merge behaviors are:
* `'first'` --- Returns the first value found, with no merging. Puppet lookup's
default behavior.
* `'unique'` (called "array merge" in classic Hiera) --- Combines any number of
arrays and scalar values to return a merged, flattened array with all duplicate
values removed. The lookup will fail if any hash values are found.
* `'hash'` --- Combines the keys and values of any number of hashes to return a
merged hash. If the same key exists in multiple source hashes, Puppet will use
the value from the highest-priority data source; it won't recursively merge the
values.
* `'deep'` --- Combines the keys and values of any number of hashes to return a
merged hash. If the same key exists in multiple source hashes, Puppet will
recursively merge hash or array values (with duplicate values removed from
arrays). For conflicting scalar values, the highest-priority value will win.
* `{'strategy' => 'first|unique|hash'}` --- Same as the string versions of these
merge behaviors.
* `{'strategy' => 'deep', => , ...}` --- Same as `'deep'`,
but can adjust the merge with additional options. The available options are:
* `'knockout_prefix'` (string or undef) --- A string prefix to indicate a
value should be _removed_ from the final result. Defaults to `undef`, which
disables this feature.
* `'sort_merged_arrays'` (boolean) --- Whether to sort all arrays that are
merged together. Defaults to `false`.
* `'merge_hash_arrays'` (boolean) --- Whether to merge hashes within arrays.
Defaults to `false`.
#### Examples
Look up a key and return the first value found:
lookup('ntp::service_name')
Do a unique merge lookup of class names, then add all of those classes to the
catalog (like `hiera_include`):
lookup('classes', Array[String], 'unique').include
Do a deep hash merge lookup of user data, but let higher priority sources
remove values by prefixing them with `--`:
lookup( { 'name' => 'users',
'merge' => {
'strategy' => 'deep',
'knockout_prefix' => '--',
},
})
ENDHEREDOC
Error.is4x('lookup')
end
end
puppet-8.4.0/lib/puppet/parser/functions/step.rb 0000644 0052762 0001160 00000005340 14552052437 021630 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:step,
:type => :rvalue,
:arity => -1,
:doc => <<~DOC
Provides stepping with given interval over elements in an iterable and optionally runs a
[lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html) for each
element.
This function takes two to three arguments:
1. An 'Iterable' that the function will iterate over.
2. An `Integer` step factor. This must be a positive integer.
3. An optional lambda, which the function calls for each element in the interval. It must
request one parameter.
**Example:** Using the `step` function
```puppet
$data.step() |$parameter| { }
```
or
```puppet
$stepped_data = $data.step()
```
or
```puppet
step($data, ) |$parameter| { }
```
or
```puppet
$stepped_data = step($data, )
```
When no block is given, Puppet returns an `Iterable` that yields the first element and every nth successor
element, from its first argument. This allows functions on iterables to be chained.
When a block is given, Puppet iterates and calls the block with the first element and then with
every nth successor element. It then returns `undef`.
**Example:** Using the `step` function with an array, a step factor, and a one-parameter block
```puppet
# For the array $data, call a block with the first element and then with each 3rd successor element
$data = [1,2,3,4,5,6,7,8]
$data.step(3) |$item| {
notice($item)
}
# Puppet notices the values '1', '4', '7'.
```
When no block is given, Puppet returns a new `Iterable` which allows it to be directly chained into
another function that takes an `Iterable` as an argument.
**Example:** Using the `step` function chained with a `map` function.
```puppet
# For the array $data, return an array, set to the first element and each 5th successor element, in reverse
# order multiplied by 10
$data = Integer[0,20]
$transformed_data = $data.step(5).map |$item| { $item * 10 }
$transformed_data contains [0,50,100,150,200]
```
**Example:** The same example using `step` function chained with a `map` in alternative syntax
```puppet
# For the array $data, return an array, set to the first and each 5th
# successor, in reverse order, multiplied by 10
$data = Integer[0,20]
$transformed_data = map(step($data, 5)) |$item| { $item * 10 }
$transformed_data contains [0,50,100,150,200]
```
* Since 4.4.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('step')
end
puppet-8.4.0/lib/puppet/parser/functions/template.rb 0000644 0052762 0001160 00000003201 14552052437 022462 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(:template, :type => :rvalue, :arity => -2, :doc =>
"Loads an ERB template from a module, evaluates it, and returns the resulting
value as a string.
The argument to this function should be a `/`
reference, which will load `` from a module's `templates`
directory. (For example, the reference `apache/vhost.conf.erb` will load the
file `/apache/templates/vhost.conf.erb`.)
This function can also accept:
* An absolute path, which can load a template file from anywhere on disk.
* Multiple arguments, which will evaluate all of the specified templates and
return their outputs concatenated into a single string.") do |vals|
if Puppet[:tasks]
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
Puppet::Pops::Issues::FEATURE_NOT_SUPPORTED_WHEN_SCRIPTING,
{:feature => 'ERB template'})
end
vals.collect do |file|
# Use a wrapper, so the template can't get access to the full
# Scope object.
debug "Retrieving template #{file}"
wrapper = Puppet::Parser::TemplateWrapper.new(self)
wrapper.file = file
begin
wrapper.result
rescue => detail
info = detail.backtrace.first.split(':')
message = []
message << _("Failed to parse template %{file}:") % { file: file }
message << _(" Filepath: %{file_path}") % { file_path: info[0] }
message << _(" Line: %{line}") % { line: info[1] }
message << _(" Detail: %{detail}") % { detail: detail }
raise Puppet::ParseError, message.join("\n") + "\n"
end
end.join("")
end
puppet-8.4.0/lib/puppet/parser/functions/generate.rb 0000644 0052762 0001160 00000003505 14552052437 022450 0 ustar jenkins jenkins # frozen_string_literal: true
# Runs an external command and returns the results
Puppet::Parser::Functions::newfunction(:generate, :arity => -2, :type => :rvalue,
:doc => "Calls an external command on the Puppet master and returns
the results of the command. Any arguments are passed to the external command as
arguments. If the generator does not exit with return code of 0,
the generator is considered to have failed and a parse error is
thrown. Generators can only have file separators, alphanumerics, dashes,
and periods in them. This function will attempt to protect you from
malicious generator calls (e.g., those with '..' in them), but it can
never be entirely safe. No subshell is used to execute
generators, so all shell metacharacters are passed directly to
the generator, and all metacharacters are returned by the function.
Consider cleaning white space from any string generated.") do |args|
# TRANSLATORS "fully qualified" refers to a fully qualified file system path
raise Puppet::ParseError, _("Generators must be fully qualified") unless Puppet::Util.absolute_path?(args[0])
if Puppet::Util::Platform.windows?
valid = args[0] =~ /^[a-z]:(?:[\/\\][-.~\w]+)+$/i
else
valid = args[0] =~ /^[-\/\w.+]+$/
end
unless valid
raise Puppet::ParseError, _("Generators can only contain alphanumerics, file separators, and dashes")
end
if args[0] =~ /\.\./
raise Puppet::ParseError, _("Can not use generators with '..' in them.")
end
begin
Dir.chdir(File.dirname(args[0])) { Puppet::Util::Execution.execute(args).to_str }
rescue Puppet::ExecutionFailure => detail
raise Puppet::ParseError, _("Failed to execute generator %{generator}: %{detail}") % { generator: args[0], detail: detail }, detail.backtrace
end
end
puppet-8.4.0/lib/puppet/parser/functions/find_file.rb 0000644 0052762 0001160 00000002125 14552052437 022572 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:find_file,
:type => :rvalue,
:arity => -2,
:doc => <<~DOC
Finds an existing file from a module and returns its path.
The argument to this function should be a String as a `/`
reference, which will search for `` relative to a module's `files`
directory. (For example, the reference `mysql/mysqltuner.pl` will search for the
file `/mysql/files/mysqltuner.pl`.)
This function can also accept:
* An absolute String path, which will check for the existence of a file from anywhere on disk.
* Multiple String arguments, which will return the path of the **first** file
found, skipping non existing files.
* An array of string paths, which will return the path of the **first** file
found from the given paths in the array, skipping non existing files.
The function returns `undef` if none of the given paths were found
- since 4.8.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('find_file')
end
puppet-8.4.0/lib/puppet/parser/functions/include.rb 0000644 0052762 0001160 00000003561 14552052437 022303 0 ustar jenkins jenkins # frozen_string_literal: true
# Include the specified classes
Puppet::Parser::Functions::newfunction(:include, :arity => -2, :doc =>
"Declares one or more classes, causing the resources in them to be
evaluated and added to the catalog. Accepts a class name, an array of class
names, or a comma-separated list of class names.
The `include` function can be used multiple times on the same class and will
only declare a given class once. If a class declared with `include` has any
parameters, Puppet will automatically look up values for them in Hiera, using
`::` as the lookup key.
Contrast this behavior with resource-like class declarations
(`class {'name': parameter => 'value',}`), which must be used in only one place
per class and can directly set parameters. You should avoid using both `include`
and resource-like declarations with the same class.
The `include` function does not cause classes to be contained in the class
where they are declared. For that, see the `contain` function. It also
does not create a dependency relationship between the declared class and the
surrounding class; for that, see the `require` function.
You must use the class's full name;
relative names are not allowed. In addition to names in string form,
you may also directly use Class and Resource Type values that are produced by
the future parser's resource and relationship expressions.
- Since < 3.0.0
- Since 4.0.0 support for class and resource type values, absolute names
- Since 4.7.0 returns an Array[Type[Class]] of all included classes
") do |classes|
call_function('include', classes)
# TRANSLATORS "function_include", "Scope", and "Scope#call_function" refer to Puppet internals and should not be translated
Puppet.warn_once('deprecations', '3xfunction#include', _("Calling function_include via the Scope class is deprecated. Use Scope#call_function instead"))
end
puppet-8.4.0/lib/puppet/parser/functions/each.rb 0000644 0052762 0001160 00000007430 14552052437 021557 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:each,
:type => :rvalue,
:arity => -3,
:doc => <<~DOC
Runs a [lambda](https://puppet.com/docs/puppet/latest/lang_lambdas.html)
repeatedly using each value in a data structure, then returns the values unchanged.
This function takes two mandatory arguments, in this order:
1. An array or hash the function will iterate over.
2. A lambda, which the function calls for each element in the first argument. It can
request one or two parameters.
**Example**: Using the `each` function
`$data.each |$parameter| { }`
or
`each($data) |$parameter| { }`
When the first argument (`$data` in the above example) is an array, Puppet passes each
value in turn to the lambda, then returns the original values.
**Example**: Using the `each` function with an array and a one-parameter lambda
~~~ puppet
# For the array $data, run a lambda that creates a resource for each item.
$data = ["routers", "servers", "workstations"]
$data.each |$item| {
notify { $item:
message => $item
}
}
# Puppet creates one resource for each of the three items in $data. Each resource is
# named after the item's value and uses the item's value in a parameter.
~~~
When the first argument is a hash, Puppet passes each key and value pair to the lambda
as an array in the form `[key, value]` and returns the original hash.
**Example**: Using the `each` function with a hash and a one-parameter lambda
~~~ puppet
# For the hash $data, run a lambda using each item as a key-value array that creates a
# resource for each item.
$data = {"rtr" => "Router", "svr" => "Server", "wks" => "Workstation"}
$data.each |$items| {
notify { $items[0]:
message => $items[1]
}
}
# Puppet creates one resource for each of the three items in $data, each named after the
# item's key and containing a parameter using the item's value.
~~~
When the first argument is an array and the lambda has two parameters, Puppet passes the
array's indexes (enumerated from 0) in the first parameter and its values in the second
parameter.
**Example**: Using the `each` function with an array and a two-parameter lambda
~~~ puppet
# For the array $data, run a lambda using each item's index and value that creates a
# resource for each item.
$data = ["routers", "servers", "workstations"]
$data.each |$index, $value| {
notify { $value:
message => $index
}
}
# Puppet creates one resource for each of the three items in $data, each named after the
# item's value and containing a parameter using the item's index.
~~~
When the first argument is a hash, Puppet passes its keys to the first parameter and its
values to the second parameter.
**Example**: Using the `each` function with a hash and a two-parameter lambda
~~~ puppet
# For the hash $data, run a lambda using each item's key and value to create a resource
# for each item.
$data = {"rtr" => "Router", "svr" => "Server", "wks" => "Workstation"}
$data.each |$key, $value| {
notify { $key:
message => $value
}
}
# Puppet creates one resource for each of the three items in $data, each named after the
# item's key and containing a parameter using the item's value.
~~~
For an example that demonstrates how to create multiple `file` resources using `each`,
see the Puppet
[iteration](https://puppet.com/docs/puppet/latest/lang_iteration.html)
documentation.
- Since 4.0.0
DOC
) do |_args|
Puppet::Parser::Functions::Error.is4x('each')
end
puppet-8.4.0/lib/puppet/parser/functions/strftime.rb 0000644 0052762 0001160 00000016111 14552052437 022510 0 ustar jenkins jenkins # frozen_string_literal: true
Puppet::Parser::Functions::newfunction(
:strftime,
:type => :rvalue,
:arity => -3,
:doc => <<~DOC
Formats timestamp or timespan according to the directives in the given format string. The directives begins with a percent (%) character.
Any text not listed as a directive will be passed through to the output string.
A third optional timezone argument can be provided. The first argument will then be formatted to represent a local time in that
timezone. The timezone can be any timezone that is recognized when using the '%z' or '%Z' formats, or the word 'current', in which
case the current timezone of the evaluating process will be used. The timezone argument is case insensitive.
The default timezone, when no argument is provided, or when using the keyword `default`, is 'UTC'.
The directive consists of a percent (%) character, zero or more flags, optional minimum field width and
a conversion specifier as follows:
```
%[Flags][Width]Conversion
```
### Flags that controls padding
| Flag | Meaning
| ---- | ---------------
| - | Don't pad numerical output
| _ | Use spaces for padding
| 0 | Use zeros for padding
### `Timestamp` specific flags
| Flag | Meaning
| ---- | ---------------
| # | Change case
| ^ | Use uppercase
| : | Use colons for %z
### Format directives applicable to `Timestamp` (names and padding can be altered using flags):
**Date (Year, Month, Day):**
| Format | Meaning |
| ------ | ------- |
| Y | Year with century, zero-padded to at least 4 digits |
| C | year / 100 (rounded down such as 20 in 2009) |
| y | year % 100 (00..99) |
| m | Month of the year, zero-padded (01..12) |
| B | The full month name ("January") |
| b | The abbreviated month name ("Jan") |
| h | Equivalent to %b |
| d | Day of the month, zero-padded (01..31) |
| e | Day of the month, blank-padded ( 1..31) |
| j | Day of the year (001..366) |
**Time (Hour, Minute, Second, Subsecond):**
| Format | Meaning |
| ------ | ------- |
| H | Hour of the day, 24-hour clock, zero-padded (00..23) |
| k | Hour of the day, 24-hour clock, blank-padded ( 0..23) |
| I | Hour of the day, 12-hour clock, zero-padded (01..12) |
| l | Hour of the day, 12-hour clock, blank-padded ( 1..12) |
| P | Meridian indicator, lowercase ("am" or "pm") |
| p | Meridian indicator, uppercase ("AM" or "PM") |
| M | Minute of the hour (00..59) |
| S | Second of the minute (00..60) |
| L | Millisecond of the second (000..999). Digits under millisecond are truncated to not produce 1000 |
| N | Fractional seconds digits, default is 9 digits (nanosecond). Digits under a specified width are truncated to avoid carry up |
**Time (Hour, Minute, Second, Subsecond):**
| Format | Meaning |
| ------ | ------- |
| z | Time zone as hour and minute offset from UTC (e.g. +0900) |
| :z | hour and minute offset from UTC with a colon (e.g. +09:00) |
| ::z | hour, minute and second offset from UTC (e.g. +09:00:00) |
| Z | Abbreviated time zone name or similar information. (OS dependent) |
**Weekday:**
| Format | Meaning |
| ------ | ------- |
| A | The full weekday name ("Sunday") |
| a | The abbreviated name ("Sun") |
| u | Day of the week (Monday is 1, 1..7) |
| w | Day of the week (Sunday is 0, 0..6) |
**ISO 8601 week-based year and week number:**
The first week of YYYY starts with a Monday and includes YYYY-01-04.
The days in the year before the first week are in the last week of
the previous year.
| Format | Meaning |
| ------ | ------- |
| G | The week-based year |
| g | The last 2 digits of the week-based year (00..99) |
| V | Week number of the week-based year (01..53) |
**Week number:**
The first week of YYYY that starts with a Sunday or Monday (according to %U
or %W). The days in the year before the first week are in week 0.
| Format | Meaning |
| ------ | ------- |
| U | Week number of the year. The week starts with Sunday. (00..53) |
| W | Week number of the year. The week starts with Monday. (00..53) |
**Seconds since the Epoch:**
| Format | Meaning |
| s | Number of seconds since 1970-01-01 00:00:00 UTC. |
**Literal string:**
| Format | Meaning |
| ------ | ------- |
| n | Newline character (\n) |
| t | Tab character (\t) |
| % | Literal "%" character |
**Combination:**
| Format | Meaning |
| ------ | ------- |
| c | date and time (%a %b %e %T %Y) |
| D | Date (%m/%d/%y) |
| F | The ISO 8601 date format (%Y-%m-%d) |
| v | VMS date (%e-%^b-%4Y) |
| x | Same as %D |
| X | Same as %T |
| r | 12-hour time (%I:%M:%S %p) |
| R | 24-hour time (%H:%M) |
| T | 24-hour time (%H:%M:%S) |
**Example**: Using `strftime` with a `Timestamp`:
~~~ puppet
$timestamp = Timestamp('2016-08-24T12:13:14')
# Notice the timestamp using a format that notices the ISO 8601 date format
notice($timestamp.strftime('%F')) # outputs '2016-08-24'
# Notice the timestamp using a format that notices weekday, month, day, time (as UTC), and year
notice($timestamp.strftime('%c')) # outputs 'Wed Aug 24 12:13:14 2016'
# Notice the timestamp using a specific timezone
notice($timestamp.strftime('%F %T %z', 'PST')) # outputs '2016-08-24 04:13:14 -0800'
# Notice the timestamp using timezone that is current for the evaluating process
notice($timestamp.strftime('%F %T', 'current')) # outputs the timestamp using the timezone for the current process
~~~
### Format directives applicable to `Timespan`:
| Format | Meaning |
| ------ | ------- |
| D | Number of Days |
| H | Hour of the day, 24-hour clock |
| M | Minute of the hour (00..59) |
| S | Second of the minute (00..59) |
| L | Millisecond of the second (000..999). Digits under millisecond are truncated to not produce 1000. |
| N | Fractional seconds digits, default is 9 digits (nanosecond). Digits under a specified length are truncated to avoid carry up |
The format directive that represents the highest magnitude in the format will be allowed to overflow.
I.e. if no "%D" is used but a "%H" is present, then the hours will be more than 23 in case the
timespan reflects more than a day.
**Example**: Using `strftime` with a Timespan and a format
~~~ puppet
$duration = Timespan({ hours => 3, minutes => 20, seconds => 30 })
# Notice the duration using a format that outputs :