summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md41
-rw-r--r--functions/round.pp9
-rw-r--r--lib/puppet/functions/fact.rb58
-rw-r--r--lib/puppet/parser/functions/pw_hash.rb7
-rw-r--r--lib/puppet/provider/file_line/ruby.rb4
-rw-r--r--lib/puppet/type/file_line.rb8
-rw-r--r--spec/aliases/integer_spec.rb2
-rw-r--r--spec/functions/pw_hash_spec.rb8
-rwxr-xr-xspec/functions/round_spec.rb11
-rwxr-xr-xspec/unit/puppet/provider/file_line/ruby_spec.rb18
10 files changed, 163 insertions, 3 deletions
diff --git a/README.md b/README.md
index 6848b92..a8b93ca 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,18 @@ file_line { 'bashrc_proxy':
In the example above, `match` looks for a line beginning with 'export' followed by 'HTTP_PROXY' and replaces it with the value in line.
+Match Example:
+
+ file_line { 'bashrc_proxy':
+ ensure => present,
+ path => '/etc/bashrc',
+ line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ match => '^export\ HTTP_PROXY\=',
+ append_on_no_match => false,
+ }
+
+In this code example, `match` looks for a line beginning with export followed by HTTP_PROXY and replaces it with the value in line. If a match is not found, then no changes are made to the file.
+
Match Example with `ensure => absent`:
```puppet
@@ -899,6 +911,31 @@ userlist:
ensure_resources('user', hiera_hash('userlist'), {'ensure' => 'present'})
```
+#### `fact`
+
+Return the value of a given fact. Supports the use of dot-notation for referring to structured facts. If a fact requested does not exist, returns Undef.
+
+Example usage:
+
+```puppet
+fact('kernel')
+fact('osfamily')
+fact('os.architecture')
+```
+
+Array indexing:
+
+```puppet
+$first_processor = fact('processors.models.0')
+$second_processor = fact('processors.models.1')
+```
+
+Fact containing a "." in the fact name:
+
+```puppet
+fact('vmware."VRA.version"')
+```
+
#### `flatten`
Flattens deeply nested arrays and returns a single flat array as a result.
@@ -1513,6 +1550,10 @@ For example, `reject(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['bbb','ccc']
Reverses the order of a string or array.
+#### `stdlib::round`
+
+ Rounds a number to the nearest integer
+
*Type*: rvalue.
#### `rstrip`
diff --git a/functions/round.pp b/functions/round.pp
new file mode 100644
index 0000000..6bad92d
--- /dev/null
+++ b/functions/round.pp
@@ -0,0 +1,9 @@
+function stdlib::round(
+ Numeric $input,
+) {
+ if $input >= 0 {
+ Integer( $input + 0.5 )
+ } else {
+ Integer( $input - 0.5 )
+ }
+}
diff --git a/lib/puppet/functions/fact.rb b/lib/puppet/functions/fact.rb
new file mode 100644
index 0000000..dfb048b
--- /dev/null
+++ b/lib/puppet/functions/fact.rb
@@ -0,0 +1,58 @@
+# Digs into the facts hash using dot-notation
+#
+# Example usage:
+#
+# fact('osfamily')
+# fact('os.architecture')
+#
+# Array indexing:
+#
+# fact('mountpoints."/dev".options.1')
+#
+# Fact containing a "." in the name:
+#
+# fact('vmware."VRA.version"')
+#
+Puppet::Functions.create_function(:fact) do
+ dispatch :fact do
+ param 'String', :fact_name
+ end
+
+ def to_dot_syntax(array_path)
+ array_path.map do |string|
+ string.include?('.') ? %Q{"#{string}"} : string
+ end.join('.')
+ end
+
+ def fact(fact_name)
+ facts = closure_scope['facts']
+
+ # Transform the dot-notation string into an array of paths to walk. Make
+ # sure to correctly extract double-quoted values containing dots as single
+ # elements in the path.
+ path = fact_name.scan(/([^."]+)|(?:")([^"]+)(?:")/).map {|x| x.compact.first }
+
+ walked_path = []
+ path.reduce(facts) do |d, k|
+ return nil if d.nil? || k.nil?
+
+ case
+ when d.is_a?(Array)
+ begin
+ result = d[Integer(k)]
+ rescue ArgumentError => e
+ Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is an array; cannot index to '#{k}'")
+ result = nil
+ end
+ when d.is_a?(Hash)
+ result = d[k]
+ else
+ Puppet.warning("fact request for #{fact_name} returning nil: '#{to_dot_syntax(walked_path)}' is not a collection; cannot walk to '#{k}'")
+ result = nil
+ end
+
+ walked_path << k
+ result
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/pw_hash.rb b/lib/puppet/parser/functions/pw_hash.rb
index d99ee5b..0deeb3a 100644
--- a/lib/puppet/parser/functions/pw_hash.rb
+++ b/lib/puppet/parser/functions/pw_hash.rb
@@ -27,6 +27,13 @@ Puppet::Parser::Functions::newfunction(
environment contains several different operating systems, ensure that they
are compatible before using this function.") do |args|
raise ArgumentError, "pw_hash(): wrong number of arguments (#{args.size} for 3)" if args.size != 3
+ args.map! do |arg|
+ if arg.is_a? Puppet::Pops::Types::PSensitiveType::Sensitive
+ arg.unwrap
+ else
+ arg
+ end
+ end
raise ArgumentError, "pw_hash(): first argument must be a string" unless args[0].is_a? String or args[0].nil?
raise ArgumentError, "pw_hash(): second argument must be a string" unless args[1].is_a? String
hashes = { 'md5' => '1',
diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb
index 2f6c8ef..16f2709 100644
--- a/lib/puppet/provider/file_line/ruby.rb
+++ b/lib/puppet/provider/file_line/ruby.rb
@@ -12,7 +12,9 @@ Puppet::Type.type(:file_line).provide(:ruby) do
found = lines_count > 0
else
match_count = count_matches(new_match_regex)
- if resource[:replace].to_s == 'true'
+ if resource[:append_on_no_match].to_s == 'false'
+ found = true
+ elsif resource[:replace].to_s == 'true'
found = lines_count > 0 && lines_count == match_count
else
found = match_count > 0
diff --git a/lib/puppet/type/file_line.rb b/lib/puppet/type/file_line.rb
index 3d691bf..b2357b8 100644
--- a/lib/puppet/type/file_line.rb
+++ b/lib/puppet/type/file_line.rb
@@ -58,7 +58,7 @@ Puppet::Type.newtype(:file_line) do
encoding => "iso-8859-1",
}
- Files with special characters that are not valid UTF-8 will give the
+ Files with special characters that are not valid UTF-8 will give the
error message "invalid byte sequence in UTF-8". In this case, determine
the correct file encoding and specify the correct encoding using the
encoding attribute, the value of which needs to be a valid Ruby character
@@ -136,6 +136,12 @@ Puppet::Type.newtype(:file_line) do
defaultto 'UTF-8'
end
+ newparam(:append_on_no_match) do
+ desc 'If true, append line if match is not found. If false, do not append line if a match is not found'
+ newvalues(true, false)
+ defaultto true
+ end
+
# Autorequire the file resource if it's being managed
autorequire(:file) do
self[:path]
diff --git a/spec/aliases/integer_spec.rb b/spec/aliases/integer_spec.rb
index aec9fd6..9cf0357 100644
--- a/spec/aliases/integer_spec.rb
+++ b/spec/aliases/integer_spec.rb
@@ -22,7 +22,7 @@ if Puppet::Util::Package.versioncmp(Puppet.version, '4.5.0') >= 0
[ "foo\nbar", true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x', 3.7, '3.7',-3.7, '-342.2315e-12' ].each do |value|
describe value.inspect do
let(:params) {{ value: value }}
- if Gem::Version.new(Puppet.version) >= Gem::Version.new('5.0.0')
+ if Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') >= 0
it { is_expected.to compile.and_raise_error(/parameter 'value' expects a Stdlib::Compat::Integer = Variant\[Integer, Pattern\[.*\], Array\[.*\]\] value/) }
else
it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Integer, Pattern(\[.*\]+)?, or Array/) }
diff --git a/spec/functions/pw_hash_spec.rb b/spec/functions/pw_hash_spec.rb
index df5348c..9e03464 100644
--- a/spec/functions/pw_hash_spec.rb
+++ b/spec/functions/pw_hash_spec.rb
@@ -65,5 +65,13 @@ describe 'pw_hash' do
it { is_expected.to run.with_params('password', 'sha-256', 'salt').and_return('$5$salt$Gcm6FsVtF/Qa77ZKD.iwsJlCVPY0XSMgLJL0Hnww/c1') }
it { is_expected.to run.with_params('password', 'sha-512', 'salt').and_return('$6$salt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy.g.') }
end
+
+ if Puppet::Util::Package.versioncmp(Puppet.version, '4.7.0') >= 0
+ describe 'when arguments are sensitive' do
+ it { is_expected.to run.with_params(Puppet::Pops::Types::PSensitiveType::Sensitive.new('password'), 'md5', 'salt').and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ it { is_expected.to run.with_params(Puppet::Pops::Types::PSensitiveType::Sensitive.new('password'), 'md5', Puppet::Pops::Types::PSensitiveType::Sensitive.new('salt')).and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ it { is_expected.to run.with_params('password', 'md5', Puppet::Pops::Types::PSensitiveType::Sensitive.new('salt')).and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ end
+ end
end
end
diff --git a/spec/functions/round_spec.rb b/spec/functions/round_spec.rb
new file mode 100755
index 0000000..5aa801c
--- /dev/null
+++ b/spec/functions/round_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe 'stdlib::round' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params(34.3).and_return(34) }
+ it { is_expected.to run.with_params(-34.3).and_return(-34) }
+ it { is_expected.to run.with_params(34.5).and_return(35) }
+ it { is_expected.to run.with_params(-34.5).and_return(-35) }
+ it { is_expected.to run.with_params(34.7).and_return(35) }
+ it { is_expected.to run.with_params(-34.7).and_return(-35) }
+end
diff --git a/spec/unit/puppet/provider/file_line/ruby_spec.rb b/spec/unit/puppet/provider/file_line/ruby_spec.rb
index ab6edf9..dcca4a4 100755
--- a/spec/unit/puppet/provider/file_line/ruby_spec.rb
+++ b/spec/unit/puppet/provider/file_line/ruby_spec.rb
@@ -194,6 +194,24 @@ describe provider_class, :unless => Puppet::Util::Platform.windows? do
@provider.create
expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
end
+
+ it 'should not add line after no matches found' do
+ @resource = Puppet::Type::File_line.new(
+ {
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'inserted = line',
+ :match => '^foo3$',
+ :append_on_no_match => false,
+ }
+ )
+ @provider = provider_class.new(@resource)
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz")
+ end
+ expect(@provider.exists?).to be true
+ expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
+ end
end
describe 'using after' do