diff --git a/README.markdown b/README.markdown index 1368b2f70..26cf56b23 100644 --- a/README.markdown +++ b/README.markdown @@ -610,6 +610,103 @@ Determines if a hash has a certain key value. Converts an array into a hash. For example, `hash(['a',1,'b',2,'c',3])` returns {'a'=>1,'b'=>2,'c'=>3}. *Type*: rvalue. +#### `hash2ini` + +Converts a hash into an +[INI file format](https://en.wikipedia.org/wiki/INI_file). *Type*: rvalue. + +It is used when you want to overwrite an entire file with a hash of settings. If +you want to manage bits and pieces of an INI file, you want +[puppetlabs/inifile](https://github.com/puppetlabs/puppetlabs-inifile). + +##### Parameters + +It accepts the following optional parameters passed to it in a hash as the second argument: + +* `header`: String you want at the top of the file saying it is controlled by puppet. Default: '# THIS FILE IS CONTROLLED BY PUPPET' +* `section_prefix`: String that will appear before the section's name. Default: '[' +* `section_suffix`: String that will appear after the section's name. Default: ']' +* `key_val_separator`: String to use between setting name and value (e.g., to determine whether the separator includes whitespace). Default: '='. +* `quote_char`: Character or string to quote the entire value of the setting. Default: '"' + +For example: + + ~~~ + $config = { + 'main' => { + 'logging' => 'INFO', + 'limit' => 314, + 'awesome' => true, + }, + 'dev' => { + 'logging' => 'DEBUG', + 'log_location' => '/var/log/dev.log', + } + } + + file {'/etc/config.ini': + ensure => 'present', + content => hash2ini($config) + } + ~~~ + +will produce a file at /etc/config.ini that looks like: + + ~~~ + # THIS FILE IS CONTROLLED BY PUPPET + + [main] + logging="INFO" + limit="314" + awesome="true" + + [dev] + logging="DEBUG" + log_location="/var/log/dev.log" + ~~~ + +Or you can specify custom settings: + + ~~~ + settings = { + 'header' => '; THIS FILE IS CONTROLLED BY PUPPET', + 'key_val_separator' => ' = ', + 'quote_char' => '', + } + + $php_config = { + 'PHP' => { + 'engine' => 'On', + 'realpath_cache_size' => '32k', + 'zlib.output_compression' => 'On', + 'expose_php' => 'Off', + }, + 'Date' => { + 'date.timezone' => '"America/Detroit"', + } + } + + file {'/etc/php.ini': + ensure => 'present', + content => hash2ini($php_config, $settings) + } + ~~~ + +will produce a file at /etc/php.ini that looks like: + + ~~~ + ; THIS FILE IS CONTROLLED BY PUPPET + + [PHP] + engine = On + realpath_cache_size = 32k + zlib.output_compression = On + expose_php = Off + + [Date] + date.timezone = "America/Detroit" + ~~~ + #### `intersection` Returns an array an intersection of two. For example, `intersection(["a","b","c"],["b","c","d"])` returns ["b","c"]. *Type*: rvalue. diff --git a/lib/puppet/parser/functions/hash2ini.rb b/lib/puppet/parser/functions/hash2ini.rb new file mode 100644 index 000000000..89505aa4e --- /dev/null +++ b/lib/puppet/parser/functions/hash2ini.rb @@ -0,0 +1,47 @@ +module Puppet::Parser::Functions + newfunction(:hash2ini, :type => :rvalue, :doc => <<-EOS +This converts a puppet hash to an INI string. + EOS + ) do |arguments| + + if arguments.size < 1 + raise(Puppet::ParseError, 'hash2ini(): requires at least one argument') + end + if arguments.size >= 3 + raise(Puppet::ParseError, 'hash2ini(): too many arguments') + end + unless arguments[0].is_a?(Hash) + raise(Puppet::ParseError, 'hash2ini(): requires a hash as argument') + end + + h = arguments[0] + + settings = { + 'header' => '# THIS FILE IS CONTROLLED BY PUPPET', + 'section_prefix' => '[', + 'section_suffix' => ']', + 'key_val_separator' => '=', + 'quote_char' => '"', + } + + if arguments[1] + unless arguments[1].is_a?(Hash) + raise(Puppet::ParseError, 'hash2ini(): Requires a hash as argument') + end + settings.merge!(arguments[1]) + end + + + + ini = [] + ini << settings['header'] << nil + h.keys.each do |section| + ini << "#{settings['section_prefix']}#{section}#{settings['section_suffix']}" + h[section].each do |k, v| + ini << "#{k}#{settings['key_val_separator']}#{settings['quote_char']}#{v}#{settings['quote_char']}" + end + ini << nil + end + return ini.join("\n") + end +end diff --git a/spec/functions/hash2ini_spec.rb b/spec/functions/hash2ini_spec.rb new file mode 100644 index 000000000..9494ae1c5 --- /dev/null +++ b/spec/functions/hash2ini_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe 'hash2ini' do + it { is_expected.not_to eq(nil) } + it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /requires at least one argument/) } + it { is_expected.to run.with_params({}, {}, {}).and_raise_error(Puppet::ParseError, /too many arguments/) } + it { is_expected.to run.with_params('some string').and_raise_error(Puppet::ParseError, /requires a hash as argument/) } + + example_input = { + 'main' => { + 'logging' => 'INFO', + 'limit' => 314, + 'awesome' => true, + }, + 'dev' => { + 'logging' => 'DEBUG', + 'log_location' => '/var/log/dev.log', + } + } + + context 'no custom settings' do + output=<<-EOS +# THIS FILE IS CONTROLLED BY PUPPET + +[main] +logging="INFO" +limit="314" +awesome="true" + +[dev] +logging="DEBUG" +log_location="/var/log/dev.log" +EOS + it { is_expected.to run.with_params(example_input).and_return(output) } + end + + context 'custom settings' do + settings = { + 'header' => '; THIS FILE IS CONTROLLED BY /dev/random', + 'section_prefix' => '[[', + 'section_suffix' => ']]', + 'key_val_separator' => ': ', + 'quote_char' => "", + } + output=<<-EOS +; THIS FILE IS CONTROLLED BY /dev/random + +[[main]] +logging: INFO +limit: 314 +awesome: true + +[[dev]] +logging: DEBUG +log_location: /var/log/dev.log +EOS + it { is_expected.to run.with_params(example_input, settings).and_return(output) } + end +end