Sync inifile with upstream

v1.1.3 41e2ddbc1cd861247e57d16b778cbe891602f509
Partial blueprint merge-openstack-puppet-modules

Change-Id: Idd6b512a4adafc31cd0c80ccf0ca59a18b43d98e
This commit is contained in:
Aleksandr Didenko 2014-09-04 16:51:16 +03:00
parent bc23f1359b
commit 81e85f0766
50 changed files with 2444 additions and 157 deletions

View File

@ -0,0 +1,3 @@
fixtures:
symlinks:
inifile: "#{source_dir}"

View File

@ -1,6 +1,7 @@
*.swp
pkg/
.DS_Store
metadata.json
Gemfile.lock
vendor/
spec/fixtures/
.vagrant/
.bundle/
coverage/

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>inifile</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.cloudsmith.geppetto.pp.dsl.ui.modulefileBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.cloudsmith.geppetto.pp.dsl.ui.puppetNature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,3 @@
---
spec/spec_helper.rb:
unmanaged: true

View File

@ -0,0 +1,17 @@
---
language: ruby
bundler_args: --without development
script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'"
matrix:
fast_finish: true
include:
- rvm: 1.8.7
env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0"
- rvm: 1.8.7
env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0"
- rvm: 1.9.3
env: PUPPET_GEM_VERSION="~> 3.0"
- rvm: 2.0.0
env: PUPPET_GEM_VERSION="~> 3.0"
notifications:
email: false

View File

@ -1,47 +0,0 @@
2012-11-02 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Version 0.9.0 released
2012-10-26 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Add detection for commented versions of settings (a45ab65)
2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Refactor to clarify implementation of `save` (f0d443f)
2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Add example for `ensure=absent` (e517148)
2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Better handling of whitespace lines at ends of sections (845fa70)
2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Respect indentation / spacing for existing sections and settings (c2c26de)
2012-10-17 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Minor tweaks to handling of removing settings (cda30a6)
2012-10-10 - Dan Bode <dan@puppetlabs.com> - 0.9.0
* Add support for removing lines (1106d70)
2012-10-02 - Dan Bode <dan@puppetlabs.com> - 0.9.0
* Make value a property (cbc90d3)
2012-10-02 - Dan Bode <dan@puppetlabs.com> - 0.9.0
* Make ruby provider a better parent. (1564c47)
2012-09-29 - Reid Vandewiele <reid@puppetlabs.com> - 0.9.0
* Allow values with spaces to be parsed and set (3829e20)
2012-09-24 - Chris Price <chris@pupppetlabs.com> - 0.0.3
* Version 0.0.3 released
2012-09-20 - Chris Price <chris@puppetlabs.com> - 0.0.3
* Add validation for key_val_separator (e527908)
2012-09-19 - Chris Price <chris@puppetlabs.com> - 0.0.3
* Allow overriding separator string between key/val pairs (8d1fdc5)
2012-08-20 - Chris Price <chris@pupppetlabs.com> - 0.0.2
* Version 0.0.2 released
2012-08-17 - Chris Price <chris@pupppetlabs.com> - 0.0.2
* Add support for "global" section at beginning of file (c57dab4)

View File

@ -0,0 +1,177 @@
##2014-07-15 - Supported Release 1.1.3
###Summary
This release merely updates metadata.json so the module can be uninstalled and
upgraded via the puppet module command.
##2014-07-10 - Supported Release 1.1.2
###Summary
This is a re-packaging release.
##2014-07-07 - Release 1.1.1
###Summary
This supported bugfix release corrects the inifile section header detection
regex (so you can use more characters in your section titles).
####Bugfixes
- Correct section regex to allow anything other than ]
- Correct `exists?` to return a boolean
- Lots of test updates
- Add missing CONTRIBUTING.md
##2014-06-04 - Release 1.1.0
###Summary
This is a compatibility and feature release. This release adds one new
feature, the ability to control the quote character used. This allows you to
do things like:
```
ini_subsetting { '-Xms':
ensure => present,
path => '/some/config/file',
section => '',
setting => 'JAVA_ARGS',
quote_char => '"',
subsetting => '-Xms'
value => '256m',
}
```
Which builds:
```
JAVA_ARGS="-Xmx256m -Xms256m"
```
####Features
- Add quote_char parameter to the ini_subsetting resource type
####Bugfixes
####Known Bugs
* No known bugs
##2014-03-04 - Supported Release 1.0.3
###Summary
This is a supported release. It has only test changes.
####Features
####Bugfixes
####Known Bugs
* No known bugs
##2014-02-26 - Version 1.0.2
###Summary
This release adds supported platforms to metadata.json and contains spec fixes
##2014-02-12 - Version 1.0.1
###Summary
This release is a bugfix for handling whitespace/[]'s better, and adding a
bunch of tests.
####Bugfixes
- Handle whitespace in sections
- Handle square brances in values
- Add metadata.json
- Update some travis testing
- Tons of beaker-rspec tests
##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 <chris@puppetlabs.com> - 0.10.3
* Fix bug in subsetting handling for new settings (cbea5dc)
##2013-05-22 - Chris Price <chris@puppetlabs.com> - 0.10.2
* Better handling of quotes for subsettings (1aa7e60)
##2013-05-21 - Chris Price <chris@puppetlabs.com> - 0.10.1
* Change constants to class variables to avoid ruby warnings (6b19864)
##2013-04-10 - Erik Dalén <dalen@spotify.com> - 0.10.1
* Style fixes (c4af8c3)
##2013-04-02 - Dan Bode <dan@puppetlabs.com> - 0.10.1
* Add travisfile and Gemfile (c2052b3)
##2013-04-02 - Chris Price <chris@puppetlabs.com> - 0.10.1
* Update README.markdown (ad38a08)
##2013-02-15 - Karel Brezina <karel.brezina@gmail.com> - 0.10.0
* Added 'ini_subsetting' custom resource type (4351d8b)
##2013-03-11 - Dan Bode <dan@puppetlabs.com> - 0.10.0
* guard against nil indentation values (5f71d7f)
##2013-01-07 - Dan Bode <dan@puppetlabs.com> - 0.10.0
* Add purging support to ini file (2f22483)
##2013-02-05 - James Sweeny <james.sweeny@puppetlabs.com> - 0.10.0
* Fix test to use correct key_val_parameter (b1aff63)
##2012-11-06 - Chris Price <chris@puppetlabs.com> - 0.10.0
* Added license file w/Apache 2.0 license (5e1d203)
##2012-11-02 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Version 0.9.0 released
##2012-10-26 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Add detection for commented versions of settings (a45ab65)
##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Refactor to clarify implementation of `save` (f0d443f)
##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Add example for `ensure=absent` (e517148)
##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Better handling of whitespace lines at ends of sections (845fa70)
##2012-10-20 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Respect indentation / spacing for existing sections and settings (c2c26de)
##2012-10-17 - Chris Price <chris@puppetlabs.com> - 0.9.0
* Minor tweaks to handling of removing settings (cda30a6)
##2012-10-10 - Dan Bode <dan@puppetlabs.com> - 0.9.0
* Add support for removing lines (1106d70)
##2012-10-02 - Dan Bode <dan@puppetlabs.com> - 0.9.0
* Make value a property (cbc90d3)
##2012-10-02 - Dan Bode <dan@puppetlabs.com> - 0.9.0
* Make ruby provider a better parent. (1564c47)
##2012-09-29 - Reid Vandewiele <reid@puppetlabs.com> - 0.9.0
* Allow values with spaces to be parsed and set (3829e20)
##2012-09-24 - Chris Price <chris@pupppetlabs.com> - 0.0.3
* Version 0.0.3 released
##2012-09-20 - Chris Price <chris@puppetlabs.com> - 0.0.3
* Add validation for key_val_separator (e527908)
##2012-09-19 - Chris Price <chris@puppetlabs.com> - 0.0.3
* Allow overriding separator string between key/val pairs (8d1fdc5)
##2012-08-20 - Chris Price <chris@pupppetlabs.com> - 0.0.2
* Version 0.0.2 released
##2012-08-17 - Chris Price <chris@pupppetlabs.com> - 0.0.2
* Add support for "global" section at beginning of file (c57dab4)

View File

@ -0,0 +1,234 @@
Checklist (and a short version for the impatient)
=================================================
* Commits:
- Make commits of logical units.
- Check for unnecessary whitespace with "git diff --check" before
committing.
- Commit using Unix line endings (check the settings around "crlf" in
git-config(1)).
- Do not check in commented out code or unneeded files.
- The first line of the commit message should be a short
description (50 characters is the soft limit, excluding ticket
number(s)), and should skip the full stop.
- Associate the issue in the message. The first line should include
the issue number in the form "(#XXXX) Rest of message".
- The body should provide a meaningful commit message, which:
- uses the imperative, present tense: "change", not "changed" or
"changes".
- includes motivation for the change, and contrasts its
implementation with the previous behavior.
- Make sure that you have tests for the bug you are fixing, or
feature you are adding.
- Make sure the test suites passes after your commit:
`bundle exec rspec spec/acceptance` More information on [testing](#Testing) below
- When introducing a new feature, make sure it is properly
documented in the README.md
* Submission:
* Pre-requisites:
- Sign the [Contributor License Agreement](https://cla.puppetlabs.com/)
- Make sure you have a [GitHub account](https://github.com/join)
- [Create a ticket](http://projects.puppetlabs.com/projects/modules/issues/new), or [watch the ticket](http://projects.puppetlabs.com/projects/modules/issues) you are patching for.
* Preferred method:
- Fork the repository on GitHub.
- Push your changes to a topic branch in your fork of the
repository. (the format ticket/1234-short_description_of_change is
usually preferred for this project).
- Submit a pull request to the repository in the puppetlabs
organization.
The long version
================
1. Make separate commits for logically separate changes.
Please break your commits down into logically consistent units
which include new or changed tests relevant to the rest of the
change. The goal of doing this is to make the diff easier to
read for whoever is reviewing your code. In general, the easier
your diff is to read, the more likely someone will be happy to
review it and get it into the code base.
If you are going to refactor a piece of code, please do so as a
separate commit from your feature or bug fix changes.
We also really appreciate changes that include tests to make
sure the bug is not re-introduced, and that the feature is not
accidentally broken.
Describe the technical detail of the change(s). If your
description starts to get too long, that is a good sign that you
probably need to split up your commit into more finely grained
pieces.
Commits which plainly describe the things which help
reviewers check the patch and future developers understand the
code are much more likely to be merged in with a minimum of
bike-shedding or requested changes. Ideally, the commit message
would include information, and be in a form suitable for
inclusion in the release notes for the version of Puppet that
includes them.
Please also check that you are not introducing any trailing
whitespace or other "whitespace errors". You can do this by
running "git diff --check" on your changes before you commit.
2. Sign the Contributor License Agreement
Before we can accept your changes, we do need a signed Puppet
Labs Contributor License Agreement (CLA).
You can access the CLA via the [Contributor License Agreement link](https://cla.puppetlabs.com/)
If you have any questions about the CLA, please feel free to
contact Puppet Labs via email at cla-submissions@puppetlabs.com.
3. Sending your patches
To submit your changes via a GitHub pull request, we _highly_
recommend that you have them on a topic branch, instead of
directly on "master".
It makes things much easier to keep track of, especially if
you decide to work on another thing before your first change
is merged in.
GitHub has some pretty good
[general documentation](http://help.github.com/) on using
their site. They also have documentation on
[creating pull requests](http://help.github.com/send-pull-requests/).
In general, after pushing your topic branch up to your
repository on GitHub, you can switch to the branch in the
GitHub UI and click "Pull Request" towards the top of the page
in order to open a pull request.
4. Update the related GitHub issue.
If there is a GitHub issue associated with the change you
submitted, then you should update the ticket to include the
location of your branch, along with any other commentary you
may wish to make.
Testing
=======
Getting Started
---------------
Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby
package manager such as [bundler](http://bundler.io/) what Ruby packages,
or Gems, are required to build, develop, and test this software.
Please make sure you have [bundler installed](http://bundler.io/#getting-started)
on your system, then use it to install all dependencies needed for this project,
by running
```shell
% bundle install
Fetching gem metadata from https://rubygems.org/........
Fetching gem metadata from https://rubygems.org/..
Using rake (10.1.0)
Using builder (3.2.2)
-- 8><-- many more --><8 --
Using rspec-system-puppet (2.2.0)
Using serverspec (0.6.3)
Using rspec-system-serverspec (1.0.0)
Using bundler (1.3.5)
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
```
NOTE some systems may require you to run this command with sudo.
If you already have those gems installed, make sure they are up-to-date:
```shell
% bundle update
```
With all dependencies in place and up-to-date we can now run the tests:
```shell
% rake spec
```
This will execute all the [rspec tests](http://rspec-puppet.com/) tests
under [spec/defines](./spec/defines), [spec/classes](./spec/classes),
and so on. rspec tests may have the same kind of dependencies as the
module they are testing. While the module defines in its [Modulefile](./Modulefile),
rspec tests define them in [.fixtures.yml](./fixtures.yml).
Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker)
tests. These tests spin up a virtual machine under
[VirtualBox](https://www.virtualbox.org/)) with, controlling it with
[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test
scenarios. In order to run these, you will need both of those tools
installed on your system.
You can run them by issuing the following command
```shell
% rake spec_clean
% rspec spec/acceptance
```
This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb)
and then run all the tests under [spec/acceptance](./spec/acceptance).
Writing Tests
-------------
XXX getting started writing tests.
If you have commit access to the repository
===========================================
Even if you have commit access to the repository, you will still need to
go through the process above, and have someone else review and merge
in your changes. The rule is that all changes must be reviewed by a
developer on the project (that did not write the code) to ensure that
all changes go through a code review process.
Having someone other than the author of the topic branch recorded as
performing the merge is the record that they performed the code
review.
Additional Resources
====================
* [Getting additional help](http://projects.puppetlabs.com/projects/puppet/wiki/Getting_Help)
* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
* [Patchwork](https://patchwork.puppetlabs.com)
* [Contributor License Agreement](https://projects.puppetlabs.com/contributor_licenses/sign)
* [General GitHub documentation](http://help.github.com/)
* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)

View File

@ -0,0 +1,28 @@
source ENV['GEM_SOURCE'] || "https://rubygems.org"
group :development, :test do
gem 'rake', :require => false
gem 'rspec', '~> 2.11', :require => false
gem 'rspec-puppet', :require => false
gem 'puppetlabs_spec_helper', :require => false
gem 'serverspec', :require => false
gem 'puppet-lint', :require => false
gem 'beaker', :require => false
gem 'beaker-rspec', '>= 2.2', :require => false
gem 'pry', :require => false
gem 'simplecov', :require => false
end
if facterversion = ENV['FACTER_GEM_VERSION']
gem 'facter', facterversion, :require => false
else
gem 'facter', :require => false
end
if puppetversion = ENV['PUPPET_GEM_VERSION']
gem 'puppet', puppetversion, :require => false
else
gem 'puppet', :require => false
end
# vim:ft=ruby

View File

@ -1,8 +0,0 @@
name 'cprice404-inifile'
version '0.9.0'
source 'git://github.com/cprice-puppet/puppetlabs-inifile.git'
author 'Chris Price'
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/cprice-puppet/puppetlabs-inifile'

View File

@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-inifile.png?branch=master)](https://travis-ci.org/puppetlabs/puppetlabs-inifile)
# INI-file module #
This module provides resource types for use in managing INI-style configuration
@ -5,14 +7,95 @@ 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":
ensure => present,
path => '/tmp/foo.ini',
section => 'foo',
setting => 'foosetting',
value => 'FOO!',
ensure => present,
}
A few noteworthy features:
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,

View File

@ -1 +1,10 @@
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-lint/tasks/puppet-lint'
PuppetLint.configuration.fail_on_warnings
PuppetLint.configuration.send('disable_80chars')
PuppetLint.configuration.send('disable_class_inherits_from_params_class')
PuppetLint.configuration.send('disable_class_parameter_defaults')
PuppetLint.configuration.send('disable_documentation')
PuppetLint.configuration.send('disable_single_quote_string_with_variables')
PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]

View File

@ -2,8 +2,43 @@ 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)
!ini_file.get_value(section, setting).nil?
end
def create
@ -28,19 +63,35 @@ Puppet::Type.type(:ini_setting).provide(:ruby) do
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
resource[: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
resource[:key_val_separator] || '='
if resource.class.validattr?(:key_val_separator)
resource[:key_val_separator] || '='
else
'='
end
end
private

View File

@ -0,0 +1,73 @@
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
def quote_char
resource[:quote_char]
end
private
def ini_file
@ini_file ||= Puppet::Util::IniFile.new(file_path, separator)
end
def setting_value
@setting_value ||= Puppet::Util::SettingValue.new(ini_file.get_value(section, setting), subsetting_separator, quote_char)
end
end

View File

@ -0,0 +1,67 @@
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
newparam(:quote_char) do
desc 'The character used to quote the entire value of the setting. ' +
%q{Valid values are '', '"' and "'". Defaults to ''.}
defaultto('')
validate do |value|
unless value =~ /^["']?$/
raise Puppet::Error, %q{:quote_char valid values are '', '"' and "'"}
end
end
end
newproperty(:value) do
desc 'The value of the subsetting to be defined.'
end
end

View File

@ -5,15 +5,9 @@ module Puppet
module Util
class IniFile
def section_regex
/^\s*\[([\w\d\.\\\/\-\:]+)\]\s*$/
end
def setting_regex
/^(\s*)([\w\d\.\\\/\-\s]*[\w\d\.\\\/\-])([ \t]*=[ \t]*)([\S\s]*?)\s*$/
end
def commented_setting_regex
/^(\s*)[#;]+(\s*)([\w\d\.\\\/\-]+)([ \t]*=[ \t]*)([\S\s]*?)\s*$/
end
@@SECTION_REGEX = /^\s*\[([^\]]*)\]\s*$/
@@SETTING_REGEX = /^(\s*)([^\[#;][\w\d\.\\\/\-\s\[\]\']*[\w\d\.\\\/\-\]])([ \t]*=[ \t]*)([\S\s]*?)\s*$/
@@COMMENTED_SETTING_REGEX = /^(\s*)[#;]+(\s*)([^\[]*[\w\d\.\\\/\-]+[\w\d\.\\\/\-\[\]\']+)([ \t]*=[ \t]*)([\S\s]*?)\s*$/
def initialize(path, key_val_separator = ' = ')
@path = path
@ -29,6 +23,14 @@ module Util
@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)
@ -37,7 +39,7 @@ module Util
def set_value(section_name, setting, value)
unless (@sections_hash.has_key?(section_name))
add_section(Section.new(section_name, nil, nil, nil, 0))
add_section(Section.new(section_name, nil, nil, nil, nil))
end
section = @sections_hash[section_name]
@ -170,7 +172,7 @@ module Util
line, line_num = line_iter.next
while line
if (match = section_regex.match(line))
if (match = @@SECTION_REGEX.match(line))
section = read_section(match[1], line_num, line_iter)
add_section(section)
end
@ -184,9 +186,9 @@ module Util
min_indentation = nil
while true
line, line_num = line_iter.peek
if (line_num.nil? or match = section_regex.match(line))
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))
elsif (match = @@SETTING_REGEX.match(line))
settings[match[2]] = match[4]
indentation = match[1].length
min_indentation = [indentation, min_indentation || indentation].min
@ -198,7 +200,7 @@ module Util
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 = @@SETTING_REGEX.match(lines[line_num]))
if (match[2] == setting)
lines[line_num] = "#{match[1]}#{match[2]}#{match[3]}#{value}"
end
@ -208,7 +210,7 @@ module Util
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 = @@SETTING_REGEX.match(lines[line_num]))
if (match[2] == setting)
lines.delete_at(line_num)
end
@ -247,7 +249,7 @@ module Util
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 = @@COMMENTED_SETTING_REGEX.match(lines[line_num]))
if (match[3] == setting)
return { :match => match, :line_num => line_num }
end
@ -262,7 +264,7 @@ module Util
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}")
lines.insert(line_num + 1, "#{' ' * (section.indentation || 0 )}#{setting}#{match[4]}#{value}")
end
# Utility method; given a section index (index into the @section_names

View File

@ -32,6 +32,10 @@ class IniFile
@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

View File

@ -0,0 +1,95 @@
module Puppet
module Util
class SettingValue
def initialize(setting_value, subsetting_separator = ' ', default_quote_char = nil)
@setting_value = setting_value
@subsetting_separator = subsetting_separator
default_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 }
@quote_char = default_quote_char if @quote_char.empty?
else
@subsetting_items = []
@quote_char = default_quote_char
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

View File

@ -0,0 +1,308 @@
require 'spec_helper_acceptance'
tmpdir = default.tmpdir('tmp')
describe 'ini_setting resource' do
after :all do
shell("rm #{tmpdir}/*.ini", :acceptable_exit_codes => [0,1,2])
end
shared_examples 'has_content' do |path,pp,content|
before :all do
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
after :all do
shell("cat #{path}", :acceptable_exit_codes => [0,1,2])
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file(path) do
it { should be_file }
#XXX Solaris 10 doesn't support multi-line grep
it("should contain #{content}", :unless => fact('osfamily') == 'Solaris') {
should contain(content)
}
end
end
shared_examples 'has_error' do |path,pp,error|
before :all do
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
after :all do
shell("cat #{path}", :acceptable_exit_codes => [0,1,2])
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
it 'applies the manifest and gets a failure message' do
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(error)
end
describe file(path) do
it { should_not be_file }
end
end
describe 'ensure parameter' do
context '=> present for global and section' do
pp = <<-EOS
ini_setting { 'ensure => present for section':
ensure => present,
path => "#{tmpdir}/ini_setting.ini",
section => 'one',
setting => 'two',
value => 'three',
}
ini_setting { 'ensure => present for global':
ensure => present,
path => "#{tmpdir}/ini_setting.ini",
section => '',
setting => 'four',
value => 'five',
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_setting.ini") do
it { should be_file }
#XXX Solaris 10 doesn't support multi-line grep
it("should contain four = five\n[one]\ntwo = three", :unless => fact('osfamily') == 'Solaris') {
should contain("four = five\n[one]\ntwo = three")
}
end
end
context '=> absent for key/value' do
before :all do
if fact('osfamily') == 'Darwin'
shell("echo \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
else
shell("echo -e \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
end
end
pp = <<-EOS
ini_setting { 'ensure => absent for key/value':
ensure => absent,
path => "#{tmpdir}/ini_setting.ini",
section => 'one',
setting => 'two',
value => 'three',
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_setting.ini") do
it { should be_file }
it { should contain('four = five') }
it { should contain('[one]') }
it { should_not contain('two = three') }
end
end
context '=> absent for section', :pending => "cannot ensure absent on a section" do
before :all do
if fact('osfamily') == 'Darwin'
shell("echo \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
else
shell("echo -e \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
end
end
after :all do
shell("cat #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0,1,2])
shell("rm #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0,1,2])
end
pp = <<-EOS
ini_setting { 'ensure => absent for section':
ensure => absent,
path => "#{tmpdir}/ini_setting.ini",
section => 'one',
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_setting.ini") do
it { should be_file }
it { should contain('four = five') }
it { should_not contain('[one]') }
it { should_not contain('two = three') }
end
end
context '=> absent for global' do
before :all do
if fact('osfamily') == 'Darwin'
shell("echo \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
else
shell("echo -e \"four = five\n[one]\ntwo = three\" > #{tmpdir}/ini_setting.ini")
end
end
after :all do
shell("cat #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0,1,2])
shell("rm #{tmpdir}/ini_setting.ini", :acceptable_exit_codes => [0,1,2])
end
pp = <<-EOS
ini_setting { 'ensure => absent for global':
ensure => absent,
path => "#{tmpdir}/ini_setting.ini",
section => '',
setting => 'four',
value => 'five',
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_setting.ini") do
it { should be_file }
it { should_not contain('four = five') }
it { should contain('[one]') }
it { should contain('two = three') }
end
end
end
describe 'section, setting, value parameters' do
{
"section => 'test', setting => 'foo', value => 'bar'," => "[test]\nfoo = bar",
"section => 'more', setting => 'baz', value => 'quux'," => "[more]\nbaz = quux",
"section => '', setting => 'top', value => 'level'," => "top = level",
}.each do |parameter_list, content|
context parameter_list do
pp = <<-EOS
ini_setting { "#{parameter_list}":
ensure => present,
path => "#{tmpdir}/ini_setting.ini",
#{parameter_list}
}
EOS
it_behaves_like 'has_content', "#{tmpdir}/ini_setting.ini", pp, content
end
end
{
"section => 'test'," => /setting is a required.+value is a required/,
"setting => 'foo', value => 'bar'," => /section is a required/,
"section => 'test', setting => 'foo'," => /value is a required/,
"section => 'test', value => 'bar'," => /setting is a required/,
"value => 'bar'," => /section is a required.+setting is a required/,
"setting => 'foo'," => /section is a required.+value is a required/,
}.each do |parameter_list, error|
context parameter_list, :pending => 'no error checking yet' do
pp = <<-EOS
ini_setting { "#{parameter_list}":
ensure => present,
path => "#{tmpdir}/ini_setting.ini",
#{parameter_list}
}
EOS
it_behaves_like 'has_error', "#{tmpdir}/ini_setting.ini", pp, error
end
end
end
describe 'path parameter' do
[
"#{tmpdir}/one.ini",
"#{tmpdir}/two.ini",
"#{tmpdir}/three.ini",
].each do |path|
context "path => #{path}" do
pp = <<-EOS
ini_setting { 'path => #{path}':
ensure => present,
section => 'one',
setting => 'two',
value => 'three',
path => '#{path}',
}
EOS
it_behaves_like 'has_content', path, pp, "[one]\ntwo = three"
end
end
context "path => foo" do
pp = <<-EOS
ini_setting { 'path => foo':
ensure => present,
section => 'one',
setting => 'two',
value => 'three',
path => 'foo',
}
EOS
it_behaves_like 'has_error', 'foo', pp, /must be fully qualified/
end
end
describe 'key_val_separator parameter' do
{
"" => "two = three",
"key_val_separator => '='," => "two=three",
"key_val_separator => ' = '," => "two = three",
}.each do |parameter, content|
context "with \"#{parameter}\" makes \"#{content}\"" do
pp = <<-EOS
ini_setting { "with #{parameter} makes #{content}":
ensure => present,
section => 'one',
setting => 'two',
value => 'three',
path => "#{tmpdir}/key_val_separator.ini",
#{parameter}
}
EOS
it_behaves_like 'has_content', "#{tmpdir}/key_val_separator.ini", pp, content
end
end
{
"key_val_separator => ''," => /must contain exactly one/,
"key_val_separator => ','," => /must contain exactly one/,
"key_val_separator => ' '," => /must contain exactly one/,
"key_val_separator => ' == '," => /must contain exactly one/,
}.each do |parameter, error|
context "with \"#{parameter}\" raises \"#{error}\"" do
pp = <<-EOS
ini_setting { "with #{parameter} raises #{error}":
ensure => present,
section => 'one',
setting => 'two',
value => 'three',
path => "#{tmpdir}/key_val_separator.ini",
#{parameter}
}
EOS
it_behaves_like 'has_error', "#{tmpdir}/key_val_separator.ini", pp, error
end
end
end
end

View File

@ -0,0 +1,195 @@
require 'spec_helper_acceptance'
tmpdir = default.tmpdir('tmp')
describe 'ini_subsetting resource' do
after :all do
shell("rm #{tmpdir}/*.ini", :acceptable_exit_codes => [0,1,2])
end
shared_examples 'has_content' do |path,pp,content|
before :all do
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
after :all do
shell("cat #{path}", :acceptable_exit_codes => [0,1,2])
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file(path) do
it { should be_file }
it { should contain(content) }
end
end
shared_examples 'has_error' do |path,pp,error|
before :all do
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
after :all do
shell("cat #{path}", :acceptable_exit_codes => [0,1,2])
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
it 'applies the manifest and gets a failure message' do
expect(apply_manifest(pp, :expect_failures => true).stderr).to match(error)
end
describe file(path) do
it { should_not be_file }
end
end
describe 'ensure, section, setting, subsetting, & value parameters' do
context '=> present with subsections' do
pp = <<-EOS
ini_subsetting { 'ensure => present for alpha':
ensure => present,
path => "#{tmpdir}/ini_subsetting.ini",
section => 'one',
setting => 'key',
subsetting => 'alpha',
value => 'bet',
}
ini_subsetting { 'ensure => present for beta':
ensure => present,
path => "#{tmpdir}/ini_subsetting.ini",
section => 'one',
setting => 'key',
subsetting => 'beta',
value => 'trons',
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_subsetting.ini") do
it { should be_file }
#XXX Solaris 10 doesn't support multi-line grep
it("should contain [one]\nkey = alphabet betatrons", :unless => fact('osfamily') == 'Solaris') {
should contain("[one]\nkey = alphabet betatrons")
}
end
end
context 'ensure => absent' do
before :all do
if fact('osfamily') == 'Darwin'
shell("echo \"[one]\nkey = alphabet betatrons\" > #{tmpdir}/ini_subsetting.ini")
else
shell("echo -e \"[one]\nkey = alphabet betatrons\" > #{tmpdir}/ini_subsetting.ini")
end
end
pp = <<-EOS
ini_subsetting { 'ensure => absent for subsetting':
ensure => absent,
path => "#{tmpdir}/ini_subsetting.ini",
section => 'one',
setting => 'key',
subsetting => 'alpha',
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_subsetting.ini") do
it { should be_file }
it { should contain('[one]') }
it { should contain('key = betatrons') }
it { should_not contain('alphabet') }
end
end
end
describe 'subsetting_separator' do
{
"" => "two = twinethree foobar",
#"subsetting_separator => ''," => "two = twinethreefoobar", # breaks regex
"subsetting_separator => ','," => "two = twinethree,foobar",
"subsetting_separator => ' '," => "two = twinethree foobar",
"subsetting_separator => ' == '," => "two = twinethree == foobar",
"subsetting_separator => '='," => "two = twinethree=foobar",
#"subsetting_separator => '---'," => "two = twinethree---foobar", # breaks regex
}.each do |parameter, content|
context "with \"#{parameter}\" makes \"#{content}\"" do
pp = <<-EOS
ini_subsetting { "with #{parameter} makes #{content}":
ensure => present,
section => 'one',
setting => 'two',
subsetting => 'twine',
value => 'three',
path => "#{tmpdir}/subsetting_separator.ini",
#{parameter}
}
ini_subsetting { "foobar":
ensure => present,
section => 'one',
setting => 'two',
subsetting => 'foo',
value => 'bar',
path => "#{tmpdir}/subsetting_separator.ini",
#{parameter}
}
EOS
it_behaves_like 'has_content', "#{tmpdir}/subsetting_separator.ini", pp, content
end
end
end
describe 'quote_char' do
{
['-Xmx'] => 'args=""',
['-Xmx', '256m'] => 'args=-Xmx256m',
['-Xmx', '512m'] => 'args="-Xmx512m"',
['-Xms', '256m'] => 'args="-Xmx256m -Xms256m"',
}.each do |parameter, content|
context %Q{with '#{parameter.first}' #{parameter.length > 1 ? '=> \'' << parameter[1] << '\'' : 'absent'} makes '#{content}'} do
path = File.join(tmpdir, 'ini_subsetting.ini')
before :all do
shell(%Q{echo '[java]\nargs=-Xmx256m' > #{path}})
end
after :all do
shell("cat #{path}", :acceptable_exit_codes => [0,1,2])
shell("rm #{path}", :acceptable_exit_codes => [0,1,2])
end
pp = <<-EOS
ini_subsetting { '#{parameter.first}':
ensure => #{parameter.length > 1 ? 'present' : 'absent'},
path => '#{path}',
section => 'java',
setting => 'args',
quote_char => '"',
subsetting => '#{parameter.first}',
value => '#{parameter.length > 1 ? parameter[1] : ''}'
}
EOS
it 'applies the manifest twice' do
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("#{tmpdir}/ini_subsetting.ini") do
it { should be_file }
it { should contain(content) }
end
end
end
end
end

View File

@ -0,0 +1,10 @@
HOSTS:
centos-510-x64:
roles:
- master
platform: el-5-x86_64
box : centos-510-x64-virtualbox-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-510-x64-virtualbox-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
centos-59-x64:
roles:
- master
platform: el-5-x86_64
box : centos-59-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,12 @@
HOSTS:
centos-64-x64:
roles:
- master
- database
- dashboard
platform: el-6-x86_64
box : centos-64-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: pe

View File

@ -0,0 +1,10 @@
HOSTS:
centos-64-x64:
roles:
- master
platform: el-6-x86_64
box : centos-64-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
centos-65-x64:
roles:
- master
platform: el-6-x86_64
box : centos-65-x64-vbox436-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@ -0,0 +1,10 @@
HOSTS:
debian-607-x64:
roles:
- master
platform: debian-6-amd64
box : debian-607-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
debian-73-x64:
roles:
- master
platform: debian-7-amd64
box : debian-73-x64-virtualbox-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
centos-64-x64:
roles:
- master
platform: el-6-x86_64
box : centos-64-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
fedora-18-x64:
roles:
- master
platform: fedora-18-x86_64
box : fedora-18-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
sles-11sp1-x64:
roles:
- master
platform: sles-11-x86_64
box : sles-11sp1-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: git

View File

@ -0,0 +1,10 @@
HOSTS:
ubuntu-server-10044-x64:
roles:
- master
platform: ubuntu-10.04-amd64
box : ubuntu-server-10044-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@ -0,0 +1,10 @@
HOSTS:
ubuntu-server-12042-x64:
roles:
- master
platform: ubuntu-12.04-amd64
box : ubuntu-server-12042-x64-vbox4210-nocm
box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
hypervisor : vagrant
CONFIG:
type: foss

View File

@ -0,0 +1,11 @@
HOSTS:
ubuntu-server-1404-x64:
roles:
- master
platform: ubuntu-14.04-amd64
box : puppetlabs/ubuntu-14.04-64-nocm
box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
hypervisor : vagrant
CONFIG:
log_level : debug
type: git

View File

@ -0,0 +1,24 @@
HOSTS:
ubuntu1204:
roles:
- master
- database
- dashboard
platform: ubuntu-12.04-amd64
template: ubuntu-1204-x86_64
hypervisor: vcloud
win2003_i386:
roles:
- agent
- default
platform: windows-2003-i386
template: win-2003-i386
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/

View File

@ -0,0 +1,24 @@
HOSTS:
ubuntu1204:
roles:
- master
- database
- dashboard
platform: ubuntu-12.04-amd64
template: ubuntu-1204-x86_64
hypervisor: vcloud
win2003r2_x86_64:
roles:
- agent
- default
platform: windows-2003r2-x86_64
template: win-2003r2-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/

View File

@ -0,0 +1,24 @@
HOSTS:
ubuntu1204:
roles:
- master
- database
- dashboard
platform: ubuntu-12.04-amd64
template: ubuntu-1204-x86_64
hypervisor: vcloud
win2008_x86_64:
roles:
- agent
- default
platform: windows-2008-x86_64
template: win-2008-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/

View File

@ -0,0 +1,24 @@
HOSTS:
ubuntu1204:
roles:
- master
- database
- dashboard
platform: ubuntu-12.04-amd64
template: ubuntu-1204-x86_64
hypervisor: vcloud
win2008r2:
roles:
- agent
- default
platform: windows-2008r2-x86_64
template: win-2008r2-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/

View File

@ -0,0 +1,24 @@
HOSTS:
ubuntu1204:
roles:
- master
- database
- dashboard
platform: ubuntu-12.04-amd64
template: ubuntu-1204-x86_64
hypervisor: vcloud
win2012:
roles:
- agent
- default
platform: windows-2012-x86_64
template: win-2012-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/

View File

@ -0,0 +1,24 @@
HOSTS:
ubuntu1204:
roles:
- master
- database
- dashboard
platform: ubuntu-12.04-amd64
template: ubuntu-1204-x86_64
hypervisor: vcloud
win2012r2:
roles:
- agent
- default
platform: windows-2012r2-x86_64
template: win-2012r2-x86_64
hypervisor: vcloud
CONFIG:
nfs_server: none
consoleport: 443
datastore: instance0
folder: Delivery/Quality Assurance/Enterprise/Dynamic
resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/
pe_dir: http://neptune.puppetlabs.lan/3.3/ci-ready/

View File

@ -0,0 +1,10 @@
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

View File

@ -0,0 +1,6 @@
--format
s
--colour
--loadby
mtime
--backtrace

View File

@ -1,10 +1,4 @@
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

View File

@ -0,0 +1,41 @@
require 'beaker-rspec/spec_helper'
require 'beaker-rspec/helpers/serverspec'
unless ENV['RS_PROVISION'] == 'no'
if hosts.first.is_pe?
install_pe
else
install_puppet
end
hosts.each do |host|
if host['platform'] =~ /debian/
on host, 'echo \'export PATH=/var/lib/gems/1.8/bin/:${PATH}\' >> ~/.bashrc'
on host, "mkdir -p #{host['distmoduledir']}"
end
end
end
RSpec.configure do |c|
# Project root
proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
# Readable test descriptions
c.formatter = :documentation
# Configure all nodes in nodeset
c.before :suite do
# Install module and dependencies
hosts.each do |host|
if host['platform'] !~ /windows/i
copy_root_module_to(host, :source => proj_root, :module_name => 'inifile')
end
end
hosts.each do |host|
if host['platform'] =~ /windows/i
on host, puppet('plugin download')
end
end
end
c.treat_symbols_as_metadata_keys_with_true_values = true
end

View File

@ -0,0 +1,67 @@
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

View File

@ -28,6 +28,96 @@ describe provider_class do
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
@ -54,7 +144,7 @@ subby=bar
resource = Puppet::Type::Ini_setting.new(common_params.merge(
:setting => 'yahoo', :value => 'yippee'))
provider = described_class.new(resource)
provider.exists?.should be_nil
provider.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -82,7 +172,7 @@ subby=bar
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -110,7 +200,7 @@ yahoo = yippee
resource = Puppet::Type::Ini_setting.new(common_params.merge(
:setting => 'baz', :value => 'bazvalue2'))
provider = described_class.new(resource)
provider.exists?.should == 'bazvalue'
provider.exists?.should be true
provider.value=('bazvalue2')
validate_file(<<-EOS
# This is a comment
@ -137,7 +227,7 @@ subby=bar
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.exists?.should be true
provider.value.should == 'bar'
provider.value=('foo')
validate_file(<<-EOS
@ -165,7 +255,7 @@ subby=foo
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.exists?.should be true
provider.value.should == 'http://192.168.1.1:8080'
provider.value=('http://192.168.0.1:8080')
@ -194,14 +284,14 @@ subby=bar
resource = Puppet::Type::Ini_setting.new(common_params.merge(
:setting => 'baz', :value => 'bazvalue'))
provider = described_class.new(resource)
provider.exists?.should == 'bazvalue'
provider.exists?.should be true
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -231,7 +321,7 @@ huzzah = shazaam
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -261,7 +351,7 @@ huzzah = shazaam
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.exists?.should be false
provider.create
validate_file("
[section1]
@ -273,7 +363,7 @@ setting1 = hellowworld
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.exists?.should be false
provider.create
validate_file("
[section:subsection]
@ -285,7 +375,7 @@ setting1 = hellowworld
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.exists?.should be true
provider.value.should == 'true'
end
@ -307,7 +397,7 @@ foo = http://192.168.1.1:8080
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -324,7 +414,7 @@ foo = http://192.168.1.1:8080
resource = Puppet::Type::Ini_setting.new(common_params.merge(
:section => '', :setting => 'foo', :value => 'yippee'))
provider = described_class.new(resource)
provider.exists?.should == 'blah'
provider.exists?.should be true
provider.value.should == 'blah'
provider.value=('yippee')
validate_file(<<-EOS
@ -341,7 +431,7 @@ foo = http://192.168.1.1:8080
resource = Puppet::Type::Ini_setting.new(common_params.merge(
:section => '', :setting => 'foo', :value => 'blah'))
provider = described_class.new(resource)
provider.exists?.should == 'blah'
provider.exists?.should be true
end
end
@ -357,7 +447,7 @@ foo = http://192.168.1.1:8080
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.exists?.should be false
provider.create
validate_file(<<-EOS
foo = yippee
@ -372,7 +462,7 @@ foo = http://192.168.1.1:8080
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.exists?.should be true
provider.value.should == 'http://192.168.1.1:8080'
provider.value=('yippee')
validate_file(<<-EOS
@ -386,7 +476,7 @@ foo = yippee
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.exists?.should be false
provider.create
validate_file(<<-EOS
[section2]
@ -432,7 +522,7 @@ foo=bar
:value => 'yippee',
:key_val_separator => '='))
provider = described_class.new(resource)
provider.exists?.should == 'bar'
provider.exists?.should be true
provider.value.should == 'bar'
provider.value=('yippee')
validate_file(<<-EOS
@ -449,7 +539,7 @@ foo=yippee
:value => 'baz',
:key_val_separator => '='))
provider = described_class.new(resource)
provider.exists?.should be_nil
provider.exists?.should be false
provider.create
validate_file(<<-EOS
[section2]
@ -486,7 +576,7 @@ EOS
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.exists?.should be true
provider.destroy
validate_file(<<-EOS
[section1]
@ -511,7 +601,7 @@ EOS
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.exists?.should be false
provider.destroy
validate_file(<<-EOS
[section1]
@ -562,7 +652,7 @@ subby=bar
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -591,7 +681,7 @@ subby=bar
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.exists?.should be true
provider.create
validate_file(<<-EOS
# This is a comment
@ -619,7 +709,7 @@ subby=bar
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -648,7 +738,7 @@ subby=bar
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.exists?.should be true
provider.create
validate_file(<<-EOS
# This is a comment
@ -676,7 +766,7 @@ subby=bar
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.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
@ -705,7 +795,7 @@ subby=bar
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.exists?.should be true
provider.create
validate_file(<<-EOS
# This is a comment
@ -744,6 +834,7 @@ subby=bar
# foo = foovalue
;bar=barvalue
blah = blah
#baz=
EOS
}
@ -751,7 +842,7 @@ blah = blah
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.exists?.should be false
provider.create
validate_file(<<-EOS
[section1]
@ -764,6 +855,7 @@ blah = blah
foo = foo3
;bar=barvalue
blah = blah
#baz=
EOS
)
end
@ -772,7 +864,7 @@ blah = blah
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.exists?.should be true
provider.create
validate_file(<<-EOS
[section1]
@ -784,6 +876,7 @@ blah = blah
# foo = foovalue
;bar=barvalue
blah = blah
#baz=
EOS
)
end
@ -792,7 +885,7 @@ blah = blah
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.exists?.should be false
provider.create
validate_file(<<-EOS
[section1]
@ -805,10 +898,166 @@ blah = blah
;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
context "when sections have spaces and dashes" do
let(:orig_content) {
<<-EOS
# This is a comment
[section - one]
; This is also a comment
foo=foovalue
bar = barvalue
master = true
[section - two]
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(
:section => 'section - two', :setting => 'yahoo', :value => 'yippee'))
provider = described_class.new(resource)
provider.exists?.should be false
provider.create
validate_file(<<-EOS
# This is a comment
[section - one]
; This is also a comment
foo=foovalue
bar = barvalue
master = true
[section - two]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
yahoo = yippee
[section:sub]
subby=bar
#another comment
; yet another comment
EOS
)
end
end
end
context "when sections have spaces and quotations" do
let(:orig_content) do
<<-EOS
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
[branch "production"]
remote = origin
merge = refs/heads/production
EOS
end
it "should add a missing setting to the correct section" do
resource = Puppet::Type::Ini_setting.new(common_params.merge(
:section => 'alias',
:setting => 'foo',
:value => 'bar'
))
provider = described_class.new(resource)
provider.exists?.should be false
provider.create
validate_file(<<-EOS
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
foo = bar
[branch "production"]
remote = origin
merge = refs/heads/production
EOS
)
end
end
end

View File

@ -0,0 +1,135 @@
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

View File

@ -1,4 +1,5 @@
require 'spec_helper'
require 'stringio'
require 'puppet/util/ini_file'
describe Puppet::Util::IniFile do
@ -20,6 +21,7 @@ describe Puppet::Util::IniFile do
foo=foovalue
bar = barvalue
baz =
[section2]
foo= foovalue2
@ -27,6 +29,7 @@ baz=bazvalue
#another comment
; yet another comment
zot = multi word value
xyzzy['thing1']['thing2']=xyzzyvalue
EOS
template.split("\n")
}
@ -44,9 +47,11 @@ baz=bazvalue
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"
subject.get_value("section2", "xyzzy['thing1']['thing2']").should == "xyzzyvalue"
end
end
@ -102,6 +107,116 @@ foo=foovalue
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=
#xyzzy['thing1']['thing2']='xyzzyvalue'
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"
subject.get_value("section1", "xyzzy['thing1']['thing2']").should == nil
subject.set_value("section1", "xyzzy['thing1']['thing2']", "xyzzyvalue")
subject.get_value("section1", "xyzzy['thing1']['thing2']").should == "xyzzyvalue"
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
context 'the file has quotation marks in its section names' do
let(:sample_content) do
template = <<-EOS
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
[branch "production"]
remote = origin
merge = refs/heads/production
EOS
template.split("\n")
end
it 'should parse the sections' do
subject.section_names.should match_array ['',
'branch "master"',
'alias',
'branch "production"'
]
end
end
context 'Samba INI file with dollars in section names' do
let(:sample_content) do
template = <<-EOS
[global]
workgroup = FELLOWSHIP
; ...
idmap config * : backend = tdb
[printers]
comment = All Printers
; ...
browseable = No
[print$]
comment = Printer Drivers
path = /var/lib/samba/printers
[Shares]
path = /home/shares
read only = No
guest ok = Yes
EOS
template.split("\n")
end
it "should parse the correct section_names" do
subject.section_names.should match_array [
'',
'global',
'printers',
'print$',
'Shares'
]
end
end
context 'section names with forward slashes in them' do
let(:sample_content) do
template = <<-EOS
[monitor:///var/log/*.log]
disabled = test_value
EOS
template.split("\n")
end
it "should parse the correct section_names" do
subject.section_names.should match_array [
'',
'monitor:///var/log/*.log'
]
end
end
end

View File

@ -0,0 +1,103 @@
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
describe "quote_char parameter" do
QUOTE_CHAR = '"'
INIT_VALUE_UNQUOTED = '-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof'
it "should get quoted empty string if original value was empty" do
setting_value = Puppet::Util::SettingValue.new(nil, ' ', QUOTE_CHAR)
setting_value.get_value.should == QUOTE_CHAR * 2
end
it "should quote the setting when adding a value" do
setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR)
setting_value.add_subsetting("-Xms", "256m")
setting_value.get_subsetting_value("-Xms").should == "256m"
setting_value.get_value.should == QUOTE_CHAR + INIT_VALUE_UNQUOTED + ' -Xms256m' + QUOTE_CHAR
end
it "should quote the setting when changing an existing value" do
setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR)
setting_value.add_subsetting("-Xmx", "512m")
setting_value.get_subsetting_value("-Xmx").should == "512m"
setting_value.get_value.should =~ /^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$/
end
it "should quote the setting when removing an existing value" do
setting_value = Puppet::Util::SettingValue.new(INIT_VALUE_UNQUOTED, ' ', QUOTE_CHAR)
setting_value.remove_subsetting("-Xmx")
setting_value.get_subsetting_value("-Xmx").should == nil
setting_value.get_value.should =~ /^#{Regexp.quote(QUOTE_CHAR)}.*#{Regexp.quote(QUOTE_CHAR)}$/
end
end
end

View File

@ -1,25 +1,25 @@
ini_setting { "sample setting":
ini_setting { 'sample setting':
ensure => present,
path => '/tmp/foo.ini',
section => 'foo',
setting => 'foosetting',
value => 'FOO!',
ensure => present,
}
ini_setting { "sample setting2":
path => '/tmp/foo.ini',
section => 'bar',
setting => 'barsetting',
value => 'BAR!',
ini_setting { 'sample setting2':
ensure => present,
path => '/tmp/foo.ini',
section => 'bar',
setting => 'barsetting',
value => 'BAR!',
key_val_separator => '=',
ensure => present,
require => Ini_setting["sample setting"],
require => Ini_setting['sample setting'],
}
ini_setting { "sample setting3":
path => '/tmp/foo.ini',
section => 'bar',
setting => 'bazsetting',
ensure => absent,
require => Ini_setting["sample setting2"],
ini_setting { 'sample setting3':
ensure => absent,
path => '/tmp/foo.ini',
section => 'bar',
setting => 'bazsetting',
require => Ini_setting['sample setting2'],
}

View File

@ -0,0 +1,18 @@
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',
}