From c4868e7cc729f8def571161d48b9816eba9891e5 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Sat, 4 Jan 2020 12:23:41 -0800 Subject: [PATCH] Porting functions to the modern Puppet 4.x API --- .../postgresql_acls_to_resources_hash.rb | 104 ++++++++++++++++++ lib/puppet/functions/postgresql_escape.rb | 52 +++++++++ lib/puppet/functions/postgresql_password.rb | 45 ++++++++ ..._postgresql_acls_to_resources_hash_spec.rb | 41 +++++++ spec/functions/_postgresql_escape_spec.rb | 41 +++++++ spec/functions/_postgresql_password_spec.rb | 41 +++++++ 6 files changed, 324 insertions(+) create mode 100644 lib/puppet/functions/postgresql_acls_to_resources_hash.rb create mode 100644 lib/puppet/functions/postgresql_escape.rb create mode 100644 lib/puppet/functions/postgresql_password.rb create mode 100644 spec/functions/_postgresql_acls_to_resources_hash_spec.rb create mode 100644 spec/functions/_postgresql_escape_spec.rb create mode 100644 spec/functions/_postgresql_password_spec.rb diff --git a/lib/puppet/functions/postgresql_acls_to_resources_hash.rb b/lib/puppet/functions/postgresql_acls_to_resources_hash.rb new file mode 100644 index 0000000000..ff78bf1953 --- /dev/null +++ b/lib/puppet/functions/postgresql_acls_to_resources_hash.rb @@ -0,0 +1,104 @@ +# This is an autogenerated function, ported from the original legacy version. +# It /should work/ as is, but will not have all the benefits of the modern +# function API. You should see the function docs to learn how to add function +# signatures for type safety and to document this function using puppet-strings. +# +# https://puppet.com/docs/puppet/latest/custom_functions_ruby.html +# +# ---- original file header ---- + +# ---- original file header ---- +# +# @summary +# This internal function translates the ipv(4|6)acls format into a resource +# suitable for create_resources. It is not intended to be used outside of the +# postgresql internal classes/defined resources. +# +# This function accepts an array of strings that are pg_hba.conf rules. It +# will return a hash that can be fed into create_resources to create multiple +# individual pg_hba_rule resources. +# +# The second parameter is an identifier that will be included in the namevar +# to provide uniqueness. It must be a string. +# +# The third parameter is an order offset, so you can start the order at an +# arbitrary starting point. +# +# +Puppet::Functions.create_function(:'postgresql_acls_to_resources_hash') do + # @param args + # The original array of arguments. Port this to individually managed params + # to get the full benefit of the modern function API. + # + # @return [Data type] + # Describe what the function returns here + # + dispatch :default_impl do + # Call the method named 'default_impl' when this is matched + # Port this to match individual params for better type safety + repeated_param 'Any', :args + end + + + def default_impl(*args) + + func_name = "postgresql_acls_to_resources_hash()" + + raise(Puppet::ParseError, "#{func_name}: Wrong number of arguments " + + "given (#{args.size} for 3)") if args.size != 3 + + acls = args[0] + raise(Puppet::ParseError, "#{func_name}: first argument must be an array") \ + unless acls.instance_of? Array + + id = args[1] + raise(Puppet::ParseError, "#{func_name}: second argument must be a string") \ + unless id.instance_of? String + + offset = args[2].to_i + raise(Puppet::ParseError, "#{func_name}: third argument must be a number") \ + unless offset.instance_of? Fixnum + + resources = {} + acls.each do |acl| + index = acls.index(acl) + + parts = acl.split + + raise(Puppet::ParseError, "#{func_name}: acl line #{index} does not " + + "have enough parts") unless parts.length >= 4 + + resource = { + 'type' => parts[0], + 'database' => parts[1], + 'user' => parts[2], + 'order' => format('%03d', offset + index), + } + if parts[0] == 'local' then + resource['auth_method'] = parts[3] + if parts.length > 4 then + resource['auth_option'] = parts.last(parts.length - 4).join(" ") + end + else + if parts[4] =~ /^\d/ + resource['address'] = parts[3] + ' ' + parts[4] + resource['auth_method'] = parts[5] + + if parts.length > 6 then + resource['auth_option'] = parts.last(parts.length - 6).join(" ") + end + else + resource['address'] = parts[3] + resource['auth_method'] = parts[4] + + if parts.length > 5 then + resource['auth_option'] = parts.last(parts.length - 5).join(" ") + end + end + end + resources["postgresql class generated rule #{id} #{index}"] = resource + end + resources + + end +end diff --git a/lib/puppet/functions/postgresql_escape.rb b/lib/puppet/functions/postgresql_escape.rb new file mode 100644 index 0000000000..4a8bacbe03 --- /dev/null +++ b/lib/puppet/functions/postgresql_escape.rb @@ -0,0 +1,52 @@ +# This is an autogenerated function, ported from the original legacy version. +# It /should work/ as is, but will not have all the benefits of the modern +# function API. You should see the function docs to learn how to add function +# signatures for type safety and to document this function using puppet-strings. +# +# https://puppet.com/docs/puppet/latest/custom_functions_ruby.html +# +# ---- original file header ---- +require 'digest/md5' + +# ---- original file header ---- +# +# @summary +# Safely escapes a string using $$ using a random tag which should be consistent +# +# +Puppet::Functions.create_function(:'postgresql_escape') do + # @param args + # The original array of arguments. Port this to individually managed params + # to get the full benefit of the modern function API. + # + # @return [Data type] + # Describe what the function returns here + # + dispatch :default_impl do + # Call the method named 'default_impl' when this is matched + # Port this to match individual params for better type safety + repeated_param 'Any', :args + end + + + def default_impl(*args) + + + raise(Puppet::ParseError, "postgresql_escape(): Wrong number of arguments " + + "given (#{args.size} for 1)") if args.size != 1 + + password = args[0] + + if password !~ /\$\$/ + retval = "$$#{password}$$" + else + escape = Digest::MD5.hexdigest(password)[0..5].gsub(/\d/,'') + until password !~ /#{escape}/ + escape = Digest::MD5.hexdigest(escape)[0..5].gsub(/\d/,'') + end + retval = "$#{escape}$#{password}$#{escape}$" + end + retval + + end +end diff --git a/lib/puppet/functions/postgresql_password.rb b/lib/puppet/functions/postgresql_password.rb new file mode 100644 index 0000000000..7079a373f2 --- /dev/null +++ b/lib/puppet/functions/postgresql_password.rb @@ -0,0 +1,45 @@ +# This is an autogenerated function, ported from the original legacy version. +# It /should work/ as is, but will not have all the benefits of the modern +# function API. You should see the function docs to learn how to add function +# signatures for type safety and to document this function using puppet-strings. +# +# https://puppet.com/docs/puppet/latest/custom_functions_ruby.html +# +# ---- original file header ---- +# hash a string as mysql's "PASSWORD()" function would do it +require 'digest/md5' + +# ---- original file header ---- +# +# @summary +# Returns the postgresql password hash from the clear text username / password. +# +# +Puppet::Functions.create_function(:'postgresql_password') do + # @param args + # The original array of arguments. Port this to individually managed params + # to get the full benefit of the modern function API. + # + # @return [Data type] + # Describe what the function returns here + # + dispatch :default_impl do + # Call the method named 'default_impl' when this is matched + # Port this to match individual params for better type safety + repeated_param 'Any', :args + end + + + def default_impl(*args) + + + raise(Puppet::ParseError, "postgresql_password(): Wrong number of arguments " + + "given (#{args.size} for 2)") if args.size != 2 + + username = args[0] + password = args[1] + + 'md5' + Digest::MD5.hexdigest(password + username) + + end +end diff --git a/spec/functions/_postgresql_acls_to_resources_hash_spec.rb b/spec/functions/_postgresql_acls_to_resources_hash_spec.rb new file mode 100644 index 0000000000..5e9676bb59 --- /dev/null +++ b/spec/functions/_postgresql_acls_to_resources_hash_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe 'postgresql_acls_to_resources_hash' do + # without knowing details about the implementation, this is the only test + # case that we can autogenerate. You should add more examples below! + it { is_expected.not_to eq(nil) } + +################################# +# Below are some example test cases. You may uncomment and modify them to match +# your needs. Notice that they all expect the base error class of `StandardError`. +# This is because the autogenerated function uses an untyped array for parameters +# and relies on your implementation to do the validation. As you convert your +# function to proper dispatches and typed signatures, you should change the +# expected error of the argument validation examples to `ArgumentError`. +# +# Other error types you might encounter include +# +# * StandardError +# * ArgumentError +# * Puppet::ParseError +# +# Read more about writing function unit tests at https://rspec-puppet.com/documentation/functions/ +# +# it 'raises an error if called with no argument' do +# is_expected.to run.with_params.and_raise_error(StandardError) +# end +# +# it 'raises an error if there is more than 1 arguments' do +# is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(StandardError) +# end +# +# it 'raises an error if argument is not the proper type' do +# is_expected.to run.with_params('foo').and_raise_error(StandardError) +# end +# +# it 'returns the proper output' do +# is_expected.to run.with_params(123).and_return('the expected output') +# end +################################# + +end diff --git a/spec/functions/_postgresql_escape_spec.rb b/spec/functions/_postgresql_escape_spec.rb new file mode 100644 index 0000000000..88d4b4d0f1 --- /dev/null +++ b/spec/functions/_postgresql_escape_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe 'postgresql_escape' do + # without knowing details about the implementation, this is the only test + # case that we can autogenerate. You should add more examples below! + it { is_expected.not_to eq(nil) } + +################################# +# Below are some example test cases. You may uncomment and modify them to match +# your needs. Notice that they all expect the base error class of `StandardError`. +# This is because the autogenerated function uses an untyped array for parameters +# and relies on your implementation to do the validation. As you convert your +# function to proper dispatches and typed signatures, you should change the +# expected error of the argument validation examples to `ArgumentError`. +# +# Other error types you might encounter include +# +# * StandardError +# * ArgumentError +# * Puppet::ParseError +# +# Read more about writing function unit tests at https://rspec-puppet.com/documentation/functions/ +# +# it 'raises an error if called with no argument' do +# is_expected.to run.with_params.and_raise_error(StandardError) +# end +# +# it 'raises an error if there is more than 1 arguments' do +# is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(StandardError) +# end +# +# it 'raises an error if argument is not the proper type' do +# is_expected.to run.with_params('foo').and_raise_error(StandardError) +# end +# +# it 'returns the proper output' do +# is_expected.to run.with_params(123).and_return('the expected output') +# end +################################# + +end diff --git a/spec/functions/_postgresql_password_spec.rb b/spec/functions/_postgresql_password_spec.rb new file mode 100644 index 0000000000..e875a88bac --- /dev/null +++ b/spec/functions/_postgresql_password_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe 'postgresql_password' do + # without knowing details about the implementation, this is the only test + # case that we can autogenerate. You should add more examples below! + it { is_expected.not_to eq(nil) } + +################################# +# Below are some example test cases. You may uncomment and modify them to match +# your needs. Notice that they all expect the base error class of `StandardError`. +# This is because the autogenerated function uses an untyped array for parameters +# and relies on your implementation to do the validation. As you convert your +# function to proper dispatches and typed signatures, you should change the +# expected error of the argument validation examples to `ArgumentError`. +# +# Other error types you might encounter include +# +# * StandardError +# * ArgumentError +# * Puppet::ParseError +# +# Read more about writing function unit tests at https://rspec-puppet.com/documentation/functions/ +# +# it 'raises an error if called with no argument' do +# is_expected.to run.with_params.and_raise_error(StandardError) +# end +# +# it 'raises an error if there is more than 1 arguments' do +# is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(StandardError) +# end +# +# it 'raises an error if argument is not the proper type' do +# is_expected.to run.with_params('foo').and_raise_error(StandardError) +# end +# +# it 'returns the proper output' do +# is_expected.to run.with_params(123).and_return('the expected output') +# end +################################# + +end