diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 064443f..8424781 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,65 +1,65 @@
name: "release"
on:
push:
branches:
- 'release'
jobs:
LitmusAcceptancePuppet5:
env:
HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
HONEYCOMB_DATASET: litmus tests
runs-on: self-hosted
strategy:
matrix:
ruby_version: [2.5.x]
puppet_gem_version: [~> 6.0]
platform: [release_checks_5]
agent_family: ['puppet5']
steps:
- uses: actions/checkout@v1
- name: Litmus Parallel
- uses: puppetlabs/action-litmus_parallel@master
+ uses: puppetlabs/action-litmus_parallel@main
with:
platform: ${{ matrix.platform }}
agent_family: ${{ matrix.agent_family }}
LitmusAcceptancePuppet6:
env:
HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
HONEYCOMB_DATASET: litmus tests
runs-on: self-hosted
strategy:
matrix:
ruby_version: [2.5.x]
puppet_gem_version: [~> 6.0]
platform: [release_checks_6]
agent_family: ['puppet6']
steps:
- uses: actions/checkout@v1
- name: Litmus Parallel
- uses: puppetlabs/action-litmus_parallel@master
+ uses: puppetlabs/action-litmus_parallel@main
with:
platform: ${{ matrix.platform }}
agent_family: ${{ matrix.agent_family }}
Spec:
runs-on: self-hosted
strategy:
matrix:
check: [parallel_spec, 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop']
ruby_version: [2.5.x]
puppet_gem_version: [~> 5.0, ~> 6.0]
exclude:
- puppet_gem_version: ~> 5.0
check: 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop'
- ruby_version: 2.5.x
puppet_gem_version: ~> 5.0
steps:
- uses: actions/checkout@v1
- name: Spec Tests
- uses: puppetlabs/action-litmus_spec@master
+ uses: puppetlabs/action-litmus_spec@main
with:
puppet_gem_version: ${{ matrix.puppet_gem_version }}
check: ${{ matrix.check }}
diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml
index f6b48df..7ca532a 100644
--- a/.github/workflows/weekly.yml
+++ b/.github/workflows/weekly.yml
@@ -1,64 +1,64 @@
name: "weekly"
on:
schedule:
- cron: '0 3 * * 5'
jobs:
LitmusAcceptancePuppet5:
env:
HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
HONEYCOMB_DATASET: litmus tests
runs-on: self-hosted
strategy:
matrix:
ruby_version: [2.5.x]
puppet_gem_version: [~> 6.0]
platform: [release_checks_5]
agent_family: ['puppet5']
steps:
- uses: actions/checkout@v1
- name: Litmus Parallel
- uses: puppetlabs/action-litmus_parallel@master
+ uses: puppetlabs/action-litmus_parallel@main
with:
platform: ${{ matrix.platform }}
agent_family: ${{ matrix.agent_family }}
LitmusAcceptancePuppet6:
env:
HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
HONEYCOMB_DATASET: litmus tests
runs-on: self-hosted
strategy:
matrix:
ruby_version: [2.5.x]
puppet_gem_version: [~> 6.0]
platform: [release_checks_6]
agent_family: ['puppet6']
steps:
- uses: actions/checkout@v1
- name: Litmus Parallel
- uses: puppetlabs/action-litmus_parallel@master
+ uses: puppetlabs/action-litmus_parallel@main
with:
platform: ${{ matrix.platform }}
agent_family: ${{ matrix.agent_family }}
Spec:
runs-on: self-hosted
strategy:
matrix:
check: [parallel_spec, 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop']
ruby_version: [2.5.x]
puppet_gem_version: [~> 5.0, ~> 6.0]
exclude:
- puppet_gem_version: ~> 5.0
check: 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop'
- ruby_version: 2.5.x
puppet_gem_version: ~> 5.0
steps:
- uses: actions/checkout@v1
- name: Spec Tests
- uses: puppetlabs/action-litmus_spec@master
+ uses: puppetlabs/action-litmus_spec@main
with:
puppet_gem_version: ${{ matrix.puppet_gem_version }}
check: ${{ matrix.check }}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1a9fb3a..9c171f9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,271 +1,271 @@
# Contributing to Puppet modules
So you want to contribute to a Puppet module: Great! Below are some instructions to get you started doing
that very thing while setting expectations around code quality as well as a few tips for making the
process as easy as possible.
### Table of Contents
1. [Getting Started](#getting-started)
1. [Commit Checklist](#commit-checklist)
1. [Submission](#submission)
1. [More about commits](#more-about-commits)
1. [Testing](#testing)
- [Running Tests](#running-tests)
- [Writing Tests](#writing-tests)
1. [Get Help](#get-help)
## Getting Started
- Fork the module repository on GitHub and clone to your workspace
- Make your changes!
## Commit Checklist
### The Basics
- [x] my commit is a single logical unit of work
- [x] I have checked for unnecessary whitespace with "git diff --check"
- [x] my commit does not include commented out code or unneeded files
### The Content
- [x] my commit includes tests for the bug I fixed or feature I added
- [x] my commit includes appropriate documentation changes if it is introducing a new feature or changing existing functionality
- [x] my code passes existing test suites
### The Commit Message
- [x] the first line of my commit message includes:
- [x] an issue number (if applicable), e.g. "(MODULES-xxxx) This is the first line"
- [x] a short description (50 characters is the soft limit, excluding ticket number(s))
- [x] the body of my commit message:
- [x] is meaningful
- [x] uses the imperative, present tense: "change", not "changed" or "changes"
- [x] includes motivation for the change, and contrasts its implementation with the previous behavior
## Submission
### Pre-requisites
- Make sure you have a [GitHub account](https://github.com/join)
- [Create a ticket](https://tickets.puppet.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppet.com/browse/) you are patching for.
### Push and PR
- Push your changes to your fork
- [Open a Pull Request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) against the repository in the puppetlabs organization
## More about commits
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. 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".
+ directly on "main".
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](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
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.
3. Update the related JIRA issue.
If there is a JIRA 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, and then use it to
install all dependencies needed for this project in the project root by running
```shell
% bundle install --path .bundle/gems
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
```
## Running Tests
With all dependencies in place and up-to-date, run the tests:
### Unit Tests
```shell
% bundle exec rake spec
```
This executes all the [rspec tests](http://rspec-puppet.com/) in the directories defined [here](https://github.com/puppetlabs/puppetlabs_spec_helper/blob/699d9fbca1d2489bff1736bb254bb7b7edb32c74/lib/puppetlabs_spec_helper/rake_tasks.rb#L17) and so on.
rspec tests may have the same kind of dependencies as the module they are testing. Although the module defines these dependencies in its [metadata.json](./metadata.json),
rspec tests define them in [.fixtures.yml](./fixtures.yml).
### Acceptance Tests
Some Puppet modules also come with acceptance tests, which use [beaker][]. These tests spin up a virtual machine under
[VirtualBox](https://www.virtualbox.org/), controlled with [Vagrant](http://www.vagrantup.com/), to simulate scripted test
scenarios. In order to run these, you need both Virtualbox and Vagrant installed on your system.
Run the tests by issuing the following command
```shell
% bundle exec rake spec_clean
% bundle exec 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
### Unit Tests
When writing unit tests for Puppet, [rspec-puppet][] is your best friend. It provides tons of helper methods for testing your manifests against a
catalog (e.g. contain_file, contain_package, with_params, etc). It would be ridiculous to try and top rspec-puppet's [documentation][rspec-puppet_docs]
but here's a tiny sample:
Sample manifest:
```puppet
file { "a test file":
ensure => present,
path => "/etc/sample",
}
```
Sample test:
```ruby
it 'does a thing' do
expect(subject).to contain_file("a test file").with({:path => "/etc/sample"})
end
```
### Acceptance Tests
Writing acceptance tests for Puppet involves [beaker][] and its cousin [beaker-rspec][]. A common pattern for acceptance tests is to create a test manifest, apply it
twice to check for idempotency or errors, then run expectations.
```ruby
it 'does an end-to-end thing' do
pp = <<-EOF
file { 'a test file':
ensure => present,
path => "/etc/sample",
content => "test string",
}
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
describe file("/etc/sample") do
it { is_expected.to contain "test string" }
end
```
# If you have commit access to the repository
Even if you have commit access to the repository, you 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 project developer that did not write the code to ensure that
all changes go through a code review process.**
The record of someone performing the merge is the record that they performed the code review. Again, this should be someone other than the author of the topic branch.
# Get Help
### On the web
* [Puppet help messageboard](http://puppet.com/community/get-help)
* [Writing tests](https://docs.puppet.com/guides/module_guides/bgtm.html#step-three-module-testing)
* [General GitHub documentation](http://help.github.com/)
* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
### On chat
* Slack (slack.puppet.com) #forge-modules, #puppet-dev, #windows, #voxpupuli
* IRC (freenode) #puppet-dev, #voxpupuli
[rspec-puppet]: http://rspec-puppet.com/
[rspec-puppet_docs]: http://rspec-puppet.com/documentation/
[beaker]: https://github.com/puppetlabs/beaker
[beaker-rspec]: https://github.com/puppetlabs/beaker-rspec
diff --git a/README.md b/README.md
index 5c44cf0..3d85fd5 100644
--- a/README.md
+++ b/README.md
@@ -1,315 +1,315 @@
# inifile
-[](https://travis-ci.org/puppetlabs/puppetlabs-inifile)
+[](https://travis-ci.org/puppetlabs/puppetlabs-inifile)
#### Table of Contents
1. [Overview](#overview)
1. [Module Description - What the module does and why it is useful](#module-description)
1. [Setup - The basics of getting started with inifile module](#setup)
1. [Usage - Configuration options and additional functionality](#usage)
1. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
1. [Limitations - OS compatibility, etc.](#limitations)
1. [Development - Guide for contributing to the module](#development)
## Overview
The inifile module lets Puppet manage settings stored in INI-style configuration files.
## Module Description
Many applications use INI-style configuration files to store their settings. This module supplies two custom resource types to let you manage those settings through Puppet.
## Setup
### Beginning with inifile
To manage a single setting in an INI file, add the `ini_setting` type to a class:
~~~puppet
ini_setting { "sample setting":
ensure => present,
path => '/tmp/foo.ini',
section => 'bar',
setting => 'baz',
value => 'quux',
}
~~~
## Usage
The inifile module is used to:
* Support comments starting with either '#' or ';'.
* Support either whitespace or no whitespace around '='.
* Add any missing sections to the INI file.
It does not manipulate your file any more than it needs to. In most cases, it doesn't affect the original whitespace, comments, or ordering. See the common usages below for examples.
### Manage multiple values in a setting
Use the `ini_subsetting` type:
~~~puppet
ini_subsetting {'sample subsetting':
ensure => present,
section => '',
key_val_separator => '=',
path => '/etc/default/pe-puppetdb',
setting => 'JAVA_ARGS',
subsetting => '-Xmx',
value => '512m',
}
~~~
Results in managing this `-Xmx` subsetting:
~~~puppet
JAVA_ARGS="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
~~~
### Use a non-standard section header
~~~puppet
ini_setting { 'default minage':
ensure => present,
path => '/etc/security/users',
section => 'default',
setting => 'minage',
value => '1',
section_prefix => '',
section_suffix => ':',
}
~~~
Results in:
~~~puppet
default:
minage = 1
~~~
### Use a non-standard indent character
To use a non-standard indent character or string for added settings, set the `indent_char` and the `indent_width` parameters. The `indent_width` parameter controls how many `indent_char` appear in the indent.
~~~puppet
ini_setting { 'procedure cache size':
ensure => present,
path => '/var/lib/ase/config/ASE-16_0/SYBASE.cfg',
section => 'SQL Server Administration',
setting => 'procedure cache size',
value => '15000',
indent_char => "\t",
indent_width => 2,
}
~~~
Results in:
~~~puppet
[SQL Server Administration]
procedure cache size = 15000
~~~
### Implement child providers
You might want to create child providers that inherit the `ini_setting` provider for one of the following reasons:
* To make a custom resource to manage an application that stores its settings in INI files, without recreating the code to manage the files themselves.
* To [purge all unmanaged settings](https://docs.puppetlabs.com/references/latest/type.html#resources-attribute-purge) from a managed INI file.
To implement child providers, first specify a custom type. Have it implement a namevar called `name` and a property called `value`:
~~~ruby
#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 define'
munge do |v|
v.to_s.strip
end
end
end
~~~
Your type also needs a provider that uses the `ini_setting` provider as its parent:
~~~ruby
# 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 you can manage the settings in the `/etc/glance/glance-api.conf` file as individual resources:
~~~puppet
glance_api_config { 'HEADER/important_config':
value => 'secret_value',
}
~~~
If you've implemented `self.file_path`, you can have Puppet purge the file of the all lines that aren't implemented as Puppet resources:
~~~puppet
resources { 'glance_api_config':
purge => true,
}
~~~
### Manage multiple ini_settings
To manage multiple `ini_settings`, use the [`inifile::create_ini_settings`](REFERENCE.md#inifilecreate_ini_settings) function.
~~~puppet
$defaults = { 'path' => '/tmp/foo.ini' }
$example = { 'section1' => { 'setting1' => 'value1' } }
inifile::create_ini_settings($example, $defaults)
~~~
Results in:
~~~puppet
ini_setting { '[section1] setting1':
ensure => present,
section => 'section1',
setting => 'setting1',
value => 'value1',
path => '/tmp/foo.ini',
}
~~~
To include special parameters, use the following code:
~~~puppet
$defaults = { 'path' => '/tmp/foo.ini' }
$example = {
'section1' => {
'setting1' => 'value1',
'settings2' => {
'ensure' => 'absent'
}
}
}
inifile::create_ini_settings($example, $defaults)
~~~
Results in:
~~~puppet
ini_setting { '[section1] setting1':
ensure => present,
section => 'section1',
setting => 'setting1',
value => 'value1',
path => '/tmp/foo.ini',
}
ini_setting { '[section1] setting2':
ensure => absent,
section => 'section1',
setting => 'setting2',
path => '/tmp/foo.ini',
}
~~~
#### Manage multiple ini_settings with Hiera
For the profile `example`:
~~~puppet
class profile::example (
Hash $settings,
) {
$defaults = { 'path' => '/tmp/foo.ini' }
inifile::create_ini_settings($settings, $defaults)
}
~~~
Provide this in your Hiera data:
~~~puppet
profile::example::settings:
section1:
setting1: value1
setting2: value2
setting3:
ensure: absent
~~~
Results in:
~~~puppet
ini_setting { '[section1] setting1':
ensure => present,
section => 'section1',
setting => 'setting1',
value => 'value1',
path => '/tmp/foo.ini',
}
ini_setting { '[section1] setting2':
ensure => present,
section => 'section1',
setting => 'setting2',
value => 'value2',
path => '/tmp/foo.ini',
}
ini_setting { '[section1] setting3':
ensure => absent,
section => 'section1',
setting => 'setting3',
path => '/tmp/foo.ini',
}
~~~
## Reference
-See [REFERENCE.md](https://github.com/puppetlabs/puppetlabs-inifile/blob/master/REFERENCE.md)
+See [REFERENCE.md](https://github.com/puppetlabs/puppetlabs-inifile/blob/main/REFERENCE.md)
## Limitations
-For an extensive list of supported operating systems, see [metadata.json](https://github.com/puppetlabs/puppetlabs-inifile/blob/master/metadata.json)
+For an extensive list of supported operating systems, see [metadata.json](https://github.com/puppetlabs/puppetlabs-inifile/blob/main/metadata.json)
## Development
We are experimenting with a new tool for running acceptance tests. It's name is [puppet_litmus](https://github.com/puppetlabs/puppet_litmus) this replaces beaker as the test runner. To run the acceptance tests follow the instructions [here](https://github.com/puppetlabs/puppet_litmus/wiki/Tutorial:-use-Litmus-to-execute-acceptance-tests-with-a-sample-module-(MoTD)#install-the-necessary-gems-for-the-module).
Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can't access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.
We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
For more information, see our [module contribution guide.](https://puppet.com/docs/puppet/latest/contributing.html)
### Contributors
To see who's already involved, see the [list of contributors.](https://github.com/puppetlabs/puppetlabs-inifile/graphs/contributors)
diff --git a/metadata.json b/metadata.json
index e926c69..1218b9f 100644
--- a/metadata.json
+++ b/metadata.json
@@ -1,114 +1,114 @@
{
"name": "puppetlabs-inifile",
"version": "4.3.0",
"author": "puppetlabs",
"summary": "Resource types for managing settings in INI files",
"license": "Apache-2.0",
"source": "https://github.com/puppetlabs/puppetlabs-inifile",
"project_page": "https://github.com/puppetlabs/puppetlabs-inifile",
"issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
"dependencies": [
{
"name": "puppetlabs/translate",
"version_requirement": ">= 1.0.0 < 3.0.0"
},
{
"name": "puppetlabs/stdlib",
"version_requirement": ">= 4.13.0 < 7.0.0"
}
],
"operatingsystem_support": [
{
"operatingsystem": "RedHat",
"operatingsystemrelease": [
"5",
"6",
"7",
"8"
]
},
{
"operatingsystem": "CentOS",
"operatingsystemrelease": [
"5",
"6",
"7",
"8"
]
},
{
"operatingsystem": "OracleLinux",
"operatingsystemrelease": [
"5",
"6",
"7"
]
},
{
"operatingsystem": "Scientific",
"operatingsystemrelease": [
"6",
"7"
]
},
{
"operatingsystem": "SLES",
"operatingsystemrelease": [
"11 SP1",
"12",
"15"
]
},
{
"operatingsystem": "Debian",
"operatingsystemrelease": [
"8",
"9",
"10"
]
},
{
"operatingsystem": "Ubuntu",
"operatingsystemrelease": [
"14.04",
"16.04",
"18.04",
"20.04"
]
},
{
"operatingsystem": "Solaris",
"operatingsystemrelease": [
"10",
"11"
]
},
{
"operatingsystem": "Windows",
"operatingsystemrelease": [
"2008 R2",
"2012 R2",
"2016",
"2019",
"10"
]
},
{
"operatingsystem": "AIX",
"operatingsystemrelease": [
"5.3",
"6.1",
"7.1"
]
}
],
"requirements": [
{
"name": "puppet",
"version_requirement": ">= 5.5.10 < 7.0.0"
}
],
- "template-url": "https://github.com/puppetlabs/pdk-templates#master",
- "template-ref": "heads/master-0-gd610ead",
+ "template-url": "https://github.com/puppetlabs/pdk-templates#main",
+ "template-ref": "heads/main-0-gd610ead",
"pdk-version": "1.18.1"
}
diff --git a/spec/unit/puppet/provider/ini_setting/ruby_spec.rb b/spec/unit/puppet/provider/ini_setting/ruby_spec.rb
index 0e8a938..414eb85 100644
--- a/spec/unit/puppet/provider/ini_setting/ruby_spec.rb
+++ b/spec/unit/puppet/provider/ini_setting/ruby_spec.rb
@@ -1,1588 +1,1588 @@
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) do
{
title: 'ini_setting_ensure_present_test',
path: tmpfile,
section: 'section2',
}
end
def validate_file(expected_content, tmpfile)
expect(File.read(tmpfile)).to eq(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 'fails 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
child_one = Class.new(provider_class) do
def self.file_path
emptyfile
end
end
it 'returns [] when file is empty' do
expect(child_one).to receive(:file_path).and_return(emptyfile)
expect(child_one.instances).to eq([])
end
child_two = Class.new(provider_class) do
def self.file_path
'/some/file/path'
end
end
it 'overrides the provider instances file_path' do
resource = Puppet::Type::Ini_setting.new(common_params)
provider = child_two.new(resource)
expect(provider.file_path).to eq('/some/file/path')
end
end
context 'when file has contecnts' do
let(:orig_content) do
<<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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 'is able to parse the results' do
child_three = Class.new(provider_class) do
def self.file_path
'/some/file/path'
end
end
expect(child_three).to receive(:file_path).exactly(2).times.and_return(tmpfile)
expect(child_three.instances.size).to eq(7)
expected_array = [
{ name: 'section1/foo', value: 'foovalue' },
{ name: 'section1/bar', value: 'barvalue' },
- { name: 'section1/master', value: 'true' },
+ { name: 'section1/main', 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
expect(ensure_array.uniq).to eq([:present])
expect((real_array - expected_array) && (expected_array - real_array)).to eq([])
end
# rubocop:enable RSpec/ExampleLength
# rubocop:enable RSpec/MultipleExpectations
end
end
context 'when ensuring that a setting is present' do
let(:orig_content) do
<<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
end
expected_content_one = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
yahoo = yippee
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
yahoo = yippee
EOS
it 'adds a missing setting to the correct section with pre/suffix' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'yahoo', value: 'yippee', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
indented = weirdly
EOS
it 'adds a missing setting to the correct section with indent_char' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'indented', value: 'weirdly', section_prefix: '-', section_suffix: '-', indent_char: "\t"))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_three, tmpfile)
end
expected_content_four = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
indented = weirdly
EOS
it 'adds a missing setting to the correct section indented by indent_char * indent_width' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'indented', value: 'weirdly',
section_prefix: '-', section_suffix: '-', indent_char: "\t", indent_width: 4))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_four, tmpfile)
end
expected_content_five = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
indented = weirdly
EOS
it 'treats a string indent_width as an integer' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'indented', value: 'weirdly',
section_prefix: '-', section_suffix: '-', indent_char: "\t", indent_width: '4'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_five, tmpfile)
end
expected_content_six = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
yahoo = yippee
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_six, tmpfile)
end
expected_content_seven = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue2
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'modifies 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)
expect(provider).to be_exists
provider.value = 'bazvalue2'
validate_file(expected_content_seven, tmpfile)
end
expected_content_eight = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = false
+main = false
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'modifies an existing setting with a different boolean value' do
- resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'master', value: false))
+ resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'main', value: false))
provider = described_class.new(resource)
expect(provider.exists?).to be true
transaction = instance_double('transaction', persistence: true)
expect(Puppet::Transaction::ResourceHarness.new(transaction).evaluate(provider.resource).out_of_sync).to eq(true)
validate_file(expected_content_eight, tmpfile)
end
# rubocop:enable RSpec/MultipleExpectations : Unable to reduce without altering test
expected_content_nine = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = orange
EOS
it 'modifies an existing setting with pre/suffix with a different value' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'shoes', value: 'orange', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.value = 'orange'
validate_file(expected_content_nine, tmpfile)
end
expected_content_ten = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=foo
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'modifies 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)
expect(provider.value).to eq('bar')
provider.value = 'foo'
validate_file(expected_content_ten, tmpfile)
end
expected_content_eleven = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.0.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'is 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)
expect(provider.value).to eq('http://192.168.1.1:8080')
provider.value = 'http://192.168.0.1:8080'
validate_file(expected_content_eleven, tmpfile)
end
expected_content_twelve = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = http://192.168.0.1:8080
EOS
it 'is able to handle settings with pre/suffix with non alphanumbering settings' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'shoes', value: 'http://192.168.0.1:8080', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.value).to eq('purple')
provider.value = 'http://192.168.0.1:8080'
validate_file(expected_content_twelve, tmpfile)
end
it 'recognizes 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)
expect(provider.exists?).to be true
end
it 'recognizes an existing setting with pre/suffix with the specified value' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'shoes', value: 'purple',
section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
end
expected_content_thirteen = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
[section3]
huzzah = shazaam
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_thirteen, tmpfile)
end
expected_content_fourteen = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
-section3-
huzzah = shazaam
EOS
it 'adds a new section with pre/suffix if the section does not exist' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section3', setting: 'huzzah', value: 'shazaam', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider).not_to be_exists
provider.create
validate_file(expected_content_fourteen, tmpfile)
end
expected_content_fifteen = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
[section:subsection]
huzzah = shazaam
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_fifteen, tmpfile)
end
expected_content_sixteen = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
-section:subsection-
huzzah = shazaam
EOS
it 'adds a new section with pre/suffix 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', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_sixteen, tmpfile)
end
it 'adds a new empty section' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(orig_content + "\n[section]\n", tmpfile)
end
it 'is able to handle variables of any type' do
- resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'master', value: true))
+ resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'main', value: true))
provider = described_class.new(resource)
expect(provider.value).to eq('true')
end
end
context 'when no sections exist' do
let(:orig_content) do
''
end
validate_zero = "[section]\n"
it 'adds an empty section' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section', path: emptyfile))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(validate_zero, emptyfile)
end
validate_one = '[section1]
setting1 = hellowworld
'
it 'adds a new section' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'setting1', value: 'hellowworld', path: emptyfile))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(validate_one, emptyfile)
end
validate_two = '-section1-
setting1 = hellowworld
'
it 'adds a new section with pre/suffix' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section1', setting: 'setting1', value: 'hellowworld', path: emptyfile, section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(validate_two, emptyfile)
end
validate_three = '[section:subsection]
setting1 = hellowworld
'
it 'adds a new section with colon' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section:subsection', setting: 'setting1', value: 'hellowworld', path: emptyfile))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(validate_three, emptyfile)
end
validate_four = '-section:subsection-
setting1 = hellowworld
'
it 'adds a new section with pre/suffix with colon' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section:subsection', setting: 'setting1', value: 'hellowworld', path: emptyfile, section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(validate_four, emptyfile)
end
end
context 'when only an empty section exists' do
let(:orig_content) do
"[section]\n"
end
it 'adds a new setting' do
expected = orig_content
{ 'section' => { 'first' => 1 } }.each_pair do |section, settings|
settings.each_pair do |setting, value|
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: section, setting: setting, value: value))
provider = described_class.new(resource)
expect(provider.exists?).to be false
# byebug
provider.create
expected += "#{setting} = #{value}\n"
end
end
validate_file(expected, tmpfile)
end
end
context 'when dealing with a global section' do
let(:orig_content) do
<<-EOS
# This is a comment
foo=blah
[section2]
foo = http://192.168.1.1:8080
; yet another comment
EOS
end
expected_content_one = <<-EOS
# This is a comment
foo=blah
bar = yippee
[section2]
foo = http://192.168.1.1:8080
; yet another comment
EOS
it "adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
# This is a comment
foo=yippee
[section2]
foo = http://192.168.1.1:8080
; yet another comment
EOS
it 'modifies 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)
expect(provider.value).to eq('blah')
provider.value = 'yippee'
validate_file(expected_content_two, tmpfile)
end
it 'recognizes 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)
expect(provider.exists?).to be true
end
end
context 'when the first line of the file is a section' do
let(:orig_content) do
<<-EOS
[section2]
foo = http://192.168.1.1:8080
EOS
end
expected_content_one = <<-EOS
foo = yippee
[section2]
foo = http://192.168.1.1:8080
EOS
it 'is 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
[section2]
foo = yippee
EOS
it 'modifies an existing setting' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section2', setting: 'foo', value: 'yippee'))
provider = described_class.new(resource)
expect(provider.value).to eq('http://192.168.1.1:8080')
provider.value = 'yippee'
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
[section2]
foo = http://192.168.1.1:8080
bar = baz
EOS
it 'adds a new setting' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section2', setting: 'bar', value: 'baz'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_three, tmpfile)
end
end
context 'when overriding the separator' do
let(:orig_content) do
<<-EOS
[section2]
foo=bar
EOS
end
expected_content_one = <<-EOS
[section2]
foo=yippee
EOS
it 'modifies 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)
expect(provider.value).to eq('bar')
provider.value = 'yippee'
validate_file(expected_content_one, tmpfile)
end
end
context 'when overriding the separator to something other than =' do
let(:orig_content) do
<<-EOS
[section2]
foo: bar
EOS
end
expected_content_one = <<-EOS
[section2]
foo: yippee
EOS
it 'modifies 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)
expect(provider.value).to eq('bar')
provider.value = 'yippee'
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
[section2]
foo: bar
bar: baz
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_two, tmpfile)
end
end
context 'when overriding the separator to a space' do
let(:orig_content) do
<<-EOS
[section2]
foo bar
EOS
end
expected_content_one = <<-EOS
[section2]
foo yippee
EOS
it 'modifies 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)
expect(provider.value).to eq('bar')
provider.value = 'yippee'
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
[section2]
foo bar
bar baz
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_two, tmpfile)
end
end
context 'when ensuring that a setting is absent' do
let(:orig_content) do
<<-EOS
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
uncom = ment
[section4]
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
end
expected_content_one = <<-EOS
[section1]
; This is also a comment
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
uncom = ment
[section4]
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'removes 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)
expect(provider.exists?).to be true
provider.destroy
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
uncom = ment
[section4]
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
EOS
it 'removes a setting with pre/suffix that exists' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'shoes', ensure: 'absent', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.destroy
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
uncom = ment
[section4]
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'does 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)
expect(provider.exists?).to be false
provider.destroy
validate_file(expected_content_three, tmpfile)
end
expected_content_four = <<-EOS
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
uncom = ment
[section4]
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'does nothing for a setting with pre/suffix that does not exist' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'nonstandard', setting: 'foo', ensure: 'absent', section_prefix: '-', section_suffix: '-'))
provider = described_class.new(resource)
expect(provider.exists?).to be false
provider.destroy
validate_file(expected_content_four, tmpfile)
end
expected_content_five = <<-EOS
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
[section4]
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'does not remove a section when the last uncommented setting is removed if there are comments' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section3', setting: 'uncom', ensure: 'absent'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.destroy
validate_file(expected_content_five, tmpfile)
end
expected_content_six = <<-EOS
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section2]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section3]
# com = ment
uncom = ment
[section:sub]
subby=bar
#another comment
; yet another comment
-nonstandard-
shoes = purple
EOS
it 'removes the section when removing the last line in the section' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section4', setting: 'uncom', ensure: 'absent'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.destroy
validate_file(expected_content_six, tmpfile)
end
end
context 'when dealing with indentation in sections' do
let(:orig_content) do
<<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
expected_content_one = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue2
- master = true
+ main = 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 'updates 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)
expect(provider.exists?).to be true
provider.create
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_three, tmpfile)
end
expected_content_four = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
it 'updates 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)
expect(provider.exists?).to be true
provider.create
validate_file(expected_content_four, tmpfile)
end
expected_content_five = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_five, tmpfile)
end
expected_content_six = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
it 'updates 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)
expect(provider.exists?).to be true
provider.create
validate_file(expected_content_six, tmpfile)
end
expected_content_seven = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
- master = true
+ main = 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
it 'updates an existing setting at the previous indentation regardless of indent_char and indent_width settings' do
resource = Puppet::Type::Ini_setting.new(common_params.merge(section: 'section:sub', setting: 'fleezy', value: 'flam2', indent_char: 'ignore this', indent_width: 10))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.create
validate_file(expected_content_seven, tmpfile)
end
end
context 'when dealing settings that have a commented version present' do
let(:orig_content) do
<<-EOS
[section1]
# foo=foovalue
bar=barvalue
foo = foovalue2
[section2]
# foo = foovalue
;bar=barvalue
blah = blah
#baz=
EOS
end
expected_content_eight = <<-EOS
[section1]
# foo=foovalue
bar=barvalue
foo = foovalue2
[section2]
# foo = foovalue
foo = foo3
;bar=barvalue
blah = blah
#baz=
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_eight, tmpfile)
end
expected_content_nine = <<-EOS
[section1]
# foo=foovalue
bar=barvalue
foo = foo3
[section2]
# foo = foovalue
;bar=barvalue
blah = blah
#baz=
EOS
it 'updates 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)
expect(provider.exists?).to be true
provider.create
validate_file(expected_content_nine, tmpfile)
end
expected_content_ten = <<-EOS
[section1]
# foo=foovalue
bar=barvalue
foo = foovalue2
[section2]
# foo = foovalue
;bar=barvalue
bar = bar3
blah = blah
#baz=
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_ten, tmpfile)
end
expected_content_four = <<-EOS
[section1]
# foo=foovalue
bar=barvalue
foo = foovalue2
[section2]
# foo = foovalue
;bar=barvalue
blah = blah
#baz=
baz = bazvalue
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_four, tmpfile)
end
context 'when a section only contains comments' do
let(:orig_content) do
<<-EOS
[section1]
# foo=foovalue
# bar=bar2
EOS
end
expected_content_one = <<-EOS
[section1]
# foo=foovalue
foo = foovalue2
# bar=bar2
EOS
it 'is 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
[section1]
# foo=foovalue
# bar=bar2
bar = barvalue2
EOS
it 'is 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_two, tmpfile)
end
end
context 'when sections have spaces and dashes' do
let(:orig_content) do
<<-EOS
# This is a comment
[section - one]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = true
[section - two]
foo= foovalue2
baz=bazvalue
url = http://192.168.1.1:8080
[section:sub]
subby=bar
#another comment
; yet another comment
EOS
end
expected_content_one = <<-EOS
# This is a comment
[section - one]
; This is also a comment
foo=foovalue
bar = barvalue
-master = true
+main = 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
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
end
end
context 'when sections have spaces and quotations' do
let(:orig_content) do
<<-EOS
-[branch "master"]
+[branch "main"]
remote = origin
- merge = refs/heads/master
+ merge = refs/heads/main
[alias]
-to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
+to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/main
[branch "production"]
remote = origin
merge = refs/heads/production
EOS
end
expected_content_one = <<-EOS
-[branch "master"]
+[branch "main"]
remote = origin
- merge = refs/heads/master
+ merge = refs/heads/main
[alias]
-to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
+to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/main
foo = bar
[branch "production"]
remote = origin
merge = refs/heads/production
EOS
it 'adds 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)
expect(provider.exists?).to be false
provider.create
validate_file(expected_content_one, tmpfile)
end
end
# rubocop:enable Layout/IndentHeredoc
end
diff --git a/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb b/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb
index d7a6986..18f22f7 100644
--- a/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb
+++ b/spec/unit/puppet/provider/ini_subsetting/ruby_spec.rb
@@ -1,361 +1,361 @@
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)
expect(File.read(tmpfile)).to eq 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) do
{
title: 'ini_setting_ensure_present_test',
path: tmpfile,
section: '',
key_val_separator: '=',
setting: 'JAVA_ARGS',
}
end
let(:orig_content) do
<<-EOS
JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
end
expected_content_one = <<-EOS
JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof -Xms128m"
EOS
it 'adds a missing subsetting' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m'))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.create
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
JAVA_ARGS="-Xms128m -Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
it 'adds a missing subsetting element at the beginning of the line' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :start))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.create
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
JAVA_ARGS="-Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof -Xms128m"
EOS
it 'adds a missing subsetting element at the end of the line' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :end))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.create
validate_file(expected_content_three, tmpfile)
end
expected_content_four = <<-EOS
JAVA_ARGS="-Xmx192m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
it 'adds a missing subsetting element after the given item' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :after, insert_value: '-Xmx'))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.create
validate_file(expected_content_four, tmpfile)
end
expected_content_five = <<-EOS
JAVA_ARGS="-Xms128m -Xmx192m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
it 'adds a missing subsetting element before the given item' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :before, insert_value: '-Xmx'))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.create
validate_file(expected_content_five, tmpfile)
end
expected_content_six = <<-EOS
JAVA_ARGS="-Xmx192m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
it 'adds a missing subsetting element at the given index' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xms', value: '128m', insert_type: :index, insert_value: '1'))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.create
validate_file(expected_content_six, tmpfile)
end
expected_content_seven = <<-EOS
JAVA_ARGS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
it 'removes an existing subsetting' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xmx'))
provider = described_class.new(resource)
expect(provider.exists?).to eq '192m'
provider.destroy
validate_file(expected_content_seven, tmpfile)
end
expected_content_eight = <<-EOS
JAVA_ARGS="-Xmx192m"
EOS
it 'is able to remove several subsettings with the same name' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-XX'))
provider = described_class.new(resource)
expect(provider.exists?).to eq ':+HeapDumpOnOutOfMemoryError'
provider.destroy
validate_file(expected_content_eight, tmpfile)
end
expected_content_nine = <<-EOS
JAVA_ARGS="-Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/pe-puppetdb/puppetdb-oom.hprof"
EOS
it 'modifies an existing subsetting' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-Xmx', value: '256m'))
provider = described_class.new(resource)
expect(provider.exists?).to eq '192m'
provider.value = '256m'
validate_file(expected_content_nine, tmpfile)
end
expected_content_ten = <<-EOS
JAVA_ARGS="-Xmx192m -XXtest -XXtest"
EOS
it 'is able to modify several subsettings with the same name' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: '-XX', value: 'test'))
provider = described_class.new(resource)
expect(provider.exists?).to eq ':+HeapDumpOnOutOfMemoryError'
provider.value = 'test'
validate_file(expected_content_ten, tmpfile)
end
end
context 'when working with subsettings in files with unquoted settings values' do
let(:common_params) do
{
title: 'ini_setting_ensure_present_test',
path: tmpfile,
- section: 'master',
+ section: 'main',
setting: 'reports',
}
end
let(:orig_content) do
<<-EOS
- [master]
+ [main]
reports = http,foo
EOS
end
expected_content_one = <<-EOS
- [master]
+ [main]
reports = foo
EOS
it 'removes an existing subsetting' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'http', subsetting_separator: ','))
provider = described_class.new(resource)
expect(provider.exists?).to eq ''
provider.destroy
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
- [master]
+ [main]
reports = http,foo,puppetdb
EOS
it "adds 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)
expect(provider.exists?).to be_nil
provider.value = ''
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
- [master]
+ [main]
reports = http,foo
somenewsetting = puppetdb
EOS
it "adds 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)
expect(provider.exists?).to be_nil
provider.value = ''
validate_file(expected_content_three, tmpfile)
end
end
context 'when working with subsettings in files with use_exact_match' do
let(:common_params) do
{
title: 'ini_setting_ensure_present_test',
path: tmpfile,
- section: 'master',
+ section: 'main',
setting: 'reports',
use_exact_match: true,
}
end
let(:orig_content) do
<<-EOS
- [master]
+ [main]
reports = http,foo
EOS
end
expected_content_one = <<-EOS
- [master]
+ [main]
reports = http,foo,fo
EOS
it "adds a new subsetting when the 'parent' setting already exists" do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'fo', subsetting_separator: ','))
provider = described_class.new(resource)
provider.value = ''
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
- [master]
+ [main]
reports = http,foo
EOS
it 'does not remove substring subsettings' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'fo', subsetting_separator: ','))
provider = described_class.new(resource)
provider.value = ''
provider.destroy
validate_file(expected_content_two, tmpfile)
end
end
context 'when working with subsettings in files with subsetting_key_val_separator' do
let(:common_params) do
{
title: 'ini_setting_ensure_present_test',
path: tmpfile,
- section: 'master',
+ section: 'main',
setting: 'reports',
subsetting_separator: ',',
subsetting_key_val_separator: ':',
}
end
let(:orig_content) do
<<-EOS
- [master]
+ [main]
reports = a:1,b:2
EOS
end
expected_content_one = <<-EOS
- [master]
+ [main]
reports = a:1,b:2,c:3
EOS
it "adds a new subsetting when the 'parent' setting already exists" do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'c', value: '3'))
provider = described_class.new(resource)
provider.value = '3'
validate_file(expected_content_one, tmpfile)
end
expected_content_two = <<-EOS
- [master]
+ [main]
reports = a:1,b:2
somenewsetting = c:3
EOS
it "adds a new subsetting when the 'parent' setting does not already exist" do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'c', value: '3', setting: 'somenewsetting'))
provider = described_class.new(resource)
expect(provider.exists?).to be_nil
provider.value = '3'
validate_file(expected_content_two, tmpfile)
end
expected_content_three = <<-EOS
- [master]
+ [main]
reports = a:1
EOS
it 'is able to remove the existing subsetting' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'b'))
provider = described_class.new(resource)
expect(provider.exists?).to eq '2'
provider.destroy
validate_file(expected_content_three, tmpfile)
end
expected_content_four = <<-EOS
- [master]
+ [main]
reports = a:1,b:5
EOS
it 'is able to modify the existing subsetting' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(subsetting: 'b', value: '5'))
provider = described_class.new(resource)
expect(provider.exists?).to eq '2'
provider.value = '5'
validate_file(expected_content_four, tmpfile)
end
end
context 'when delete_if_empty is toggled to true' do
let(:common_params) do
{
title: 'ini_setting_delete_if_empty_test',
path: tmpfile,
- section: 'master',
+ section: 'main',
delete_if_empty: true,
}
end
let(:orig_content) do
<<-EOS
- [master]
+ [main]
reports = http
something = else
EOS
end
expected_content_one = <<-EOS
- [master]
+ [main]
something = else
EOS
expected_content_two = ''
it 'removes the subsetting when the it is empty' do
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(setting: 'reports', subsetting: 'http', subsetting_separator: ','))
provider = described_class.new(resource)
provider.destroy
validate_file(expected_content_one, tmpfile)
resource = Puppet::Type::Ini_subsetting.new(common_params.merge(setting: 'something', subsetting: 'else', subsetting_separator: ','))
provider = described_class.new(resource)
provider.destroy
validate_file(expected_content_two, tmpfile)
end
end
end
diff --git a/spec/unit/puppet/util/ini_file_spec.rb b/spec/unit/puppet/util/ini_file_spec.rb
index 2f284d3..bb4ceda 100644
--- a/spec/unit/puppet/util/ini_file_spec.rb
+++ b/spec/unit/puppet/util/ini_file_spec.rb
@@ -1,316 +1,316 @@
require 'spec_helper'
require 'stringio'
require 'puppet/util/ini_file'
describe Puppet::Util::IniFile do
subject(:ini_sub) { described_class.new('/my/ini/file/path') }
before :each do
allow(File).to receive(:file?).with('/my/ini/file/path') { true }
allow(described_class).to receive(:readlines).once.with('/my/ini/file/path') do
sample_content
end
end
context 'when parsing a file' do
let(:sample_content) do
template = <<-EOS
# This is a comment
[section1]
; This is also a comment
foo=foovalue
bar = barvalue
baz =
[section2]
foo= foovalue2
baz=bazvalue
; commented = out setting
#another comment
; yet another comment
zot = multi word value
xyzzy['thing1']['thing2']=xyzzyvalue
l=git log
EOS
template.split("\n")
end
it 'parses the correct number of sections' do
# there is always a "global" section, so our count should be 3.
expect(ini_sub.section_names.length).to eq(3)
end
it 'parses the correct section_names' do
# there should always be a "global" section named "" at the beginning of the list
expect(ini_sub.section_names).to eq(['', 'section1', 'section2'])
end
it 'exposes settings for sections #section1' do
expect(ini_sub.get_settings('section1')).to eq('bar' => 'barvalue',
'baz' => '',
'foo' => 'foovalue')
end
it 'exposes settings for sections #section2' do
expect(ini_sub.get_settings('section2')).to eq('baz' => 'bazvalue',
'foo' => 'foovalue2',
'l' => 'git log',
"xyzzy['thing1']['thing2']" => 'xyzzyvalue',
'zot' => 'multi word value')
end
end
context 'when parsing a file whose first line is a section' do
let(:sample_content) do
template = <<-EOS
[section1]
; This is a comment
foo=foovalue
EOS
template.split("\n")
end
it 'parses the correct number of sections' do
# there is always a "global" section, so our count should be 2.
expect(ini_sub.section_names.length).to eq(2)
end
it 'parses the correct section_names' do
# there should always be a "global" section named "" at the beginning of the list
expect(ini_sub.section_names).to eq(['', 'section1'])
end
it 'exposes settings for sections' do
expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue')
end
end
context "when parsing a file with a 'global' section" do
let(:sample_content) do
template = <<-EOS
foo = bar
[section1]
; This is a comment
foo=foovalue
EOS
template.split("\n")
end
it 'parses the correct number of sections' do
# there is always a "global" section, so our count should be 2.
expect(ini_sub.section_names.length).to eq(2)
end
it 'parses the correct section_names' do
# there should always be a "global" section named "" at the beginning of the list
expect(ini_sub.section_names).to eq(['', 'section1'])
end
it 'exposes settings for sections #bar' do
expect(ini_sub.get_value('', 'foo')).to eq('bar')
end
it 'exposes settings for sections #foovalue' do
expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue')
end
end
context 'when updating a file with existing empty values' do
let(:sample_content) do
template = <<-EOS
[section1]
foo=
#bar=
#xyzzy['thing1']['thing2']='xyzzyvalue'
EOS
template.split("\n")
end
# rubocop:disable RSpec/ExpectInHook
before :each do
expect(ini_sub.get_value('section1', 'far')).to eq(nil)
expect(ini_sub.get_value('section1', 'bar')).to eq(nil)
expect(ini_sub.get_value('section1', "xyzzy['thing1']['thing2']")).to eq(nil)
end
# rubocop:enable RSpec/ExpectInHook
it 'properlies update uncommented values' do
ini_sub.set_value('section1', 'foo', ' = ', 'foovalue')
expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue')
end
it 'properlies update uncommented values without separator' do
ini_sub.set_value('section1', 'foo', 'foovalue')
expect(ini_sub.get_value('section1', 'foo')).to eq('foovalue')
end
it 'properlies update commented value' do
ini_sub.set_value('section1', 'bar', ' = ', 'barvalue')
expect(ini_sub.get_value('section1', 'bar')).to eq('barvalue')
end
it 'properlies update commented values' do
ini_sub.set_value('section1', "xyzzy['thing1']['thing2']", ' = ', 'xyzzyvalue')
expect(ini_sub.get_value('section1', "xyzzy['thing1']['thing2']")).to eq('xyzzyvalue')
end
it 'properlies update commented value without separator' do
ini_sub.set_value('section1', 'bar', 'barvalue')
expect(ini_sub.get_value('section1', 'bar')).to eq('barvalue')
end
it 'properlies update commented values without separator' do
ini_sub.set_value('section1', "xyzzy['thing1']['thing2']", 'xyzzyvalue')
expect(ini_sub.get_value('section1', "xyzzy['thing1']['thing2']")).to eq('xyzzyvalue')
end
it 'properlies add new empty values' do
ini_sub.set_value('section1', 'baz', ' = ', 'bazvalue')
expect(ini_sub.get_value('section1', 'baz')).to eq('bazvalue')
end
it 'adds new empty values without separator' do
ini_sub.set_value('section1', 'baz', 'bazvalue')
expect(ini_sub.get_value('section1', 'baz')).to eq('bazvalue')
end
end
context 'the file has quotation marks in its section names' do
let(:sample_content) do
template = <<-EOS
- [branch "master"]
+ [branch "main"]
remote = origin
- merge = refs/heads/master
+ merge = refs/heads/main
[alias]
- to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/master
+ to-deploy = log --merges --grep='pull request' --format='%s (%cN)' origin/production..origin/main
[branch "production"]
remote = origin
merge = refs/heads/production
EOS
template.split("\n")
end
it 'parses the sections' do
expect(ini_sub.section_names).to match_array ['',
- 'branch "master"',
+ 'branch "main"',
'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 'parses the correct section_names' do
expect(ini_sub.section_names).to 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 'parses the correct section_names' do
expect(ini_sub.section_names).to match_array [
'',
'monitor:///var/log/*.log',
]
end
end
context 'KDE Configuration with braces in setting names' do
let(:sample_content) do
template = <<-EOS
[khotkeys]
_k_friendly_name=khotkeys
{5465e8c7-d608-4493-a48f-b99d99fdb508}=Print,none,PrintScreen
{d03619b6-9b3c-48cc-9d9c-a2aadb485550}=Search,none,Search
EOS
template.split("\n")
end
it 'exposes settings for sections #print' do
expect(ini_sub.get_value('khotkeys', '{5465e8c7-d608-4493-a48f-b99d99fdb508}')).to eq('Print,none,PrintScreen')
end
it 'exposes settings for sections #search' do
expect(ini_sub.get_value('khotkeys', '{d03619b6-9b3c-48cc-9d9c-a2aadb485550}')).to eq('Search,none,Search')
end
end
context 'Configuration with colons in setting names' do
let(:sample_content) do
template = <<-EOS
[Drive names]
A:=5.25" Floppy
B:=3.5" Floppy
C:=Winchester
EOS
template.split("\n")
end
it 'exposes settings for sections #A' do
expect(ini_sub.get_value('Drive names', 'A:')).to eq '5.25" Floppy'
end
it 'exposes settings for sections #B' do
expect(ini_sub.get_value('Drive names', 'B:')).to eq '3.5" Floppy'
end
it 'exposes settings for sections #C' do
expect(ini_sub.get_value('Drive names', 'C:')).to eq 'Winchester'
end
end
context 'Configuration with spaces in setting names' do
let(:sample_content) do
template = <<-EOS
[global]
# log files split per-machine:
log file = /var/log/samba/log.%m
kerberos method = system keytab
passdb backend = tdbsam
security = ads
EOS
template.split("\n")
end
it 'exposes settings for sections #log' do
expect(ini_sub.get_value('global', 'log file')).to eq '/var/log/samba/log.%m'
end
it 'exposes settings for sections #kerberos' do
expect(ini_sub.get_value('global', 'kerberos method')).to eq 'system keytab'
end
it 'exposes settings for sections #passdb' do
expect(ini_sub.get_value('global', 'passdb backend')).to eq 'tdbsam'
end
it 'exposes settings for sections #security' do
expect(ini_sub.get_value('global', 'security')).to eq 'ads'
end
end
end