puppetlabs-inifile-1.0.0/000755 000765 000024 00000000000 12171506567 016120 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/CHANGELOG000644 000765 000024 00000006256 12171506567 017343 0ustar00apenneystaff000000 000000 2013-07-16 - Version 1.0.0 Features: - Handle empty values. - Handle whitespace in settings names (aka: server role = something) - Add mechanism for allowing ini_setting subclasses to override the formation of the namevar during .instances, to allow for ini_setting derived types that manage flat ini-file-like files and still purge them. 2013-05-28 - Chris Price - 0.10.3 * Fix bug in subsetting handling for new settings (cbea5dc) 2013-05-22 - Chris Price - 0.10.2 * Better handling of quotes for subsettings (1aa7e60) 2013-05-21 - Chris Price - 0.10.1 * Change constants to class variables to avoid ruby warnings (6b19864) 2013-04-10 - Erik Dalén - 0.10.1 * Style fixes (c4af8c3) 2013-04-02 - Dan Bode - 0.10.1 * Add travisfile and Gemfile (c2052b3) 2013-04-02 - Chris Price - 0.10.1 * Update README.markdown (ad38a08) 2013-02-15 - Karel Brezina - 0.10.0 * Added 'ini_subsetting' custom resource type (4351d8b) 2013-03-11 - Dan Bode - 0.10.0 * guard against nil indentation values (5f71d7f) 2013-01-07 - Dan Bode - 0.10.0 * Add purging support to ini file (2f22483) 2013-02-05 - James Sweeny - 0.10.0 * Fix test to use correct key_val_parameter (b1aff63) 2012-11-06 - Chris Price - 0.10.0 * Added license file w/Apache 2.0 license (5e1d203) 2012-11-02 - Chris Price - 0.9.0 * Version 0.9.0 released 2012-10-26 - Chris Price - 0.9.0 * Add detection for commented versions of settings (a45ab65) 2012-10-20 - Chris Price - 0.9.0 * Refactor to clarify implementation of `save` (f0d443f) 2012-10-20 - Chris Price - 0.9.0 * Add example for `ensure=absent` (e517148) 2012-10-20 - Chris Price - 0.9.0 * Better handling of whitespace lines at ends of sections (845fa70) 2012-10-20 - Chris Price - 0.9.0 * Respect indentation / spacing for existing sections and settings (c2c26de) 2012-10-17 - Chris Price - 0.9.0 * Minor tweaks to handling of removing settings (cda30a6) 2012-10-10 - Dan Bode - 0.9.0 * Add support for removing lines (1106d70) 2012-10-02 - Dan Bode - 0.9.0 * Make value a property (cbc90d3) 2012-10-02 - Dan Bode - 0.9.0 * Make ruby provider a better parent. (1564c47) 2012-09-29 - Reid Vandewiele - 0.9.0 * Allow values with spaces to be parsed and set (3829e20) 2012-09-24 - Chris Price - 0.0.3 * Version 0.0.3 released 2012-09-20 - Chris Price - 0.0.3 * Add validation for key_val_separator (e527908) 2012-09-19 - Chris Price - 0.0.3 * Allow overriding separator string between key/val pairs (8d1fdc5) 2012-08-20 - Chris Price - 0.0.2 * Version 0.0.2 released 2012-08-17 - Chris Price - 0.0.2 * Add support for "global" section at beginning of file (c57dab4) puppetlabs-inifile-1.0.0/Gemfile000644 000765 000024 00000000723 12171506567 017415 0ustar00apenneystaff000000 000000 source 'https://rubygems.org' group :development, :test do gem 'rake', :require => false gem 'rspec-puppet', :require => false gem 'puppetlabs_spec_helper', :require => false gem 'simplecov', :require => false gem 'pry', :require => false end if puppetversion = ENV['PUPPET_GEM_VERSION'] gem 'puppet', puppetversion, :require => false else gem 'puppet', :require => false end # vim:ft=ruby puppetlabs-inifile-1.0.0/Gemfile.lock000644 000765 000024 00000002123 12171506567 020340 0ustar00apenneystaff000000 000000 GEM remote: https://rubygems.org/ specs: coderay (1.0.9) diff-lcs (1.2.4) facter (1.7.1) hiera (1.2.1) json_pure json_pure (1.8.0) metaclass (0.0.1) method_source (0.8.1) mocha (0.14.0) metaclass (~> 0.0.1) multi_json (1.7.7) pry (0.9.12.2) coderay (~> 1.0.5) method_source (~> 0.8) slop (~> 3.4) puppet (3.2.2) facter (~> 1.6) hiera (~> 1.0) rgen (~> 0.6) puppetlabs_spec_helper (0.4.1) mocha (>= 0.10.5) rake rspec (>= 2.9.0) rspec-puppet (>= 0.1.1) rake (10.1.0) rgen (0.6.5) rspec (2.14.0) rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) rspec-core (2.14.2) rspec-expectations (2.14.0) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.14.1) rspec-puppet (0.1.6) rspec simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) simplecov-html (0.7.1) slop (3.4.5) PLATFORMS ruby DEPENDENCIES pry puppet puppetlabs_spec_helper rake rspec-puppet simplecov puppetlabs-inifile-1.0.0/lib/000755 000765 000024 00000000000 12171506567 016666 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/LICENSE000644 000765 000024 00000026114 12171506567 017131 0ustar00apenneystaff000000 000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2012 Chris Price Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. puppetlabs-inifile-1.0.0/metadata.json000644 000765 000024 00000012414 12171506567 020575 0ustar00apenneystaff000000 000000 { "name": "puppetlabs-inifile", "version": "1.0.0", "source": "git://github.com/puppetlabs/puppetlabs-inifile.git", "author": "Puppetlabs", "license": "Apache", "summary": "Resource types for managing settings in INI files", "description": "Resource types for managing settings in INI files", "project_page": "https://github.com/puppetlabs/puppetlabs-inifile", "dependencies": [ ], "types": [ { "name": "ini_setting", "doc": "", "properties": [ { "name": "ensure", "doc": "The basic property that the resource should be in. Valid values are `present`, `absent`." }, { "name": "value", "doc": "The value of the setting to be defined." } ], "parameters": [ { "name": "name", "doc": "An arbitrary name used as the identity of the resource." }, { "name": "section", "doc": "The name of the section in the ini file in which the setting should be defined." }, { "name": "setting", "doc": "The name of the setting to be defined." }, { "name": "path", "doc": "The ini file Puppet will ensure contains the specified setting." }, { "name": "key_val_separator", "doc": "The separator string to use between each setting name and value. Defaults to \" = \", but you could use this to override e.g. whether or not the separator should include whitespace." } ], "providers": [ { "name": "ruby", "doc": "" } ] }, { "name": "ini_subsetting", "doc": "", "properties": [ { "name": "ensure", "doc": "The basic property that the resource should be in. Valid values are `present`, `absent`." }, { "name": "value", "doc": "The value of the subsetting to be defined." } ], "parameters": [ { "name": "name", "doc": "An arbitrary name used as the identity of the resource." }, { "name": "section", "doc": "The name of the section in the ini file in which the setting should be defined." }, { "name": "setting", "doc": "The name of the setting to be defined." }, { "name": "subsetting", "doc": "The name of the subsetting to be defined." }, { "name": "subsetting_separator", "doc": "The separator string between subsettings. Defaults to \" \"" }, { "name": "path", "doc": "The ini file Puppet will ensure contains the specified setting." }, { "name": "key_val_separator", "doc": "The separator string to use between each setting name and value. Defaults to \" = \", but you could use this to override e.g. whether or not the separator should include whitespace." } ], "providers": [ { "name": "ruby", "doc": "" } ] } ], "checksums": { "CHANGELOG": "1d2ab7d31e0fa7b96ff2e62a59890585", "Gemfile": "144b186b7315b993411af56fd3fe17ba", "Gemfile.lock": "805305e11bd3eb3ccf93779e06dec330", "LICENSE": "519b25a3992e0598a9855e4ccd7f66a1", "Modulefile": "db6005147c078f60dd4d33819941ffd0", "README.markdown": "a373118f66eed7b342fad96bc3885584", "Rakefile": "0254db5d3fc38c67a2c160d7296a24f8", "lib/puppet/provider/ini_setting/ruby.rb": "19174eb75e2efa2f1e5935cd694ee87a", "lib/puppet/provider/ini_subsetting/ruby.rb": "99991c9d3ccf54c2aa1fcacf491d0cfc", "lib/puppet/type/ini_setting.rb": "afcd3f28b946b08db1b48fb189e6d8cf", "lib/puppet/type/ini_subsetting.rb": "b4e6a659f461bcd274dcdf1b1c39db65", "lib/puppet/util/external_iterator.rb": "69ad1eb930ca6d8d6b6faea343b4a22e", "lib/puppet/util/ini_file/section.rb": "77757399ed9b9ce352ddcc8b8f9273c4", "lib/puppet/util/ini_file.rb": "911c2fabc08bded5e364158eb49e97c4", "lib/puppet/util/setting_value.rb": "a9db550b94d66164b8643612dbf7cbb2", "spec/classes/inherit_test1_spec.rb": "56bbfd63e770b180abc3fd7e331de2fb", "spec/fixtures/modules/inherit_ini_setting/lib/puppet/provider/inherit_ini_setting/ini_setting.rb": "15949e27a64f4768a65fc01ca8d0c90d", "spec/fixtures/modules/inherit_ini_setting/lib/puppet/type/inherit_ini_setting.rb": "90f25ea0e389688a0df74f23a5ad18e7", "spec/fixtures/modules/inherit_test1/manifests/init.pp": "ece5099a0da66d65a05055d22485756c", "spec/spec_helper.rb": "3a33176450601775fcc0932340df9f74", "spec/unit/puppet/provider/ini_setting/inheritance_spec.rb": "bbe2fb9d6805ae8cae85271e48f646b3", "spec/unit/puppet/provider/ini_setting/ruby_spec.rb": "1c82228947d3d7bd32ee333068aff7f0", "spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb": "b05cf15a5830feb249ad7177f7d966ca", "spec/unit/puppet/util/external_iterator_spec.rb": "35cc6e56e0064e496e9151dd778f751f", "spec/unit/puppet/util/ini_file_spec.rb": "9090ada5867eb0333f3c543a7fd11a53", "spec/unit/puppet/util/setting_value_spec.rb": "64db9b766063db958e73e713a3e584fa", "tests/ini_setting.pp": "9c8a9d2c453901cedb106cada253f1f6", "tests/ini_subsetting.pp": "71c82234fa8bb8cb442ff01436ce2cf3" } }puppetlabs-inifile-1.0.0/Modulefile000644 000765 000024 00000000507 12171506567 020132 0ustar00apenneystaff000000 000000 name 'puppetlabs-inifile' version '1.0.0' source 'git://github.com/puppetlabs/puppetlabs-inifile.git' author 'Puppetlabs' description 'Resource types for managing settings in INI files' summary 'Resource types for managing settings in INI files' license 'Apache' project_page 'https://github.com/puppetlabs/puppetlabs-inifile' puppetlabs-inifile-1.0.0/Rakefile000644 000765 000024 00000000054 12171506567 017564 0ustar00apenneystaff000000 000000 require 'puppetlabs_spec_helper/rake_tasks' puppetlabs-inifile-1.0.0/README.markdown000644 000765 000024 00000007042 12171506567 020624 0ustar00apenneystaff000000 000000 [![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-inifile.png?branch=master)](https://travis-ci.org/cprice-puppet/puppetlabs-inifile) # INI-file module # This module provides resource types for use in managing INI-style configuration files. The main resource type is `ini_setting`, which is used to manage an individual setting in an INI file. Here's an example usage: ini_setting { "sample setting": path => '/tmp/foo.ini', section => 'foo', setting => 'foosetting', value => 'FOO!', ensure => present, } A supplementary resource type is `ini_subsetting`, which is used to manage settings that consist of several arguments such as JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof " ini_subsetting {'sample subsetting': ensure => present, section => '', key_val_separator => '=', path => '/etc/default/pe-puppetdb', setting => 'JAVA_ARGS', subsetting => '-Xmx', value => '512m', } ## implementing child providers: The ini_setting class can be overridden by child providers in order to implement the management of ini settings for a specific configuration file. In order to implement this, you will need to specify your own Type (as shown below). This type needs to implement a namevar (name), and a property called value: example: #my_module/lib/puppet/type/glance_api_config.rb Puppet::Type.newtype(:glance_api_config) do ensurable newparam(:name, :namevar => true) do desc 'Section/setting name to manage from glance-api.conf' # namevar should be of the form section/setting newvalues(/\S+\/\S+/) end newproperty(:value) do desc 'The value of the setting to be defined.' munge do |v| v.to_s.strip end end end This type also must have a provider that utilizes the ini_setting provider as its parent: example: # my_module/lib/puppet/provider/glance_api_config/ini_setting.rb Puppet::Type.type(:glance_api_config).provide( :ini_setting, # set ini_setting as the parent provider :parent => Puppet::Type.type(:ini_setting).provider(:ruby) ) do # implement section as the first part of the namevar def section resource[:name].split('/', 2).first end def setting # implement setting as the second part of the namevar resource[:name].split('/', 2).last end # hard code the file path (this allows purging) def self.file_path '/etc/glance/glance-api.conf' end end Now, the individual settings of the /etc/glance/glance-api.conf file can be managed as individual resources: glance_api_config { 'HEADER/important_config': value => 'secret_value', } Provided that self.file_path has been implemented, you can purge with the following puppet syntax: resources { 'glance_api_config' purge => true, } If the above code is added, then the resulting configured file will only contain lines implemented as Puppet resources ## A few noteworthy features: * The module tries *hard* not to manipulate your file any more than it needs to. In most cases, it should leave the original whitespace, comments, ordering, etc. perfectly intact. * Supports comments starting with either '#' or ';'. * Will add missing sections if they don't exist. * Supports a "global" section (settings that go at the beginning of the file, before any named sections) by specifying a section name of "". puppetlabs-inifile-1.0.0/spec/000755 000765 000024 00000000000 12171506567 017052 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/tests/000755 000765 000024 00000000000 12171506567 017262 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/tests/ini_setting.pp000644 000765 000024 00000001152 12171506567 022136 0ustar00apenneystaff000000 000000 ini_setting { 'sample setting': ensure => present, path => '/tmp/foo.ini', section => 'foo', setting => 'foosetting', value => 'FOO!', } ini_setting { 'sample setting2': ensure => present, path => '/tmp/foo.ini', section => 'bar', setting => 'barsetting', value => 'BAR!', key_val_separator => '=', require => Ini_setting['sample setting'], } ini_setting { 'sample setting3': ensure => absent, path => '/tmp/foo.ini', section => 'bar', setting => 'bazsetting', require => Ini_setting['sample setting2'], } puppetlabs-inifile-1.0.0/tests/ini_subsetting.pp000644 000765 000024 00000001012 12171506567 022643 0ustar00apenneystaff000000 000000 ini_subsetting { 'sample subsetting': ensure => present, section => '', key_val_separator => '=', path => '/etc/default/pe-puppetdb', setting => 'JAVA_ARGS', subsetting => '-Xmx', value => '512m', } ini_subsetting { 'sample subsetting2': ensure => absent, section => '', key_val_separator => '=', path => '/etc/default/pe-puppetdb', setting => 'JAVA_ARGS', subsetting => '-Xms', } puppetlabs-inifile-1.0.0/spec/classes/000755 000765 000024 00000000000 12171506567 020507 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/000755 000765 000024 00000000000 12171506567 020723 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/spec_helper.rb000644 000765 000024 00000000426 12171506567 021672 0ustar00apenneystaff000000 000000 gem 'rspec', '>=2.0.0' require 'rspec/expectations' require 'puppetlabs_spec_helper/puppetlabs_spec_helper' require 'puppetlabs_spec_helper/puppetlabs_spec/files' require 'puppetlabs_spec_helper/module_spec_helper' RSpec.configure do |config| config.mock_with :rspec end puppetlabs-inifile-1.0.0/spec/unit/000755 000765 000024 00000000000 12171506567 020031 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/unit/puppet/000755 000765 000024 00000000000 12171506567 021346 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/unit/puppet/provider/000755 000765 000024 00000000000 12171506567 023200 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/unit/puppet/util/000755 000765 000024 00000000000 12171506567 022323 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/unit/puppet/util/external_iterator_spec.rb000644 000765 000024 00000001726 12171506567 027423 0ustar00apenneystaff000000 000000 require 'spec_helper' require 'puppet/util/external_iterator' describe Puppet::Util::ExternalIterator do let(:subject) { Puppet::Util::ExternalIterator.new(["a", "b", "c"]) } context "#next" do it "should iterate over the items" do subject.next.should == ["a", 0] subject.next.should == ["b", 1] subject.next.should == ["c", 2] end end context "#peek" do it "should return the 0th item repeatedly" do subject.peek.should == ["a", 0] subject.peek.should == ["a", 0] end it "should not advance the iterator, but should reflect calls to #next" do subject.peek.should == ["a", 0] subject.peek.should == ["a", 0] subject.next.should == ["a", 0] subject.peek.should == ["b", 1] subject.next.should == ["b", 1] subject.peek.should == ["c", 2] subject.next.should == ["c", 2] subject.peek.should == [nil, nil] subject.next.should == [nil, nil] end end end puppetlabs-inifile-1.0.0/spec/unit/puppet/util/ini_file_spec.rb000644 000765 000024 00000007543 12171506567 025451 0ustar00apenneystaff000000 000000 require 'spec_helper' require 'stringio' require 'puppet/util/ini_file' describe Puppet::Util::IniFile do let(:subject) { Puppet::Util::IniFile.new("/my/ini/file/path") } before :each do File.should_receive(:file?).with("/my/ini/file/path") { true } described_class.should_receive(:readlines).once.with("/my/ini/file/path") do sample_content end end context "when parsing a file" do let(:sample_content) { template = <<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue baz = [section2] foo= foovalue2 baz=bazvalue #another comment ; yet another comment zot = multi word value EOS template.split("\n") } it "should parse the correct number of sections" do # there is always a "global" section, so our count should be 3. subject.section_names.length.should == 3 end it "should parse the correct section_names" do # there should always be a "global" section named "" at the beginning of the list subject.section_names.should == ["", "section1", "section2"] end it "should expose settings for sections" do subject.get_value("section1", "foo").should == "foovalue" subject.get_value("section1", "bar").should == "barvalue" subject.get_value("section1", "baz").should == "" subject.get_value("section2", "foo").should == "foovalue2" subject.get_value("section2", "baz").should == "bazvalue" subject.get_value("section2", "zot").should == "multi word value" end end context "when parsing a file whose first line is a section" do let(:sample_content) { template = <<-EOS [section1] ; This is a comment foo=foovalue EOS template.split("\n") } it "should parse the correct number of sections" do # there is always a "global" section, so our count should be 2. subject.section_names.length.should == 2 end it "should parse the correct section_names" do # there should always be a "global" section named "" at the beginning of the list subject.section_names.should == ["", "section1"] end it "should expose settings for sections" do subject.get_value("section1", "foo").should == "foovalue" end end context "when parsing a file with a 'global' section" do let(:sample_content) { template = <<-EOS foo = bar [section1] ; This is a comment foo=foovalue EOS template.split("\n") } it "should parse the correct number of sections" do # there is always a "global" section, so our count should be 2. subject.section_names.length.should == 2 end it "should parse the correct section_names" do # there should always be a "global" section named "" at the beginning of the list subject.section_names.should == ["", "section1"] end it "should expose settings for sections" do subject.get_value("", "foo").should == "bar" subject.get_value("section1", "foo").should == "foovalue" end end context "when updating a file with existing empty values" do let(:sample_content) { template = <<-EOS [section1] foo= #bar= EOS template.split("\n") } it "should properly update uncommented values" do subject.get_value("section1", "far").should == nil subject.set_value("section1", "foo", "foovalue") subject.get_value("section1", "foo").should == "foovalue" end it "should properly update commented values" do subject.get_value("section1", "bar").should == nil subject.set_value("section1", "bar", "barvalue") subject.get_value("section1", "bar").should == "barvalue" end it "should properly add new empty values" do subject.get_value("section1", "baz").should == nil subject.set_value("section1", "baz", "bazvalue") subject.get_value("section1", "baz").should == "bazvalue" end end end puppetlabs-inifile-1.0.0/spec/unit/puppet/util/setting_value_spec.rb000644 000765 000024 00000004444 12171506567 026541 0ustar00apenneystaff000000 000000 require 'spec_helper' require 'puppet/util/setting_value' describe Puppet::Util::SettingValue do describe "space subsetting separator" do INIT_VALUE_SPACE = "\"-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof\"" before :each do @setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_SPACE, " ") end it "should get the original value" do @setting_value.get_value.should == INIT_VALUE_SPACE end it "should get the correct value" do @setting_value.get_subsetting_value("-Xmx").should == "192m" end it "should add a new value" do @setting_value.add_subsetting("-Xms", "256m") @setting_value.get_subsetting_value("-Xms").should == "256m" @setting_value.get_value.should == INIT_VALUE_SPACE[0, INIT_VALUE_SPACE.length - 1] + " -Xms256m\"" end it "should change existing value" do @setting_value.add_subsetting("-Xmx", "512m") @setting_value.get_subsetting_value("-Xmx").should == "512m" end it "should remove existing value" do @setting_value.remove_subsetting("-Xmx") @setting_value.get_subsetting_value("-Xmx").should == nil end end describe "comma subsetting separator" do INIT_VALUE_COMMA = "\"-Xmx192m,-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof\"" before :each do @setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_COMMA, ",") end it "should get the original value" do @setting_value.get_value.should == INIT_VALUE_COMMA end it "should get the correct value" do @setting_value.get_subsetting_value("-Xmx").should == "192m" end it "should add a new value" do @setting_value.add_subsetting("-Xms", "256m") @setting_value.get_subsetting_value("-Xms").should == "256m" @setting_value.get_value.should == INIT_VALUE_COMMA[0, INIT_VALUE_COMMA.length - 1] + ",-Xms256m\"" end it "should change existing value" do @setting_value.add_subsetting("-Xmx", "512m") @setting_value.get_subsetting_value("-Xmx").should == "512m" end it "should remove existing value" do @setting_value.remove_subsetting("-Xmx") @setting_value.get_subsetting_value("-Xmx").should == nil end end end puppetlabs-inifile-1.0.0/spec/unit/puppet/provider/ini_setting/000755 000765 000024 00000000000 12171506567 025514 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/unit/puppet/provider/ini_subsetting/000755 000765 000024 00000000000 12171506567 026226 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb000644 000765 000024 00000007367 12171506567 030563 0ustar00apenneystaff000000 000000 require 'spec_helper' require 'puppet' provider_class = Puppet::Type.type(:ini_subsetting).provider(:ruby) describe provider_class do include PuppetlabsSpec::Files let(:tmpfile) { tmpfilename("ini_setting_test") } def validate_file(expected_content,tmpfile = tmpfile) File.read(tmpfile).should == expected_content end before :each do File.open(tmpfile, 'w') do |fh| fh.write(orig_content) end end context "when ensuring that a subsetting is present" do let(:common_params) { { :title => 'ini_setting_ensure_present_test', :path => tmpfile, :section => '', :key_val_separator => '=', :setting => 'JAVA_ARGS', } } let(:orig_content) { <<-EOS JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS } it "should add a missing subsetting" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => '-Xms', :value => '128m')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof -Xms128m" EOS ) end it "should remove an existing subsetting" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => '-Xmx')) provider = described_class.new(resource) provider.exists?.should == "192m" provider.destroy validate_file(<<-EOS JAVA_ARGS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS ) end it "should modify an existing subsetting" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => '-Xmx', :value => '256m')) provider = described_class.new(resource) provider.exists?.should == "192m" provider.value=('256m') validate_file(<<-EOS JAVA_ARGS="-Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof" EOS ) end end context "when working with subsettings in files with unquoted settings values" do let(:common_params) { { :title => 'ini_setting_ensure_present_test', :path => tmpfile, :section => 'master', :setting => 'reports', } } let(:orig_content) { <<-EOS [master] reports = http,foo EOS } it "should remove an existing subsetting" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => 'http', :subsetting_separator => ',')) provider = described_class.new(resource) provider.exists?.should == "" provider.destroy validate_file(<<-EOS [master] reports = foo EOS ) end it "should add a new subsetting when the 'parent' setting already exists" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :subsetting => 'puppetdb', :subsetting_separator => ',')) provider = described_class.new(resource) provider.exists?.should be_nil provider.value=('') validate_file(<<-EOS [master] reports = http,foo,puppetdb EOS ) end it "should add a new subsetting when the 'parent' setting does not already exist" do resource = Puppet::Type::Ini_subsetting.new(common_params.merge( :setting => 'somenewsetting', :subsetting => 'puppetdb', :subsetting_separator => ',')) provider = described_class.new(resource) provider.exists?.should be_nil provider.value=('') validate_file(<<-EOS [master] reports = http,foo somenewsetting = puppetdb EOS ) end end end puppetlabs-inifile-1.0.0/spec/unit/puppet/provider/ini_setting/inheritance_spec.rb000644 000765 000024 00000003450 12171506567 031346 0ustar00apenneystaff000000 000000 require 'spec_helper' # This is a reduced version of ruby_spec.rb just to ensure we can subclass as # documented $: << 'spec/fixtures/modules/inherit_ini_setting/lib' provider_class = Puppet::Type.type(:inherit_ini_setting).provider(:ini_setting) describe provider_class do include PuppetlabsSpec::Files let(:tmpfile) { tmpfilename('inherit_ini_setting_test') } def validate_file(expected_content,tmpfile = tmpfile) File.read(tmpfile).should == expected_content end before :each do File.open(tmpfile, 'w') do |fh| fh.write(orig_content) end end context 'when calling instances' do let(:orig_content) { '' } it 'should parse nothing when the file is empty' do provider_class.stubs(:file_path).returns(tmpfile) provider_class.instances.should == [] end context 'when the file has contents' do let(:orig_content) { <<-EOS # A comment red = blue green = purple EOS } it 'should parse the results' do provider_class.stubs(:file_path).returns(tmpfile) instances = provider_class.instances instances.size.should == 2 # inherited version of namevar flattens the names names = instances.map do |instance| instance.instance_variable_get(:@property_hash)[:name] end names.sort.should == [ 'green', 'red' ] end end end context 'when ensuring that a setting is present' do let(:orig_content) { '' } it 'should add a value to the file' do provider_class.stubs(:file_path).returns(tmpfile) resource = Puppet::Type::Inherit_ini_setting.new({ :setting => 'set_this', :value => 'to_that', }) provider = described_class.new(resource) provider.create validate_file("set_this=to_that\n") end end end puppetlabs-inifile-1.0.0/spec/unit/puppet/provider/ini_setting/ruby_spec.rb000644 000765 000024 00000060315 12171506567 030041 0ustar00apenneystaff000000 000000 require 'spec_helper' require 'puppet' provider_class = Puppet::Type.type(:ini_setting).provider(:ruby) describe provider_class do include PuppetlabsSpec::Files let(:tmpfile) { tmpfilename("ini_setting_test") } let(:emptyfile) { tmpfilename("ini_setting_test_empty") } let(:common_params) { { :title => 'ini_setting_ensure_present_test', :path => tmpfile, :section => 'section2', } } def validate_file(expected_content,tmpfile = tmpfile) File.read(tmpfile).should == expected_content end before :each do File.open(tmpfile, 'w') do |fh| fh.write(orig_content) end File.open(emptyfile, 'w') do |fh| fh.write("") end end context 'when calling instances' do let :orig_content do '' end it 'should fail when file path is not set' do expect { provider_class.instances }.to raise_error(Puppet::Error, 'Ini_settings only support collecting instances when a file path is hard coded') end context 'when file path is set by a child class' do it 'should return [] when file is empty' do child_one = Class.new(provider_class) do def self.file_path emptyfile end end child_one.stubs(:file_path).returns(emptyfile) child_one.instances.should == [] end it 'should override the provider instances file_path' do child_two = Class.new(provider_class) do def self.file_path '/some/file/path' end end resource = Puppet::Type::Ini_setting.new(common_params) provider = child_two.new(resource) provider.file_path.should == '/some/file/path' end context 'when file has contecnts' do let(:orig_content) { <<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS } it 'should be able to parse the results' do child_three = Class.new(provider_class) do def self.file_path '/some/file/path' end end child_three.stubs(:file_path).returns(tmpfile) child_three.instances.size == 7 expected_array = [ {:name => 'section1/foo', :value => 'foovalue' }, {:name => 'section1/bar', :value => 'barvalue' }, {:name => 'section1/master', :value => 'true' }, {:name => 'section2/foo', :value => 'foovalue2' }, {:name => 'section2/baz', :value => 'bazvalue' }, {:name => 'section2/url', :value => 'http://192.168.1.1:8080' }, {:name => 'section:sub/subby', :value => 'bar' } ] real_array = [] ensure_array = [] child_three.instances.each do |x| prop_hash = x.instance_variable_get(:@property_hash) ensure_value = prop_hash.delete(:ensure) ensure_array.push(ensure_value) real_array.push(prop_hash) end ensure_array.uniq.should == [:present] ((real_array - expected_array) && (expected_array - real_array)).should == [] end end end end context "when ensuring that a setting is present" do let(:orig_content) { <<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS } it "should add a missing setting to the correct section" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 yahoo = yippee [section:sub] subby=bar #another comment ; yet another comment EOS ) end it "should add a missing setting to the correct section with colon" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section:sub', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment yahoo = yippee EOS ) end it "should modify an existing setting with a different value" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'baz', :value => 'bazvalue2')) provider = described_class.new(resource) provider.exists?.should == 'bazvalue' provider.value=('bazvalue2') validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue2 url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS ) end it "should modify an existing setting with a different value - with colon in section" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section:sub', :setting => 'subby', :value => 'foo')) provider = described_class.new(resource) provider.exists?.should == 'bar' provider.value.should == 'bar' provider.value=('foo') validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=foo #another comment ; yet another comment EOS ) end it "should be able to handle settings with non alphanumbering settings " do resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'url', :value => 'http://192.168.0.1:8080')) provider = described_class.new(resource) provider.exists?.should == 'http://192.168.1.1:8080' provider.value.should == 'http://192.168.1.1:8080' provider.value=('http://192.168.0.1:8080') validate_file( <<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.0.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS ) end it "should recognize an existing setting with the specified value" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :setting => 'baz', :value => 'bazvalue')) provider = described_class.new(resource) provider.exists?.should == 'bazvalue' end it "should add a new section if the section does not exist" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section3", :setting => 'huzzah', :value => 'shazaam')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment [section3] huzzah = shazaam EOS ) end it "should add a new section if the section does not exist - with colon" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section:subsection", :setting => 'huzzah', :value => 'shazaam')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment [section:subsection] huzzah = shazaam EOS ) end it "should add a new section if no sections exists" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section1", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile)) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(" [section1] setting1 = hellowworld ", emptyfile) end it "should add a new section with colon if no sections exists" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section:subsection", :setting => 'setting1', :value => 'hellowworld', :path => emptyfile)) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(" [section:subsection] setting1 = hellowworld ", emptyfile) end it "should be able to handle variables of any type" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => "section1", :setting => 'master', :value => true)) provider = described_class.new(resource) provider.exists?.should == 'true' provider.value.should == 'true' end end context "when dealing with a global section" do let(:orig_content) { <<-EOS # This is a comment foo=blah [section2] foo = http://192.168.1.1:8080 ; yet another comment EOS } it "should add a missing setting if it doesn't exist" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'bar', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment foo=blah bar = yippee [section2] foo = http://192.168.1.1:8080 ; yet another comment EOS ) end it "should modify an existing setting with a different value" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'foo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should == 'blah' provider.value.should == 'blah' provider.value=('yippee') validate_file(<<-EOS # This is a comment foo=yippee [section2] foo = http://192.168.1.1:8080 ; yet another comment EOS ) end it "should recognize an existing setting with the specified value" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'foo', :value => 'blah')) provider = described_class.new(resource) provider.exists?.should == 'blah' end end context "when the first line of the file is a section" do let(:orig_content) { <<-EOS [section2] foo = http://192.168.1.1:8080 EOS } it "should be able to add a global setting" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => '', :setting => 'foo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS foo = yippee [section2] foo = http://192.168.1.1:8080 EOS ) end it "should modify an existing setting" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'foo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should == 'http://192.168.1.1:8080' provider.value.should == 'http://192.168.1.1:8080' provider.value=('yippee') validate_file(<<-EOS [section2] foo = yippee EOS ) end it "should add a new setting" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'bar', :value => 'baz')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS [section2] foo = http://192.168.1.1:8080 bar = baz EOS ) end end context "when overriding the separator" do let(:orig_content) { <<-EOS [section2] foo=bar EOS } it "should fail if the separator doesn't include an equals sign" do expect { Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'foo', :value => 'yippee', :key_val_separator => '+')) }.to raise_error Puppet::Error, /must contain exactly one/ end it "should fail if the separator includes more than one equals sign" do expect { Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'foo', :value => 'yippee', :key_val_separator => ' = foo = ')) }.to raise_error Puppet::Error, /must contain exactly one/ end it "should modify an existing setting" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'foo', :value => 'yippee', :key_val_separator => '=')) provider = described_class.new(resource) provider.exists?.should == 'bar' provider.value.should == 'bar' provider.value=('yippee') validate_file(<<-EOS [section2] foo=yippee EOS ) end it "should add a new setting" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'bar', :value => 'baz', :key_val_separator => '=')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS [section2] foo=bar bar=baz EOS ) end end context "when ensuring that a setting is absent" do let(:orig_content) { <<-EOS [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS } it "should remove a setting that exists" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section1', :setting => 'foo', :ensure => 'absent')) provider = described_class.new(resource) provider.exists?.should be_true provider.destroy validate_file(<<-EOS [section1] ; This is also a comment bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS ) end it "should do nothing for a setting that does not exist" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section:sub', :setting => 'foo', :ensure => 'absent')) provider = described_class.new(resource) provider.exists?.should be_nil provider.destroy validate_file(<<-EOS [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment ; yet another comment EOS ) end end context "when dealing with indentation in sections" do let(:orig_content) { <<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment fleezy = flam ; yet another comment EOS } it "should add a missing setting at the correct indentation when the header is aligned" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section1', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true yahoo = yippee [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment fleezy = flam ; yet another comment EOS ) end it "should update an existing setting at the correct indentation when the header is aligned" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section1', :setting => 'bar', :value => 'barvalue2')) provider = described_class.new(resource) provider.exists?.should be_true provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue2 master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment fleezy = flam ; yet another comment EOS ) end it "should add a missing setting at the correct indentation when the header is not aligned" do resource = Puppet::Type::Ini_setting.new(common_params.merge( :section => 'section2', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 yahoo = yippee [section:sub] subby=bar #another comment fleezy = flam ; yet another comment EOS ) end it "should update an existing setting at the correct indentation when the header is not aligned" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'baz', :value => 'bazvalue2')) provider = described_class.new(resource) provider.exists?.should be_true provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue2 url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment fleezy = flam ; yet another comment EOS ) end it "should add a missing setting at the min indentation when the section is not aligned" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section:sub', :setting => 'yahoo', :value => 'yippee')) provider = described_class.new(resource) provider.exists?.should be_nil provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment fleezy = flam ; yet another comment yahoo = yippee EOS ) end it "should update an existing setting at the previous indentation when the section is not aligned" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section:sub', :setting => 'fleezy', :value => 'flam2')) provider = described_class.new(resource) provider.exists?.should be_true provider.create validate_file(<<-EOS # This is a comment [section1] ; This is also a comment foo=foovalue bar = barvalue master = true [section2] foo= foovalue2 baz=bazvalue url = http://192.168.1.1:8080 [section:sub] subby=bar #another comment fleezy = flam2 ; yet another comment EOS ) end end context "when dealing settings that have a commented version present" do let(:orig_content) { <<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue ;bar=barvalue blah = blah #baz= EOS } it "should add a new setting below a commented version of that setting" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'foo', :value => 'foo3')) provider = described_class.new(resource) provider.exists?.should be_false provider.create validate_file(<<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue foo = foo3 ;bar=barvalue blah = blah #baz= EOS ) end it "should update an existing setting in place, even if there is a commented version of that setting" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section1', :setting => 'foo', :value => 'foo3')) provider = described_class.new(resource) provider.exists?.should be_true provider.create validate_file(<<-EOS [section1] # foo=foovalue bar=barvalue foo = foo3 [section2] # foo = foovalue ;bar=barvalue blah = blah #baz= EOS ) end it "should add a new setting below a commented version of that setting, respecting semicolons as comments" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'bar', :value => 'bar3')) provider = described_class.new(resource) provider.exists?.should be_false provider.create validate_file(<<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue ;bar=barvalue bar=bar3 blah = blah #baz= EOS ) end it "should add a new setting below an empty commented version of that setting" do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section2', :setting => 'baz', :value => 'bazvalue')) provider = described_class.new(resource) provider.exists?.should be_false provider.create validate_file(<<-EOS [section1] # foo=foovalue bar=barvalue foo = foovalue2 [section2] # foo = foovalue ;bar=barvalue blah = blah #baz= baz=bazvalue EOS ) end context 'when a section only contains comments' do let(:orig_content) { <<-EOS [section1] # foo=foovalue # bar=bar2 EOS } it 'should be able to add a new setting when a section contains only comments' do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section1', :setting => 'foo', :value => 'foovalue2') ) provider = described_class.new(resource) provider.exists?.should be_false provider.create validate_file(<<-EOS [section1] # foo=foovalue foo=foovalue2 # bar=bar2 EOS ) end it 'should be able to add a new setting when it matches a commented out line other than the first one' do resource = Puppet::Type::Ini_setting.new( common_params.merge(:section => 'section1', :setting => 'bar', :value => 'barvalue2') ) provider = described_class.new(resource) provider.exists?.should be_false provider.create validate_file(<<-EOS [section1] # foo=foovalue # bar=bar2 bar=barvalue2 EOS ) end end end end puppetlabs-inifile-1.0.0/spec/fixtures/manifests/000755 000765 000024 00000000000 12171506567 022714 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/000755 000765 000024 00000000000 12171506567 022373 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/tmp/000755 000765 000024 00000000000 12171506567 021523 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/tmp/.empty000644 000765 000024 00000000000 12171506567 022650 0ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_ini_setting/000755 000765 000024 00000000000 12171506567 026431 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_test1/000755 000765 000024 00000000000 12171506567 025155 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_test1/manifests/000755 000765 000024 00000000000 12171506567 027146 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_test1/manifests/init.pp000644 000765 000024 00000000125 12171506567 030450 0ustar00apenneystaff000000 000000 class inherit_test1 { inherit_ini_setting { 'valid_type': value => true, } } puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_ini_setting/lib/000755 000765 000024 00000000000 12171506567 027177 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_ini_setting/lib/puppet/000755 000765 000024 00000000000 12171506567 030514 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_ini_setting/lib/puppet/provider/000755 000765 000024 00000000000 12171506567 032346 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/spec/fixtures/modules/inherit_ini_setting/lib/puppet/type/000755 000765 000024 00000000000 12171506567 031475 5ustar00apenneystaff000000 000000 spec/fixtures/modules/inherit_ini_setting/lib/puppet/type/inherit_ini_setting.rb000644 000765 000024 00000000173 12171506567 036002 0ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0Puppet::Type.newtype(:inherit_ini_setting) do ensurable newparam(:setting, :namevar => true) newproperty(:value) end spec/fixtures/modules/inherit_ini_setting/lib/puppet/provider/inherit_ini_setting/000755 000765 000024 00000000000 12171506567 036325 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0spec/fixtures/modules/inherit_ini_setting/lib/puppet/provider/inherit_ini_setting/ini_setting.rb000644 000765 000024 00000000602 12171506567 041164 0ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0Puppet::Type.type(:inherit_ini_setting).provide( :ini_setting, :parent => Puppet::Type.type(:ini_setting).provider(:ruby) ) do def section '' # all global end # This type has no sections def self.namevar(section_name, setting) setting end def self.file_path File.expand_path(File.dirname(__FILE__) + '/../../../../../../tmp/inherit_inifile.cfg') end end puppetlabs-inifile-1.0.0/spec/classes/inherit_test1_spec.rb000644 000765 000024 00000000370 12171506567 024630 0ustar00apenneystaff000000 000000 require 'spec_helper' # We can't really test much here, apart from the type roundtrips though the # parser OK. describe 'inherit_test1' do it do should contain_inherit_ini_setting('valid_type').with({ 'value' => 'true' }) end end puppetlabs-inifile-1.0.0/lib/puppet/000755 000765 000024 00000000000 12171506567 020203 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/provider/000755 000765 000024 00000000000 12171506567 022035 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/type/000755 000765 000024 00000000000 12171506567 021164 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/util/000755 000765 000024 00000000000 12171506567 021160 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/util/external_iterator.rb000644 000765 000024 00000000641 12171506567 025241 0ustar00apenneystaff000000 000000 module Puppet module Util class ExternalIterator def initialize(coll) @coll = coll @cur_index = -1 end def next @cur_index = @cur_index + 1 item_at(@cur_index) end def peek item_at(@cur_index + 1) end private def item_at(index) if @coll.length > index [@coll[index], index] else [nil, nil] end end end end end puppetlabs-inifile-1.0.0/lib/puppet/util/ini_file/000755 000765 000024 00000000000 12171506567 022736 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/util/ini_file.rb000644 000765 000024 00000024342 12171506567 023270 0ustar00apenneystaff000000 000000 require File.expand_path('../external_iterator', __FILE__) require File.expand_path('../ini_file/section', __FILE__) module Puppet module Util class IniFile @@SECTION_REGEX = /^\s*\[([\w\d\.\\\/\-\:]+)\]\s*$/ @@SETTING_REGEX = /^(\s*)([\w\d\.\\\/\-\s]*[\w\d\.\\\/\-])([ \t]*=[ \t]*)([\S\s]*?)\s*$/ @@COMMENTED_SETTING_REGEX = /^(\s*)[#;]+(\s*)([\w\d\.\\\/\-]+)([ \t]*=[ \t]*)([\S\s]*?)\s*$/ def initialize(path, key_val_separator = ' = ') @path = path @key_val_separator = key_val_separator @section_names = [] @sections_hash = {} if File.file?(@path) parse_file end end def section_names @section_names end def get_settings(section_name) section = @sections_hash[section_name] section.setting_names.inject({}) do |result, setting| result[setting] = section.get_value(setting) result end end def get_value(section_name, setting) if (@sections_hash.has_key?(section_name)) @sections_hash[section_name].get_value(setting) end end def set_value(section_name, setting, value) unless (@sections_hash.has_key?(section_name)) add_section(Section.new(section_name, nil, nil, nil, nil)) end section = @sections_hash[section_name] if (section.has_existing_setting?(setting)) update_line(section, setting, value) section.update_existing_setting(setting, value) elsif result = find_commented_setting(section, setting) # So, this stanza is a bit of a hack. What we're trying # to do here is this: for settings that don't already # exist, we want to take a quick peek to see if there # is a commented-out version of them in the section. # If so, we'd prefer to add the setting directly after # the commented line, rather than at the end of the section. # If we get here then we found a commented line, so we # call "insert_inline_setting_line" to update the lines array insert_inline_setting_line(result, section, setting, value) # Then, we need to tell the setting object that we hacked # in an inline setting section.insert_inline_setting(setting, value) # Finally, we need to update all of the start/end line # numbers for all of the sections *after* the one that # was modified. section_index = @section_names.index(section_name) increment_section_line_numbers(section_index + 1) else section.set_additional_setting(setting, value) end end def remove_setting(section_name, setting) section = @sections_hash[section_name] if (section.has_existing_setting?(setting)) # If the setting is found, we have some work to do. # First, we remove the line from our array of lines: remove_line(section, setting) # Then, we need to tell the setting object to remove # the setting from its state: section.remove_existing_setting(setting) # Finally, we need to update all of the start/end line # numbers for all of the sections *after* the one that # was modified. section_index = @section_names.index(section_name) decrement_section_line_numbers(section_index + 1) end end def save File.open(@path, 'w') do |fh| @section_names.each_index do |index| name = @section_names[index] section = @sections_hash[name] # We need a buffer to cache lines that are only whitespace whitespace_buffer = [] if (section.is_new_section?) && (! section.is_global?) fh.puts("\n[#{section.name}]") end if ! section.is_new_section? # write all of the pre-existing settings (section.start_line..section.end_line).each do |line_num| line = lines[line_num] # We buffer any lines that are only whitespace so that # if they are at the end of a section, we can insert # any new settings *before* the final chunk of whitespace # lines. if (line =~ /^\s*$/) whitespace_buffer << line else # If we get here, we've found a non-whitespace line. # We'll flush any cached whitespace lines before we # write it. flush_buffer_to_file(whitespace_buffer, fh) fh.puts(line) end end end # write new settings, if there are any section.additional_settings.each_pair do |key, value| fh.puts("#{' ' * (section.indentation || 0)}#{key}#{@key_val_separator}#{value}") end if (whitespace_buffer.length > 0) flush_buffer_to_file(whitespace_buffer, fh) else # We get here if there were no blank lines at the end of the # section. # # If we are adding a new section with a new setting, # and if there are more sections that come after this one, # we'll write one blank line just so that there is a little # whitespace between the sections. #if (section.end_line.nil? && if (section.is_new_section? && (section.additional_settings.length > 0) && (index < @section_names.length - 1)) fh.puts("") end end end end end private def add_section(section) @sections_hash[section.name] = section @section_names << section.name end def parse_file line_iter = create_line_iter # We always create a "global" section at the beginning of the file, for # anything that appears before the first named section. section = read_section('', 0, line_iter) add_section(section) line, line_num = line_iter.next while line if (match = @@SECTION_REGEX.match(line)) section = read_section(match[1], line_num, line_iter) add_section(section) end line, line_num = line_iter.next end end def read_section(name, start_line, line_iter) settings = {} end_line_num = nil min_indentation = nil while true line, line_num = line_iter.peek if (line_num.nil? or match = @@SECTION_REGEX.match(line)) return Section.new(name, start_line, end_line_num, settings, min_indentation) elsif (match = @@SETTING_REGEX.match(line)) settings[match[2]] = match[4] indentation = match[1].length min_indentation = [indentation, min_indentation || indentation].min end end_line_num = line_num line_iter.next end end def update_line(section, setting, value) (section.start_line..section.end_line).each do |line_num| if (match = @@SETTING_REGEX.match(lines[line_num])) if (match[2] == setting) lines[line_num] = "#{match[1]}#{match[2]}#{match[3]}#{value}" end end end end def remove_line(section, setting) (section.start_line..section.end_line).each do |line_num| if (match = @@SETTING_REGEX.match(lines[line_num])) if (match[2] == setting) lines.delete_at(line_num) end end end end def create_line_iter ExternalIterator.new(lines) end def lines @lines ||= IniFile.readlines(@path) end # This is mostly here because it makes testing easier--we don't have # to try to stub any methods on File. def self.readlines(path) # If this type is ever used with very large files, we should # write this in a different way, using a temp # file; for now assuming that this type is only used on # small-ish config files that can fit into memory without # too much trouble. File.readlines(path) end # This utility method scans through the lines for a section looking for # commented-out versions of a setting. It returns `nil` if it doesn't # find one. If it does find one, then it returns a hash containing # two keys: # # :line_num - the line number that contains the commented version # of the setting # :match - the ruby regular expression match object, which can # be used to mimic the whitespace from the comment line def find_commented_setting(section, setting) return nil if section.is_new_section? (section.start_line..section.end_line).each do |line_num| if (match = @@COMMENTED_SETTING_REGEX.match(lines[line_num])) if (match[3] == setting) return { :match => match, :line_num => line_num } end end end nil end # This utility method is for inserting a line into the existing # lines array. The `result` argument is expected to be in the # format of the return value of `find_commented_setting`. def insert_inline_setting_line(result, section, setting, value) line_num = result[:line_num] match = result[:match] lines.insert(line_num + 1, "#{' ' * (section.indentation || 0 )}#{setting}#{match[4]}#{value}") end # Utility method; given a section index (index into the @section_names # array), decrement the start/end line numbers for that section and all # all of the other sections that appear *after* the specified section. def decrement_section_line_numbers(section_index) @section_names[section_index..(@section_names.length - 1)].each do |name| section = @sections_hash[name] section.decrement_line_nums end end # Utility method; given a section index (index into the @section_names # array), increment the start/end line numbers for that section and all # all of the other sections that appear *after* the specified section. def increment_section_line_numbers(section_index) @section_names[section_index..(@section_names.length - 1)].each do |name| section = @sections_hash[name] section.increment_line_nums end end def flush_buffer_to_file(buffer, fh) if buffer.length > 0 buffer.each { |l| fh.puts(l) } buffer.clear end end end end end puppetlabs-inifile-1.0.0/lib/puppet/util/setting_value.rb000644 000765 000024 00000004243 12171506567 024361 0ustar00apenneystaff000000 000000 module Puppet module Util class SettingValue def initialize(setting_value, subsetting_separator = ' ') @setting_value = setting_value @subsetting_separator = subsetting_separator @quote_char = "" if @setting_value unquoted, @quote_char = unquote_setting_value(setting_value) @subsetting_items = unquoted.scan(Regexp.new("(?:(?:[^\\#{@subsetting_separator}]|\\.)+)")) # an item can contain escaped separator @subsetting_items.map! { |item| item.strip } else @subsetting_items = [] end end def unquote_setting_value(setting_value) quote_char = "" if (setting_value.start_with?('"') and setting_value.end_with?('"')) quote_char = '"' elsif (setting_value.start_with?("'") and setting_value.end_with?("'")) quote_char = "'" end unquoted = setting_value if (quote_char != "") unquoted = setting_value[1, setting_value.length - 2] end [unquoted, quote_char] end def get_value result = "" first = true @subsetting_items.each { |item| result << @subsetting_separator unless first result << item first = false } @quote_char + result + @quote_char end def get_subsetting_value(subsetting) value = nil @subsetting_items.each { |item| if(item.start_with?(subsetting)) value = item[subsetting.length, item.length - subsetting.length] break end } value end def add_subsetting(subsetting, subsetting_value) new_item = subsetting + (subsetting_value || '') found = false @subsetting_items.map! { |item| if item.start_with?(subsetting) value = new_item found = true else value = item end value } unless found @subsetting_items.push(new_item) end end def remove_subsetting(subsetting) @subsetting_items = @subsetting_items.map { |item| item.start_with?(subsetting) ? nil : item }.compact end end end end puppetlabs-inifile-1.0.0/lib/puppet/util/ini_file/section.rb000644 000765 000024 00000006102 12171506567 024726 0ustar00apenneystaff000000 000000 module Puppet module Util class IniFile class Section # Some implementation details: # # * `name` will be set to the empty string for the 'global' section. # * there will always be a 'global' section, with a `start_line` of 0, # but if the file actually begins with a real section header on # the first line, then the 'global' section will have an # `end_line` of `nil`. # * `start_line` and `end_line` will be set to `nil` for a new non-global # section. def initialize(name, start_line, end_line, settings, indentation) @name = name @start_line = start_line @end_line = end_line @existing_settings = settings.nil? ? {} : settings @additional_settings = {} @indentation = indentation end attr_reader :name, :start_line, :end_line, :additional_settings, :indentation def is_global?() @name == '' end def is_new_section?() # a new section (global or named) will always have `end_line` # set to `nil` @end_line.nil? end def setting_names @existing_settings.keys | @additional_settings.keys end def get_value(setting_name) @existing_settings[setting_name] || @additional_settings[setting_name] end def has_existing_setting?(setting_name) @existing_settings.has_key?(setting_name) end def update_existing_setting(setting_name, value) @existing_settings[setting_name] = value end def remove_existing_setting(setting_name) if (@existing_settings.delete(setting_name)) if @end_line @end_line = @end_line - 1 end end end # This is a hacky method; it's basically called when we need to insert # a new setting but we don't want it to appear at the very end of the # section. Instead we hack it into the existing settings list and # increment our end_line number--this assumes that the caller (`ini_file`) # is doing some babysitting w/rt the other sections and the actual data # of the lines. def insert_inline_setting(setting_name, value) @existing_settings[setting_name] = value if @end_line @end_line = @end_line + 1 end end def set_additional_setting(setting_name, value) @additional_settings[setting_name] = value end # Decrement the start and end line numbers for the section (if they are # defined); this is intended to be called when a setting is removed # from a section that comes before this section in the ini file. def decrement_line_nums() if @start_line @start_line = @start_line - 1 end if @end_line @end_line = @end_line - 1 end end # Increment the start and end line numbers for the section (if they are # defined); this is intended to be called when an inline setting is added # to a section that comes before this section in the ini file. def increment_line_nums() if @start_line @start_line = @start_line + 1 end if @end_line @end_line = @end_line + 1 end end end end end end puppetlabs-inifile-1.0.0/lib/puppet/type/ini_setting.rb000644 000765 000024 00000002471 12171506567 024031 0ustar00apenneystaff000000 000000 Puppet::Type.newtype(:ini_setting) do ensurable do defaultvalues defaultto :present end newparam(:name, :namevar => true) do desc 'An arbitrary name used as the identity of the resource.' end newparam(:section) do desc 'The name of the section in the ini file in which the setting should be defined.' end newparam(:setting) do desc 'The name of the setting to be defined.' end newparam(:path) do desc 'The ini file Puppet will ensure contains the specified setting.' validate do |value| unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/)) raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'") end end end newparam(:key_val_separator) do desc 'The separator string to use between each setting name and value. ' + 'Defaults to " = ", but you could use this to override e.g. whether ' + 'or not the separator should include whitespace.' defaultto(" = ") validate do |value| unless value.scan('=').size == 1 raise Puppet::Error, ":key_val_separator must contain exactly one = character." end end end newproperty(:value) do desc 'The value of the setting to be defined.' end end puppetlabs-inifile-1.0.0/lib/puppet/type/ini_subsetting.rb000644 000765 000024 00000003031 12171506567 024534 0ustar00apenneystaff000000 000000 Puppet::Type.newtype(:ini_subsetting) do ensurable do defaultvalues defaultto :present end newparam(:name, :namevar => true) do desc 'An arbitrary name used as the identity of the resource.' end newparam(:section) do desc 'The name of the section in the ini file in which the setting should be defined.' end newparam(:setting) do desc 'The name of the setting to be defined.' end newparam(:subsetting) do desc 'The name of the subsetting to be defined.' end newparam(:subsetting_separator) do desc 'The separator string between subsettings. Defaults to " "' defaultto(" ") end newparam(:path) do desc 'The ini file Puppet will ensure contains the specified setting.' validate do |value| unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/)) raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'") end end end newparam(:key_val_separator) do desc 'The separator string to use between each setting name and value. ' + 'Defaults to " = ", but you could use this to override e.g. whether ' + 'or not the separator should include whitespace.' defaultto(" = ") validate do |value| unless value.scan('=').size == 1 raise Puppet::Error, ":key_val_separator must contain exactly one = character." end end end newproperty(:value) do desc 'The value of the subsetting to be defined.' end end puppetlabs-inifile-1.0.0/lib/puppet/provider/ini_setting/000755 000765 000024 00000000000 12171506567 024351 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/provider/ini_subsetting/000755 000765 000024 00000000000 12171506567 025063 5ustar00apenneystaff000000 000000 puppetlabs-inifile-1.0.0/lib/puppet/provider/ini_subsetting/ruby.rb000644 000765 000024 00000002703 12171506567 026373 0ustar00apenneystaff000000 000000 require File.expand_path('../../../util/ini_file', __FILE__) require File.expand_path('../../../util/setting_value', __FILE__) Puppet::Type.type(:ini_subsetting).provide(:ruby) do def exists? setting_value.get_subsetting_value(subsetting) end def create setting_value.add_subsetting(subsetting, resource[:value]) ini_file.set_value(section, setting, setting_value.get_value) ini_file.save @ini_file = nil @setting_value = nil end def destroy setting_value.remove_subsetting(subsetting) ini_file.set_value(section, setting, setting_value.get_value) ini_file.save @ini_file = nil @setting_value = nil end def value setting_value.get_subsetting_value(subsetting) end def value=(value) setting_value.add_subsetting(subsetting, resource[:value]) ini_file.set_value(section, setting, setting_value.get_value) ini_file.save end def section resource[:section] end def setting resource[:setting] end def subsetting resource[:subsetting] end def subsetting_separator resource[:subsetting_separator] end def file_path resource[:path] end def separator resource[:key_val_separator] || '=' end private def ini_file @ini_file ||= Puppet::Util::IniFile.new(file_path, separator) end private def setting_value @setting_value ||= Puppet::Util::SettingValue.new(ini_file.get_value(section, setting), subsetting_separator) end end puppetlabs-inifile-1.0.0/lib/puppet/provider/ini_setting/ruby.rb000644 000765 000024 00000005506 12171506567 025665 0ustar00apenneystaff000000 000000 require File.expand_path('../../../util/ini_file', __FILE__) Puppet::Type.type(:ini_setting).provide(:ruby) do def self.instances # this code is here to support purging and the query-all functionality of the # 'puppet resource' command, on a per-file basis. Users # can create a type for a specific config file with a provider that uses # this as its parent and implements the method # 'self.file_path', and that will provide the value for the path to the # ini file (rather than needing to specify it on each ini setting # declaration). This allows 'purging' to be used to clear out # all settings from a particular ini file except those included in # the catalog. if self.respond_to?(:file_path) # figure out what to do about the seperator ini_file = Puppet::Util::IniFile.new(file_path, '=') resources = [] ini_file.section_names.each do |section_name| ini_file.get_settings(section_name).each do |setting, value| resources.push( new( :name => namevar(section_name, setting), :value => value, :ensure => :present ) ) end end resources else raise(Puppet::Error, 'Ini_settings only support collecting instances when a file path is hard coded') end end def self.namevar(section_name, setting) "#{section_name}/#{setting}" end def exists? ini_file.get_value(section, setting) end def create ini_file.set_value(section, setting, resource[:value]) ini_file.save @ini_file = nil end def destroy ini_file.remove_setting(section, setting) ini_file.save @ini_file = nil end def value ini_file.get_value(section, setting) end def value=(value) ini_file.set_value(section, setting, resource[:value]) ini_file.save end def section # this method is here so that it can be overridden by a child provider resource[:section] end def setting # this method is here so that it can be overridden by a child provider resource[:setting] end def file_path # this method is here to support purging and sub-classing. # if a user creates a type and subclasses our provider and provides a # 'file_path' method, then they don't have to specify the # path as a parameter for every ini_setting declaration. # This implementation allows us to support that while still # falling back to the parameter value when necessary. if self.class.respond_to?(:file_path) self.class.file_path else resource[:path] end end def separator if resource.class.validattr?(:key_val_separator) resource[:key_val_separator] || '=' else '=' end end private def ini_file @ini_file ||= Puppet::Util::IniFile.new(file_path, separator) end end