puppet-lint-2.4.2/0000755000004100000410000000000013611752231014031 5ustar www-datawww-datapuppet-lint-2.4.2/.travis.yml0000644000004100000410000000053613611752231016146 0ustar www-datawww-data--- language: ruby dist: trusty sudo: false branches: only: - master bundler_args: --without development system_tests script: - bundle exec rake $CHECK env: - CHECK=ci rvm: - 1.8.7 - 1.9.3 - 2.0.0 - 2.1.10 - 2.2.10 - 2.3.8 - 2.4.7 - 2.5.6 - 2.6.4 matrix: include: - rvm: 2.6.4 env: CHECK=rubocop puppet-lint-2.4.2/.rspec0000644000004100000410000000003713611752231015146 0ustar www-datawww-data--format documentation --color puppet-lint-2.4.2/README.md0000644000004100000410000002577213611752231015325 0ustar www-datawww-data# Puppet Lint [![Build Status](https://secure.travis-ci.org/rodjek/puppet-lint.png)](http://travis-ci.org/rodjek/puppet-lint) [![Inline docs](http://inch-ci.org/github/rodjek/puppet-lint.png?branch=master)](http://inch-ci.org/github/rodjek/puppet-lint) Puppet Lint tests Puppet code against the recommended [Puppet language style guide](http://puppet.com/docs/puppet/latest/style_guide.html). Puppet Lint validates only code style; it does not validate syntax. To test syntax, use Puppet's `puppet parser validate` command. ## Compatibility warning Puppet Lint version 2 is the last planned version with support for Puppet 3 and Ruby 1.8.7. The next major version of Puppet Lint will drop support for these versions. ## Installation Install the Puppet Lint gem by running: ``` gem install puppet-lint ``` ## Testing with Puppet Lint To test manifests for correct Puppet style, run the `puppet-lint` command with the path to the files you want to test. For example: ``` puppet-lint ~/modules/puppetlabs-java/manifests/init.pp ``` ``` puppet-lint ~/modules/puppetlabs-mysql/manifests ``` ### Fix issues automatically To instruct Lint to automatically fix any issues that it detects, use the `--fix` flag: ``` puppet-lint --fix /modules ``` ### Modify which checks to run Puppet Lint options allow you to modify which checks to run. You can disable any of the checks temporarily or permanently, or you can limit testing to specific checks. #### List all available checks To list all available checks along with basic usage documentation, use the `--list-checks` option. #### Run specific checks To run only specific checks, use the `--only-checks` option, with a comma-separated list of arguments specifying which checks to make: ``` puppet-lint --only-checks trailing_whitespace,140chars modules/ ``` To avoid enormous patch sets when using the `--fix` flag, use the `--only-checks` option to limit which checks Puppet Lint makes: ``` puppet-lint --only-checks trailing_whitespace --fix modules/ ``` ### Disable Lint checks You can disable specific Lint checks on the command line, disable them permanently with a configuration file, or disable them with control comments within your Puppet code. #### Disable checks on the command line To disable any of the checks when running the `puppet-lint` command, add a `--no--check` flag to the command. For example, to skip the 140-character check, run: ``` puppet-lint --no-140chars-check modules/ ``` #### Disable checks within Puppet code To disable checks from within your Puppet code itself, use [control comments](http://puppet-lint.com/controlcomments/). Disable checks on either a per-line or per-block basis using `#lint:ignore:`. For example: ```puppet class foo { $bar = 'bar' # This ignores the double_quoted_strings check over multiple lines # lint:ignore:double_quoted_strings $baz = "baz" $gronk = "gronk" # lint:endignore # This ignores the 140chars check on a single line $this_line_has_a_really_long_name_and_value_that_is_much_longer_than_the_style_guide_recommends = "I mean, a really, really long line like you can't believe" # lint:ignore:140chars } ``` ## Configuration file Each time Puppet Lint starts up, it loads configuration from three files in order: 1. `/etc/puppet-lint.rc` 1. `~/.puppet-lint.rc` 1. `.puppet-lint.rc` This means that a flag in the local `.puppet-lint.rc` will take precedence over a flag in the global `/etc/puppet-lint.rc`, for example. Flags specified on the command line take final precedence and override all config file options. Any flag that can be specified on the command line can also be specified in the configuration file. For example, to always skip the hard tab character check, create `~/.puppet-lint.rc` and include the line: ``` --no-hard_tabs-check ``` Or to specify a whitelist of allowed checks, include a line like: ``` --only-checks=trailing_whitespace,hard_tabs,duplicate_params,double_quoted_strings,unquoted_file_mode,only_variable_string,variables_not_enclosed,single_quote_string_with_variables,variable_contains_dash,ensure_not_symlink_target,unquoted_resource_title,relative_classname_inclusion,file_mode,resource_reference_without_title_capital,leading_zero,arrow_alignment,variable_is_lowercase,ensure_first_param,resource_reference_without_whitespace,file_ensure,trailing_comma,leading_zero ``` Please note that there is an important difference between reading options from the command line and reading options from a configuration file: In the former case the shell interprets one level of quotes. That does not happen in the latter case. So, it would make sense to quote some configuration values on the command line, like so: ``` $ puppet-lint --ignore-paths 'modules/stdlib/*' modules/ ``` When reading from a configuration file those quotes would be passed on to the option parser -- probably not giving the expected result. Instead the line should read ``` --ignore-paths=modules/stdlib/* ``` ## Testing with Puppet Lint as a Rake task To test your entire Puppet manifest directory, add `require 'puppet-lint/tasks/puppet-lint'` to your Rakefile and then run: ``` rake lint ``` To modify the default behaviour of the Rake task, modify the Puppet Lint configuration by defining the task yourself. For example: ```ruby PuppetLint::RakeTask.new :lint do |config| # Pattern of files to check, defaults to `**/*.pp` config.pattern = 'modules' # Pattern of files to ignore config.ignore_paths = ['modules/apt', 'modules/stdlib'] # List of checks to disable config.disable_checks = ['documentation', '140chars'] # Should puppet-lint prefix it's output with the file being checked, # defaults to true config.with_filename = false # Should the task fail if there were any warnings, defaults to false config.fail_on_warnings = true # Format string for puppet-lint's output (see the puppet-lint help output # for details config.log_format = '%{filename} - %{message}' # Print out the context for the problem, defaults to false config.with_context = true # Enable automatic fixing of problems, defaults to false config.fix = true # Show ignored problems in the output, defaults to false config.show_ignored = true # Compare module layout relative to the module root config.relative = true end ``` ### Disable checks in the Lint Rake task You can also disable checks when running Puppet Lint through the supplied Rake task by modifying your `Rakefile`. * To disable a check, add the following line after the `require` statement in your `Rakefile`: ```ruby PuppetLint.configuration.send("disable_") ``` For example, to disable the 140-character check, add: ```ruby PuppetLint.configuration.send("disable_140chars") ``` * To set the Lint Rake task to ignore certain paths: ```ruby PuppetLint.configuration.ignore_paths = ["vendor/**/*.pp"] ``` * To set a pattern of files that Lint should check: ```ruby # Defaults to `**/*.pp` PuppetLint.configuration.pattern = "modules" ``` ## Testing with Puppet Lint as a GitHub Action There is a GitHub Actions action available to get linter feedback in workflows: * [puppet-lint-action](https://github.com/marketplace/actions/puppet-lint-action) ## Options See `puppet-lint --help` for a full list of command line options and checks. ## Checks For a complete list of checks, and how to resolve errors on each check, see the Puppet Lint [checks](http://puppet-lint.com/checks/) page. ### Spacing, Indentation, and Whitespace * Must use two-space soft tabs. * Must not use literal tab characters. * Must not contain trailing white space. * Should not exceed an 140-character line width. * An exception has been made for `source => 'puppet://...'` lines as splitting these over multiple lines decreases the readability of the manifests. * Should align arrows (`=>`) within blocks of attributes. ### Quoting * All strings that do not contain variables should be enclosed in single quotes. * An exception has been made for double-quoted strings containing \n or \t. * All strings that contain variables must be enclosed in double quotes. * All variables should be enclosed in braces when interpolated in a string. * Variables standing by themselves should not be quoted. ### Capitalization * All variables should be in lowercase. ### Resources * All resource titles should be quoted. * An exception has been made for resource titles that consist of only a variable standing by itself. * If a resource declaration includes an `ensure` attribute, it should be the first attribute specified. * Symbolic links should be declared by using an ensure value of `link` and explicitly specifying a value for the `target` attribute. * File modes should be represented as a 4-digit string enclosed in single quotes or use symbolic file modes. ### Conditionals * You should not intermingle conditionals inside resource declarations (that is, selectors inside resources). * Case statements should have a default case. ### Classes * Relationship declarations with the chaining syntax should only be used in the 'left to right' direction. * Classes should not be defined inside a class. * Defines should not be defined inside a class. * Classes should not inherit between namespaces. * Required parameters in class & defined type definitions should be listed before optional parameters. * When using top-scope variables, including facts, Puppet modules should explicitly specify the empty namespace. * Chaining operators should appear on the same line as the right hand operand. ## Reporting bugs or incorrect results If you find a bug in Puppet Lint or its results, please create an issue in the [repo issues tracker](https://github.com/rodjek/puppet-lint/issues/). Bonus points will be awarded if you also include a patch that fixes the issue. ## Thank you Many thanks to the following people for contributing to puppet-lint * James Turnbull (@kartar) * Jan Vansteenkiste (@vStone) * Julian Simpson (@simpsonjulian) * S. Zachariah Sprackett (@zsprackett) As well as the many people who have reported the issues they've had! ## License Copyright (c) 2011-2016 Tim Sharpe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. puppet-lint-2.4.2/bin/0000755000004100000410000000000013611752231014601 5ustar www-datawww-datapuppet-lint-2.4.2/bin/puppet-lint0000755000004100000410000000022313611752231017005 0ustar www-datawww-data#!/usr/bin/env ruby $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'puppet-lint' exit PuppetLint::Bin.new(ARGV).run puppet-lint-2.4.2/spec/0000755000004100000410000000000013611752231014763 5ustar www-datawww-datapuppet-lint-2.4.2/spec/fixtures/0000755000004100000410000000000013611752231016634 5ustar www-datawww-datapuppet-lint-2.4.2/spec/fixtures/test/0000755000004100000410000000000013611752231017613 5ustar www-datawww-datapuppet-lint-2.4.2/spec/fixtures/test/manifests/0000755000004100000410000000000013611752231021604 5ustar www-datawww-datapuppet-lint-2.4.2/spec/fixtures/test/manifests/ignore_reason.pp0000644000004100000410000000017113611752231024776 0ustar www-datawww-data# test::ignore_reason class test::ignore_reason { $foo = "test" # lint:ignore:double_quoted_strings for a good reason }puppet-lint-2.4.2/spec/fixtures/test/manifests/init.pp0000644000004100000410000000002513611752231023105 0ustar www-datawww-data# foo class test { } puppet-lint-2.4.2/spec/fixtures/test/manifests/url_interpolation.pp0000644000004100000410000000033213611752231025714 0ustar www-datawww-datafile { 'test1': source => 'puppet:///foo' } file { 'test2': source => "puppet:///foo/${::fqdn}" } file { 'test3': source => "puppet:///${::fqdn}/foo" } file { 'test4': source => "puppet:///foo/${::fqdn}/bar" } puppet-lint-2.4.2/spec/fixtures/test/manifests/unterminated_control_comment.pp0000644000004100000410000000041513611752231030126 0ustar www-datawww-datajenkins::cli::exec { "create-jenkins-credentials-${title}": # lint:ignore:140chars unless => "for i in \$(seq 1 ${::jenkins::cli_tries}); do \$HELPER_CMD credential_info ${title} && break || sleep ${::jenkins::cli_try_sleep}; done | grep ${title}", # lint:end } puppet-lint-2.4.2/spec/fixtures/test/manifests/fail.pp0000644000004100000410000000003213611752231023053 0ustar www-datawww-data# foo class test::foo { } puppet-lint-2.4.2/spec/fixtures/test/manifests/two_warnings.pp0000644000004100000410000000012713611752231024666 0ustar www-datawww-data# foo define test::two_warnings() { $var1-with-dash = 42 $VarUpperCase = false } puppet-lint-2.4.2/spec/fixtures/test/manifests/ignore_multiple_block.pp0000644000004100000410000000015013611752231026511 0ustar www-datawww-data# lint:ignore:double_quoted_strings lint:ignore:quoted_booleans "true" "false" # lint:endignore "true" puppet-lint-2.4.2/spec/fixtures/test/manifests/ignore.pp0000644000004100000410000000005313611752231023426 0ustar www-datawww-data"test" # lint:ignore:double_quoted_strings puppet-lint-2.4.2/spec/fixtures/test/manifests/malformed.pp0000644000004100000410000000004613611752231024113 0ustar www-datawww-dataclass { 'apacheds': master => true' } puppet-lint-2.4.2/spec/fixtures/test/manifests/mismatched_control_comment.pp0000644000004100000410000000002113611752231027536 0ustar www-datawww-data# lint:endignore puppet-lint-2.4.2/spec/fixtures/test/manifests/ignore_multiple_line.pp0000644000004100000410000000022613611752231026352 0ustar www-datawww-data"true" # lint:ignore:double_quoted_strings lint:ignore:quoted_booleans "false" # lint:ignore:quoted_booleans lint:ignore:double_quoted_strings reason puppet-lint-2.4.2/spec/fixtures/test/manifests/warning.pp0000644000004100000410000000006113611752231023607 0ustar www-datawww-data# foo define test::warning($foo='bar', $baz) { } puppet-lint-2.4.2/spec/puppet-lint/0000755000004100000410000000000013611752231017244 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/data_spec.rb0000644000004100000410000000604213611752231021516 0ustar www-datawww-datarequire 'spec_helper' describe PuppetLint::Data do subject(:data) { PuppetLint::Data } let(:lexer) { PuppetLint::Lexer.new } describe '.resource_indexes' do before(:each) do data.tokens = lexer.tokenise(manifest) end context 'when a namespaced class name contains a single colon' do let(:manifest) { 'class foo:bar { }' } it 'raises a SyntaxError' do expect { data.resource_indexes }.to raise_error(PuppetLint::SyntaxError) { |error| expect(error.token).to eq(data.tokens[3]) } end end context 'when typo in namespace separator makes parser look for resource' do let(:manifest) { '$testparam = $::module:;testparam' } it 'raises a SyntaxError' do expect { data.resource_indexes }.to raise_error(PuppetLint::SyntaxError) { |error| expect(error.token).to eq(data.tokens[5]) } end end end describe '.insert' do let(:manifest) { '$x = $a' } let(:new_token) { PuppetLint::Lexer::Token.new(:PLUS, '+', 0, 0) } let(:original_tokens) { lexer.tokenise(manifest) } let(:tokens) { original_tokens.dup } before do data.tokens = tokens data.insert(2, new_token) end it 'adds token at the given index' do expect(data.tokens.map(&:to_manifest).join).to eq('$x += $a') end it 'sets the prev_token' do expect(new_token.prev_token).to eq(original_tokens[1]) end it 'sets the prev_code_token' do expect(new_token.prev_code_token).to eq(original_tokens[0]) end it 'sets the next_token' do expect(new_token.next_token).to eq(original_tokens[2]) end it 'sets the next_code_token' do expect(new_token.next_code_token).to eq(original_tokens[2]) end it 'updates the existing next_token' do expect(tokens[1].next_token).to eq(new_token) end it 'updates the existing next_code_token' do expect(tokens[0].next_code_token).to eq(new_token) end it 'updates the existing prev_token' do expect(tokens[3].prev_token).to eq(new_token) end it 'updates the existing prev_code_token' do expect(tokens[3].prev_code_token).to eq(new_token) end end describe '.delete' do let(:manifest) { '$x + = $a' } let(:token) { tokens[2] } let(:original_tokens) { lexer.tokenise(manifest) } let(:tokens) { original_tokens.dup } before do data.tokens = tokens data.delete(token) end it 'removes the token' do expect(data.tokens.map(&:to_manifest).join).to eq('$x = $a') end it 'updates the existing next_token' do expect(tokens[1].next_token).to eq(original_tokens[3]) end it 'updates the existing next_code_token' do expect(tokens[0].next_code_token).to eq(original_tokens[4]) end it 'updates the existing prev_token' do expect(tokens[2].prev_token).to eq(original_tokens[1]) end it 'updates the existing prev_code_token' do expect(tokens[3].prev_code_token).to eq(original_tokens[0]) end end end puppet-lint-2.4.2/spec/puppet-lint/configuration_spec.rb0000644000004100000410000000332713611752231023457 0ustar www-datawww-datarequire 'spec_helper' describe PuppetLint::Configuration do subject { PuppetLint::Configuration.new } it 'should create check methods on the fly' do klass = Class.new subject.add_check('foo', klass) expect(subject).to respond_to(:foo_enabled?) expect(subject).to_not respond_to(:bar_enabled?) expect(subject).to respond_to(:enable_foo) expect(subject).to respond_to(:disable_foo) subject.disable_foo expect(subject.settings['foo_disabled']).to be_truthy expect(subject.foo_enabled?).to be_falsey subject.enable_foo expect(subject.settings['foo_disabled']).to be_falsey expect(subject.foo_enabled?).to be_truthy end it 'should know what checks have been added' do klass = Class.new subject.add_check('foo', klass) expect(subject.checks).to include('foo') end it 'should respond nil to unknown config options' do expect(subject.foobarbaz).to be_nil end it 'should be able to explicitly add options' do subject.add_option('bar') expect(subject.bar).to be_nil subject.bar = 'aoeui' expect(subject.bar).to eq('aoeui') end it 'should be able to add options on the fly' do expect(subject.test_option).to eq(nil) subject.test_option = 'test' expect(subject.test_option).to eq('test') end it 'should be able to set sane defaults' do subject.defaults expect(subject.settings).to eq( 'with_filename' => false, 'fail_on_warnings' => false, 'error_level' => :all, 'log_format' => '', 'with_context' => false, 'fix' => false, 'show_ignored' => false, 'json' => false, 'ignore_paths' => ['vendor/**/*.pp'] ) end end puppet-lint-2.4.2/spec/puppet-lint/bin_spec.rb0000644000004100000410000003371613611752231021365 0ustar www-datawww-datarequire 'spec_helper' require 'rspec/mocks' require 'optparse' require 'tempfile' class CommandRun attr_accessor :stdout, :stderr, :exitstatus def initialize(args) out = StringIO.new err = StringIO.new $stdout = out $stderr = err PuppetLint.configuration.defaults @exitstatus = PuppetLint::Bin.new(args).run PuppetLint.configuration.defaults @stdout = out.string.strip @stderr = err.string.strip $stdout = STDOUT $stderr = STDERR end end describe PuppetLint::Bin do subject do sane_args = if args.is_a?(Array) args else [args] end CommandRun.new(sane_args) end context 'when running normally' do let(:args) { 'spec/fixtures/test/manifests/init.pp' } its(:exitstatus) { is_expected.to eq(0) } end context 'when running without arguments' do let(:args) { [] } its(:exitstatus) { is_expected.to eq(1) } end context 'when asked to display version' do let(:args) { '--version' } its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to eq("puppet-lint #{PuppetLint::VERSION}") } end context 'when asked to display available checks' do let(:args) { '--list-checks' } all_checks = PuppetLint.configuration.checks.map(&:to_s) its(:exitstatus) { is_expected.to eq(0) } all_checks.each do |c| it "includes check #{c} in its output" do expect(subject.stdout).to include c end end end context 'when passed a backslash separated path on Windows', :if => Gem.win_platform? do let(:args) do [ 'spec\fixtures\test\manifests', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{spec/fixtures/test/manifests/warning\.pp - WARNING: optional}m) } end context 'when passed multiple files' do let(:args) do [ 'spec/fixtures/test/manifests/warning.pp', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) do is_expected.to eq( [ "#{args[0]} - WARNING: optional parameter listed before required parameter on line 2", "#{args[1]} - ERROR: test::foo not in autoload module layout on line 2", ].join("\n") ) end end context 'when passed a malformed file' do let(:args) { 'spec/fixtures/test/manifests/malformed.pp' } its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('ERROR: Syntax error on line 1') } its(:stderr) { is_expected.to eq('Try running `puppet parser validate `') } end context 'when passed ignore paths option' do let(:args) do [ '--ignore-paths', 'spec/*', 'spec/fixtures/test/manifests/malformed.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to eq('') } end context 'when limited to errors only' do let(:args) do [ '--error-level', 'error', 'spec/fixtures/test/manifests/warning.pp', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{^#{args.last} - ERROR}) } end context 'when limited to warnings only' do let(:args) do [ '--error-level', 'warning', 'spec/fixtures/test/manifests/warning.pp', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{WARNING}) } its(:stdout) { is_expected.to_not match(%r{ERROR}) } end context 'when specifying a specific check to run' do let(:args) do [ '--only-checks', 'parameter_order', 'spec/fixtures/test/manifests/warning.pp', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to_not match(%r{ERROR}) } its(:stdout) { is_expected.to match(%r{WARNING}) } end context 'when asked to display filenames ' do let(:args) do [ '--with-filename', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{^spec/fixtures/test/manifests/fail\.pp -}) } end context 'when not asked to fail on warnings' do let(:args) do [ 'spec/fixtures/test/manifests/warning.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to match(%r{optional parameter}) } end context 'when asked to provide context to problems' do let(:args) do [ '--with-context', 'spec/fixtures/test/manifests/warning.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) do is_expected.to eq( [ 'WARNING: optional parameter listed before required parameter on line 2', '', " define test::warning($foo='bar', $baz) { }", ' ^', ].join("\n") ) end end context 'when asked to fail on warnings' do let(:args) do [ '--fail-on-warnings', 'spec/fixtures/test/manifests/warning.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{optional parameter}) } end context 'when used with an invalid option' do let(:args) { '--foo-bar-baz' } its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{invalid option}) } end context 'when passed a file that does not exist' do let(:args) { 'spec/fixtures/test/manifests/enoent.pp' } its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{specified file does not exist}) } end context 'when passed a directory' do let(:args) { 'spec/fixtures/' } its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to match(%r{ERROR}) } end context 'when disabling a check' do let(:args) do [ '--no-autoloader_layout', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to eq('') } end context 'when changing the log format' do context 'to print %{filename}' do let(:args) do [ '--log-format', '%{filename}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('fail.pp') } end context 'to print %{path}' do let(:args) do [ '--log-format', '%{path}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('spec/fixtures/test/manifests/fail.pp') } end context 'to print %{fullpath}' do let(:args) do [ '--log-format', '%{fullpath}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) do is_expected.to match(%r{^(/|[A-Za-z]\:).+/spec/fixtures/test/manifests/fail\.pp$}) end end context 'to print %{line}' do let(:args) do [ '--log-format', '%{line}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('2') } end context 'to print %{kind}' do let(:args) do [ '--log-format', '%{kind}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('error') } end context 'to print %{KIND}' do let(:args) do [ '--log-format', '%{KIND}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('ERROR') } end context 'to print %{check}' do let(:args) do [ '--log-format', '%{check}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('autoloader_layout') } end context 'to print %{message}' do let(:args) do [ '--log-format', '%{message}', 'spec/fixtures/test/manifests/fail.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) { is_expected.to eq('test::foo not in autoload module layout') } end end context 'when displaying results as json' do let(:args) do [ '--json', 'spec/fixtures/test/manifests/warning.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) do if respond_to?(:include_json) is_expected.to include_json([[{ 'KIND' => 'WARNING' }]]) else is_expected.to match(%r{\[\n \{}) end end end context 'when displaying results for multiple targets as json' do let(:args) do [ '--json', 'spec/fixtures/test/manifests/fail.pp', 'spec/fixtures/test/manifests/warning.pp', ] end its(:exitstatus) { is_expected.to eq(1) } its(:stdout) do if respond_to?(:include_json) is_expected.to include_json([[{ 'KIND' => 'ERROR' }], [{ 'KIND' => 'WARNING' }]]) else is_expected.to match(%r{\[\n \{}) end end end context 'when hiding ignored problems' do let(:args) do [ 'spec/fixtures/test/manifests/ignore.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to_not match(%r{IGNORED}) } end context 'when showing ignored problems' do let(:args) do [ '--show-ignored', 'spec/fixtures/test/manifests/ignore.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to match(%r{IGNORED}) } end context 'when showing ignored problems with a reason' do let(:args) do [ '--show-ignored', 'spec/fixtures/test/manifests/ignore_reason.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) do is_expected.to eq( [ 'IGNORED: double quoted string containing no variables on line 3', ' for a good reason', ].join("\n") ) end end context 'ignoring multiple checks on a line' do let(:args) do [ 'spec/fixtures/test/manifests/ignore_multiple_line.pp', ] end its(:exitstatus) { is_expected.to eq(0) } end context 'ignoring multiple checks in a block' do let(:args) do [ 'spec/fixtures/test/manifests/ignore_multiple_block.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to match(%r{^.*line 6$}) } end context 'when an lint:endignore control comment exists with no opening lint:ignore comment' do let(:args) do [ 'spec/fixtures/test/manifests/mismatched_control_comment.pp', ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) { is_expected.to match(%r{WARNING: lint:endignore comment with no opening lint:ignore: comment found on line 1}) } end context 'when a lint:ignore control comment block is not terminated properly' do let(:args) do [ 'spec/fixtures/test/manifests/unterminated_control_comment.pp', ] end its(:stdout) { is_expected.to match(%r{WARNING: lint:ignore:140chars comment on line 2 with no closing lint:endignore comment}) } end context 'when fixing a file with \n line endings' do before(:context) do @windows_file = Tempfile.new('windows') @posix_file = Tempfile.new('posix') @windows_file.binmode @posix_file.binmode @windows_file.write("\r\n") @posix_file.write("\n") @windows_file.close @posix_file.close end after(:context) do @windows_file.unlink @posix_file.unlink end let(:args) do [ '--fix', @posix_file.path, @windows_file.path, ] end its(:exitstatus) { is_expected.to eq(0) } it 'does not change the line endings' do File.open(@posix_file.path, 'rb') do |f| data = f.read expect(data).to match(%r{\n\Z}m) expect(data).to_not match(%r{\r\n\Z}m) end File.open(@windows_file.path, 'rb') do |f| data = f.read expect(data).to match(%r{\r\n\Z}m) end end end context 'when overriding config file options with command line options' do context 'and config file sets "--only-checks=variable_contains_dash"' do around(:context) do |example| Dir.mktmpdir do |tmpdir| Dir.chdir(tmpdir) do File.open('.puppet-lint.rc', 'wb') do |f| f.puts('--only-checks=variable_contains_dash') end example.run end end end context 'and command-line does not override "--only-checks"' do let(:args) do File.join(File.dirname(__FILE__), '..', 'fixtures', 'test', 'manifests', 'two_warnings.pp') end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) do is_expected.to eq('WARNING: variable contains a dash on line 3') end end context 'and command-line sets "--only-checks=variable_is_lowercase"' do let(:args) do [ '--only-checks=variable_is_lowercase', File.join(File.dirname(__FILE__), '..', 'fixtures', 'test', 'manifests', 'two_warnings.pp'), ] end its(:exitstatus) { is_expected.to eq(0) } its(:stdout) do is_expected.to eq('WARNING: variable contains an uppercase letter on line 4') end end end end end puppet-lint-2.4.2/spec/puppet-lint/ignore_overrides_spec.rb0000644000004100000410000000744513611752231024162 0ustar www-datawww-datarequire 'spec_helper' describe 'quoted_booleans', :type => :lint do let(:msg) { 'quoted boolean value found' } context 'with a single line ignore' do let(:code) do <<-END 'true' 'true' # lint:ignore:quoted_booleans 'false' END end it 'should detect three problems' do expect(problems).to have(3).problems end it 'should have two warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) expect(problems).to contain_warning(msg).on_line(3).in_column(9) end it 'should have one ignored problem' do expect(problems).to contain_ignored(msg).on_line(2).in_column(9) end end context 'with a single line ignore and a reason' do let(:code) do <<-END 'true' 'true' # lint:ignore:quoted_booleans some good reason 'false' END end it 'should detect three problems' do expect(problems).to have(3).problems end it 'should have two warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) expect(problems).to contain_warning(msg).on_line(3).in_column(9) end it 'should have one ignored problem with a reason' do expect(problems).to contain_ignored(msg).on_line(2).in_column(9).with_reason('some good reason') end end context 'with a block ignore' do let(:code) do <<-END 'true' # lint:ignore:quoted_booleans 'false' 'true' # lint:endignore 'true' END end it 'should detect four problems' do expect(problems).to have(4).problems end it 'should have two warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) expect(problems).to contain_warning(msg).on_line(6).in_column(9) end it 'should have two ignored problems' do expect(problems).to contain_ignored(msg).on_line(3).in_column(9) expect(problems).to contain_ignored(msg).on_line(4).in_column(9) end end context 'with a block ignore and a reason' do let(:code) do <<-END 'true' # lint:ignore:quoted_booleans another reason 'false' 'true' # lint:endignore 'true' END end it 'should detect four problems' do expect(problems).to have(4).problems end it 'should have two warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) expect(problems).to contain_warning(msg).on_line(6).in_column(9) end it 'should have two ignored problems with a reason' do expect(problems).to contain_ignored(msg).on_line(3).in_column(9).with_reason('another reason') expect(problems).to contain_ignored(msg).on_line(4).in_column(9).with_reason('another reason') end end context 'disable multiple checks on a line with a reason' do let(:code) { '"true" # lint:ignore:quoted_booleans lint:ignore:double_quoted_string a reason' } it 'should detect 1 problems' do expect(problems).to have(1).problems end it 'should have one ignored problems' do expect(problems).to contain_ignored(msg).on_line(1).in_column(1).with_reason('a reason') end end context 'disable multiple checks in a block' do let(:code) do <<-END # lint:ignore:double_quoted_string lint:ignore:quoted_booleans lint:ignore:arrow_alignment foo { "bar": test => 'true', other_test => 'false', } # lint:endignore END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should ignore both problems' do expect(problems).to contain_ignored(msg).on_line(4).in_column(19).with_reason('') expect(problems).to contain_ignored(msg).on_line(5).in_column(25).with_reason('') end end end puppet-lint-2.4.2/spec/puppet-lint/checks_spec.rb0000644000004100000410000001715013611752231022047 0ustar www-datawww-datarequire 'spec_helper' describe PuppetLint::Checks do subject(:instance) { described_class.new } let(:path) { File.join('path', 'to', 'test.pp') } let(:content) { "notify { 'test': }" } describe '#initialize' do it { is_expected.to have_attributes(:problems => []) } end describe '#load_data' do let(:lexer) { PuppetLint::Lexer.new } before do allow(PuppetLint::Lexer).to receive(:new).and_return(lexer) end context 'when the tokeniser encounters an error' do before do allow(lexer).to receive(:tokenise).with(content).and_raise(lexer_error) instance.load_data(path, content) end context 'and the reason for the error is unknown' do let(:lexer_error) { PuppetLint::LexerError.new(1, 2) } it 'stores an empty tokens array' do expect(PuppetLint::Data.tokens).to be_empty end it 'creates a syntax error problem for the file' do expect(instance.problems).to have(1).problem expect(instance.problems.first).to include( :kind => :error, :check => :syntax, :message => 'Syntax error', :line => 1, :column => 2, :path => anything, :fullpath => anything, :filename => anything ) end end context 'and the reason for the error is known' do let(:lexer_error) { PuppetLint::LexerError.new(1, 2, 'some reason') } it 'stores an empty tokens array' do expect(PuppetLint::Data.tokens).to be_empty end it 'creates a syntax error problem for the file' do expect(instance.problems).to have(1).problem expect(instance.problems.first).to include( :kind => :error, :check => :syntax, :message => 'Syntax error (some reason)', :line => 1, :column => 2, :path => anything, :fullpath => anything, :filename => anything ) end end end end describe '#run' do let(:fileinfo) { File.join('path', 'to', 'test.pp') } let(:data) { "notify { 'test': }" } let(:enabled_checks) { [] } before do allow(instance).to receive(:enabled_checks).and_return(enabled_checks) end it 'loads the manifest data' do expect(instance).to receive(:load_data).with(fileinfo, data).and_call_original instance.run(fileinfo, data) end context 'when there are checks enabled' do let(:enabled_checks) { [:arrow_alignment, :hard_tabs] } let(:enabled_check_classes) { enabled_checks.map { |r| PuppetLint.configuration.check_object[r] } } let(:disabled_checks) { PuppetLint.configuration.checks - enabled_checks } let(:disabled_check_classes) { disabled_checks.map { |r| PuppetLint.configuration.check_object[r] } } it 'runs the enabled checks' do expect(enabled_check_classes).to all(receive(:new).and_call_original) instance.run(fileinfo, data) end it 'does not run the disabled checks' do # expect().to_not all(matcher) is not supported disabled_check_classes.each do |check_class| expect(check_class).to_not receive(:new) end instance.run(fileinfo, data) end context 'when a check finds a problem in the manifest' do let(:arrow_alignment_check) { PuppetLint.configuration.check_object[:arrow_alignment] } let(:hard_tabs_check) { PuppetLint.configuration.check_object[:hard_tabs] } let(:mock_arrow_alignment) do instance_double( PuppetLint::CheckPlugin, :run => [{ :kind => :error, :check => :arrow_alignment }], :fix_problems => [{ :kind => :fixed, :check => :arrow_alignment }] ) end let(:mock_hard_tabs) do instance_double(PuppetLint::CheckPlugin, :run => [], :fix_problems => []) end let(:fix_state) { false } before(:each) do allow(arrow_alignment_check).to receive(:new).and_return(mock_arrow_alignment) allow(hard_tabs_check).to receive(:new).and_return(mock_hard_tabs) allow(PuppetLint.configuration).to receive(:fix).and_return(fix_state) instance.run(fileinfo, data) end it 'adds the found problems to the problems array' do expect(instance).to have_attributes(:problems => [{ :kind => :error, :check => :arrow_alignment }]) end context 'and fix is enabled' do let(:fix_state) { true } it 'calls #fix_problems on the check and adds the results to the problems array' do expect(instance).to have_attributes(:problems => [{ :kind => :fixed, :check => :arrow_alignment }]) end end end end context 'when an unhandled exception is raised' do before do allow(instance).to receive(:load_data).with(fileinfo, data).and_raise(StandardError.new('test message')) allow($stdout).to receive(:puts).with(anything) end it 'prints out information about the puppet-lint version and ruby environment' do expected_info = [ "puppet-lint version: #{PuppetLint::VERSION}", "ruby version: #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}", "platform: #{RUBY_PLATFORM}", ] pattern = expected_info.map { |r| Regexp.escape(r) }.join('\s+') expect($stdout).to receive(:puts).with(a_string_matching(%r{#{pattern}}m)) expect { instance.run(fileinfo, data) }.to raise_error(SystemExit) { |error| expect(error.status).to eq(1) } end it 'prints out the details of the exception raised' do expect($stdout).to receive(:puts).with(a_string_matching(%r{error:\s+```\s+StandardError: test message.+```}m)) expect { instance.run(fileinfo, data) }.to raise_error(SystemExit) { |error| expect(error.status).to eq(1) } end context 'and the file being linted is readable' do before do allow(File).to receive(:readable?).with(fileinfo).and_return(true) allow(File).to receive(:read).with(fileinfo).and_return(data) end it 'adds the contents of the file to the bug report' do expect($stdout).to receive(:puts).with("file contents:\n```\n#{data}\n```") expect { instance.run(fileinfo, data) }.to raise_error(SystemExit) { |error| expect(error.status).to eq(1) } end end end end describe '#enabled_checks' do subject(:enabled_checks) { instance.enabled_checks } let(:expected_enabled_checks) { [:arrow_alignment, :trailing_whitespace] } before do PuppetLint.configuration.checks.each do |check| allow(PuppetLint.configuration).to receive("#{check}_enabled?").and_return(expected_enabled_checks.include?(check)) end end it 'checks the configuration for each check to see if it is enabled' do expect(enabled_checks.map(&:to_s).sort).to eq(expected_enabled_checks.map(&:to_s).sort) end end describe '#manifest' do subject(:manifest) { instance.manifest } let(:tokens) do [ instance_double(PuppetLint::Lexer::Token, :to_manifest => '1'), instance_double(PuppetLint::Lexer::Token, :to_manifest => '2'), instance_double(PuppetLint::Lexer::Token, :to_manifest => '3'), ] end before do allow(PuppetLint::Data).to receive(:tokens).and_return(tokens) end it 'reassembles the manifest from the tokens array' do expect(manifest).to eq('123') end end end puppet-lint-2.4.2/spec/puppet-lint/lexer/0000755000004100000410000000000013611752231020363 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/lexer/token_spec.rb0000644000004100000410000000103213611752231023036 0ustar www-datawww-datarequire 'spec_helper' describe PuppetLint::Lexer::Token do subject do PuppetLint::Lexer::Token.new(:NAME, 'foo', 1, 2) end it { is_expected.to respond_to(:type) } it { is_expected.to respond_to(:value) } it { is_expected.to respond_to(:line) } it { is_expected.to respond_to(:column) } its(:type) { is_expected.to eq(:NAME) } its(:value) { is_expected.to eq('foo') } its(:line) { is_expected.to eq(1) } its(:column) { is_expected.to eq(2) } its(:inspect) { is_expected.to eq('') } end puppet-lint-2.4.2/spec/puppet-lint/lexer/string_slurper_spec.rb0000644000004100000410000003232213611752231025006 0ustar www-datawww-datarequire 'spec_helper' describe PuppetLint::Lexer::StringSlurper do describe '#parse' do subject(:segments) { described_class.new(string).parse } context 'when parsing an unterminated string' do let(:string) { 'foo' } it 'raises an UnterminatedStringError' do expect { segments }.to raise_error(described_class::UnterminatedStringError) end end context 'when parsing up to a double quote' do let(:string) { 'foo"bar' } it 'returns a single segment up to the double quote' do expect(segments).to eq([[:STRING, 'foo']]) end context 'and the string is empty' do let(:string) { '"' } it 'returns a single empty string segment' do expect(segments).to eq([[:STRING, '']]) end end context 'and the string contains' do context 'a newline' do let(:string) { %(foo\nbar") } it 'includes the newline in the string segment' do expect(segments).to eq([[:STRING, "foo\nbar"]]) end end context 'an escaped $var' do let(:string) { '\$foo"' } it 'does not create an unenclosed variable segment' do expect(segments).to eq([[:STRING, '\$foo']]) end end context 'an escaped ${} enclosure' do let(:string) { '\"\${\"string\"}\""' } it 'does not create an interpolation segment' do expect(segments).to eq([[:STRING, '\"\${\"string\"}\"']]) end end context 'a variable and a suffix' do let(:string) { '${foo}bar"' } it 'puts the variable into an interpolation segment' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'foo'], [:STRING, 'bar'], ]) end end context 'a variable surrounded by text' do let(:string) { 'foo${bar}baz"' } it 'puts the variable into an interpolation segment' do expect(segments).to eq([ [:STRING, 'foo'], [:INTERP, 'bar'], [:STRING, 'baz'], ]) end end context 'multiple variables with surrounding text' do let(:string) { 'foo${bar}baz${gronk}meh"' } it 'puts each variable into an interpolation segment' do expect(segments).to eq([ [:STRING, 'foo'], [:INTERP, 'bar'], [:STRING, 'baz'], [:INTERP, 'gronk'], [:STRING, 'meh'], ]) end end context 'only an enclosed variable' do let(:string) { '${bar}"' } it 'puts empty string segments around the interpolated segment' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'bar'], [:STRING, ''], ]) end end context 'an enclosed variable with an unnecessary $' do let(:string) { '${$bar}"' } it 'does not remove the unnecessary $' do expect(segments).to eq([ [:STRING, ''], [:INTERP, '$bar'], [:STRING, ''], ]) end end context 'a variable with an array reference' do let(:string) { '${foo[bar][baz]}"' } it 'includes the references in the interpolated section' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'foo[bar][baz]'], [:STRING, ''], ]) end end context 'only enclosed variables' do let(:string) { '${foo}${bar}"' } it 'creates an interpolation section per variable' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'foo'], [:STRING, ''], [:INTERP, 'bar'], [:STRING, ''], ]) end end context 'an unenclosed variable' do let(:string) { '$foo"' } it 'creates a special segment for the unenclosed variable' do expect(segments).to eq([ [:STRING, ''], [:UNENC_VAR, '$foo'], [:STRING, ''], ]) end end context 'an interpolation with a nested single quoted string' do let(:string) { %(string with ${'a nested single quoted string'} inside it") } it 'creates an interpolation segment for the nested string' do expect(segments).to eq([ [:STRING, 'string with '], [:INTERP, "'a nested single quoted string'"], [:STRING, ' inside it'], ]) end end context 'an interpolation with nested math' do let(:string) { 'string with ${(3+5)/4} nested math"' } it 'creates an interpolation segment for the nested math' do expect(segments).to eq([ [:STRING, 'string with '], [:INTERP, '(3+5)/4'], [:STRING, ' nested math'], ]) end end context 'an interpolation with a nested array' do let(:string) { %(string with ${['an array ', $v2]} in it") } it 'creates an interpolation segment for the nested array' do expect(segments).to eq([ [:STRING, 'string with '], [:INTERP, "['an array ', $v2]"], [:STRING, ' in it'], ]) end end context 'repeated $s' do let(:string) { '$$$$"' } it 'creates a single string segment' do expect(segments).to eq([[:STRING, '$$$$']]) end end context 'multiple unenclosed variables' do let(:string) { '$foo$bar"' } it 'creates a special segment for each unenclosed variable' do expect(segments).to eq([ [:STRING, ''], [:UNENC_VAR, '$foo'], [:STRING, ''], [:UNENC_VAR, '$bar'], [:STRING, ''], ]) end end context 'an unenclosed variable with a trailing $' do let(:string) { 'foo$bar$"' } it 'places the trailing $ in a string segment' do expect(segments).to eq([ [:STRING, 'foo'], [:UNENC_VAR, '$bar'], [:STRING, '$'], ]) end end context 'an unenclosed variable starting with two $s' do let(:string) { 'foo$$bar"' } it 'includes the preceeding $ in the string segment before the unenclosed variable' do expect(segments).to eq([ [:STRING, 'foo$'], [:UNENC_VAR, '$bar'], [:STRING, ''], ]) end end context 'an unenclosed variable with incorrect namespacing' do let(:string) { '$foo::::bar"' } it 'only includes the valid part of the variable name in the segment' do expect(segments).to eq([ [:STRING, ''], [:UNENC_VAR, '$foo'], [:STRING, '::::bar'], ]) end end context 'a variable followed by an odd number of backslashes before a double quote' do let(:string) { '${foo}\"bar"' } it 'does not let this double quote terminate the string' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'foo'], [:STRING, '\\"bar'], ]) end end context 'a variable followed by an even number of backslashes before a double quote' do let(:string) { '${foo}\\\\"bar"' } it 'recognizes this double quote as the terminator' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'foo'], [:STRING, '\\\\'], ]) end end context 'an interpolation with a complex function chain' do let(:string) { '${key} ${flatten([$value]).join("\nkey ")}"' } it 'keeps the whole function chain in a single interpolation segment' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'key'], [:STRING, ' '], [:INTERP, 'flatten([$value]).join("\nkey ")'], [:STRING, ''], ]) end end context 'nested interpolations' do let(:string) { '${facts["network_${iface}"]}/${facts["netmask_${iface}"]}"' } it 'keeps each full interpolation in its own segment' do expect(segments).to eq([ [:STRING, ''], [:INTERP, 'facts["network_${iface}"]'], [:STRING, '/'], [:INTERP, 'facts["netmask_${iface}"]'], [:STRING, ''], ]) end end context 'interpolation with nested braces' do let(:string) { '${$foo.map |$bar| { something($bar) }}"' } it do expect(segments).to eq([ [:STRING, ''], [:INTERP, '$foo.map |$bar| { something($bar) }'], [:STRING, ''], ]) end end end end end describe '#parse_heredoc' do subject(:segments) { described_class.new(heredoc).parse_heredoc(heredoc_tag) } context 'when parsing a heredoc with interpolation disabled' do context 'that is a plain heredoc' do let(:heredoc) { %( SOMETHING\n ELSE\n :\n |-myheredoc) } let(:heredoc_tag) { 'myheredoc' } it 'splits the heredoc into two segments' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n ELSE\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains a value enclosed in ${}' do let(:heredoc) { %( SOMETHING\n ${else}\n :\n |-myheredoc) } let(:heredoc_tag) { 'myheredoc' } it 'does not create an interpolation segment' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n ${else}\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains an unenclosed variable' do let(:heredoc) { %( SOMETHING\n $else\n :\n |-myheredoc) } let(:heredoc_tag) { 'myheredoc' } it 'does not create a segment for the unenclosed variable' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n $else\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end end context 'when parsing a heredoc with interpolation enabled' do context 'that is a plain heredoc' do let(:heredoc) { %( SOMETHING\n ELSE\n :\n |-myheredoc) } let(:heredoc_tag) { '"myheredoc"' } it 'splits the heredoc into two segments' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n ELSE\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains a value enclosed in ${}' do let(:heredoc) { %( SOMETHING\n ${else}\n :\n |-myheredoc) } let(:heredoc_tag) { '"myheredoc"' } it 'creates an interpolation segment' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n "], [:INTERP, 'else'], [:HEREDOC, "\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains an unenclosed variable' do let(:heredoc) { %( SOMETHING\n $else\n :\n |-myheredoc) } let(:heredoc_tag) { '"myheredoc"' } it 'does not create a segment for the unenclosed variable' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n "], [:UNENC_VAR, '$else'], [:HEREDOC, "\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains a nested interpolation' do let(:heredoc) { %( SOMETHING\n ${facts["other_${thing}"]}\n :\n |-myheredoc) } let(:heredoc_tag) { '"myheredoc"' } it 'does not create a segment for the unenclosed variable' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n "], [:INTERP, 'facts["other_${thing}"]'], [:HEREDOC, "\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains an interpolation with nested braces' do let(:heredoc) { %( SOMETHING\n ${$foo.map |$bar| { something($bar) }}\n :\n |-myheredoc) } let(:heredoc_tag) { '"myheredoc"' } it 'does not create a segment for the unenclosed variable' do expect(segments).to eq([ [:HEREDOC, " SOMETHING\n "], [:INTERP, '$foo.map |$bar| { something($bar) }'], [:HEREDOC, "\n :\n "], [:HEREDOC_TERM, '|-myheredoc'], ]) end end context 'that contains braces' do let(:heredoc) { %( {\n "foo": "bar"\n }\n |-end) } let(:heredoc_tag) { '"end":json/' } it do expect(segments).to eq([ [:HEREDOC, %( {\n "foo": "bar"\n }\n )], [:HEREDOC_TERM, '|-end'], ]) end end end end end puppet-lint-2.4.2/spec/puppet-lint/lexer_spec.rb0000644000004100000410000017761313611752231021741 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' describe PuppetLint::Lexer do # rubocop:disable Metrics/BlockLength before do @lexer = PuppetLint::Lexer.new end context 'invalid code' do it 'should bork' do expect { @lexer.tokenise('^') }.to raise_error(PuppetLint::LexerError) end end context '#new_token' do it 'should calculate the line number for an empty string' do token = @lexer.new_token(:TEST, 'test') expect(token.line).to eq(1) end it 'should get correct line number after double quoted multi line string' do @lexer.new_token(:STRING, "test\ntest") token = @lexer.new_token(:TEST, 'test') expect(token.line).to eq(2) end it 'should get correct line number after a multi line comment' do @lexer.new_token(:MLCOMMENT, "test\ntest", :raw => "/*test\ntest*/") token = @lexer.new_token(:TEST, 'test') expect(token.line).to eq(2) end it 'should calculate the line number for a multi line string' do @lexer.new_token(:SSTRING, "test\ntest") token = @lexer.new_token(:TEST, 'test') expect(token.line).to eq(2) end it 'should calculate line number for string that ends with newline' do @lexer.new_token(:SSTRING, "test\n") token = @lexer.new_token(:TEST, 'test') expect(token.line).to eq(2) end it 'should calculate the column number for an empty string' do token = @lexer.new_token(:TEST, 'test') expect(token.column).to eq(1) end it 'should calculate the column number for a single line string' do @lexer.new_token(:SSTRING, 'this is a test') token = @lexer.new_token(:TEST, 'test') expect(token.column).to eq(17) end it 'should calculate the column number for a multi line string' do @lexer.instance_variable_set('@line_no', 4) @lexer.instance_variable_set('@column', 5) @lexer.new_token(:SSTRING, "test\ntest") token = @lexer.new_token(:TEST, 'test') expect(token.column).to eq(6) end end context '#process_string_segments' do subject(:tokens) { @lexer.tokens } subject(:manifest) { @lexer.tokens.map(&:to_manifest).join } before(:each) do @lexer.process_string_segments(segments) end context 'an empty string segment' do let(:segments) do [ [:STRING, ''], ] end it 'creates a :STRING token' do expect(tokens).to have(1).token expect(tokens[0]).to have_attributes( :type => :STRING, :value => '', :line => 1, :column => 1 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('""') end end context 'an interpolated variable with a suffix' do let(:segments) do [ [:STRING, ''], [:INTERP, 'foo'], [:STRING, 'bar'], ] end it 'creates a tokenised string with an interpolated variable' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'foo', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => 'bar', :line => 1, :column => 7 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${foo}bar"') end end context 'an interpolated variable surrounded by string segments' do let(:segments) do [ [:STRING, 'foo'], [:INTERP, 'bar'], [:STRING, 'baz'], ] end it 'creates a tokenised string with an interpolated variable' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => 'foo', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'bar', :line => 1, :column => 7 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => 'baz', :line => 1, :column => 10 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"foo${bar}baz"') end end context 'multiple interpolated variables with surrounding text' do let(:segments) do [ [:STRING, 'foo'], [:INTERP, 'bar'], [:STRING, 'baz'], [:INTERP, 'gronk'], [:STRING, 'meh'], ] end it 'creates a tokenised string with the interpolated variables' do expect(tokens).to have(5).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => 'foo', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'bar', :line => 1, :column => 7 ) expect(tokens[2]).to have_attributes( :type => :DQMID, :value => 'baz', :line => 1, :column => 10 ) expect(tokens[3]).to have_attributes( :type => :VARIABLE, :value => 'gronk', :line => 1, :column => 16 ) expect(tokens[4]).to have_attributes( :type => :DQPOST, :value => 'meh', :line => 1, :column => 21 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"foo${bar}baz${gronk}meh"') end end context 'only a single interpolated variable' do let(:segments) do [ [:STRING, ''], [:INTERP, 'foo'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'foo', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 7 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${foo}"') end end context 'treats a variable named the same as the keyword as a variable' do PuppetLint::Lexer::KEYWORDS.keys.each do |keyword| context "for '#{keyword}'" do let(:segments) do [ [:STRING, ''], [:INTERP, keyword], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => keyword, :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => keyword.size + 4 ) end it 'can render the result back into a manifest' do expect(manifest).to eq("\"${#{keyword}}\"") end end end end context 'an interpolated variable with an unnecessary $' do let(:segments) do [ [:STRING, ''], [:INTERP, '$bar'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'bar', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 8 ) end it 'includes the extra $ in the rendered manifest' do expect(manifest).to eq('"${$bar}"') end end context 'an interpolated variable with an array reference' do let(:segments) do [ [:STRING, ''], [:INTERP, 'foo[bar][baz]'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(9).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'foo', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :LBRACK, :value => '[', :line => 1, :column => 7 ) expect(tokens[3]).to have_attributes( :type => :NAME, :value => 'bar', :line => 1, :column => 8 ) expect(tokens[4]).to have_attributes( :type => :RBRACK, :value => ']', :line => 1, :column => 11 ) expect(tokens[5]).to have_attributes( :type => :LBRACK, :value => '[', :line => 1, :column => 12 ) expect(tokens[6]).to have_attributes( :type => :NAME, :value => 'baz', :line => 1, :column => 13 ) expect(tokens[7]).to have_attributes( :type => :RBRACK, :value => ']', :line => 1, :column => 16 ) expect(tokens[8]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 17 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${foo[bar][baz]}"') end end context 'multiple interpreted variables' do let(:segments) do [ [:STRING, ''], [:INTERP, 'foo'], [:STRING, ''], [:INTERP, 'bar'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(5).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'foo', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DQMID, :value => '', :line => 1, :column => 7 ) expect(tokens[3]).to have_attributes( :type => :VARIABLE, :value => 'bar', :line => 1, :column => 10 ) expect(tokens[4]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 13 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${foo}${bar}"') end end context 'an unenclosed variable' do let(:segments) do [ [:STRING, ''], [:UNENC_VAR, '$foo'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :UNENC_VARIABLE, :value => 'foo', :line => 1, :column => 2 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 6 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"$foo"') end end context 'an interpolation with a nested single quote string' do let(:segments) do [ [:STRING, 'string with '], [:INTERP, "'a nested single quoted string'"], [:STRING, ' inside it'], ] end it 'creates a tokenised string' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => 'string with ', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :SSTRING, :value => 'a nested single quoted string', :line => 1, :column => 16 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => ' inside it', :line => 1, :column => 47 ) end it 'can render the result back into a manifest' do expect(manifest).to eq(%("string with ${'a nested single quoted string'} inside it")) end end context 'an interpolation with a nested math expression' do let(:segments) do [ [:STRING, 'string with '], [:INTERP, '(3+5)/4'], [:STRING, ' nested math'], ] end it 'creates a tokenised string' do expect(tokens).to have(9).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => 'string with ', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :LPAREN, :value => '(', :line => 1, :column => 16 ) expect(tokens[2]).to have_attributes( :type => :NUMBER, :value => '3', :line => 1, :column => 17 ) expect(tokens[3]).to have_attributes( :type => :PLUS, :value => '+', :line => 1, :column => 18 ) expect(tokens[4]).to have_attributes( :type => :NUMBER, :value => '5', :line => 1, :column => 19 ) expect(tokens[5]).to have_attributes( :type => :RPAREN, :value => ')', :line => 1, :column => 20 ) expect(tokens[6]).to have_attributes( :type => :DIV, :value => '/', :line => 1, :column => 21 ) expect(tokens[7]).to have_attributes( :type => :NUMBER, :value => '4', :line => 1, :column => 22 ) expect(tokens[8]).to have_attributes( :type => :DQPOST, :value => ' nested math', :line => 1, :column => 23 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"string with ${(3+5)/4} nested math"') end end context 'an interpolation with a nested array' do let(:segments) do [ [:STRING, 'string with '], [:INTERP, "['an array ', $v2]"], [:STRING, ' in it'], ] end it 'creates a tokenised string' do expect(tokens).to have(8).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => 'string with ', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :LBRACK, :value => '[', :line => 1, :column => 16 ) expect(tokens[2]).to have_attributes( :type => :SSTRING, :value => 'an array ', :line => 1, :column => 17 ) expect(tokens[3]).to have_attributes( :type => :COMMA, :value => ',', :line => 1, :column => 28 ) expect(tokens[4]).to have_attributes( :type => :WHITESPACE, :value => ' ', :line => 1, :column => 29 ) expect(tokens[5]).to have_attributes( :type => :VARIABLE, :value => 'v2', :line => 1, :column => 30 ) expect(tokens[6]).to have_attributes( :type => :RBRACK, :value => ']', :line => 1, :column => 33 ) expect(tokens[7]).to have_attributes( :type => :DQPOST, :value => ' in it', :line => 1, :column => 34 ) end it 'can render the result back into a manifest' do expect(manifest).to eq(%("string with ${['an array ', $v2]} in it")) end end context 'multiple unenclosed variables' do let(:segments) do [ [:STRING, ''], [:UNENC_VAR, '$foo'], [:STRING, ''], [:UNENC_VAR, '$bar'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(5).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :UNENC_VARIABLE, :value => 'foo', :line => 1, :column => 2 ) expect(tokens[2]).to have_attributes( :type => :DQMID, :value => '', :line => 1, :column => 6 ) expect(tokens[3]).to have_attributes( :type => :UNENC_VARIABLE, :value => 'bar', :line => 1, :column => 6 ) expect(tokens[4]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 10 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"$foo$bar"') end end context 'an unenclosed variable with a trailing $' do let(:segments) do [ [:STRING, 'foo'], [:UNENC_VAR, '$bar'], [:STRING, '$'], ] end it 'creates a tokenised string' do expect(tokens).to have(3).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => 'foo', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :UNENC_VARIABLE, :value => 'bar', :line => 1, :column => 5 ) expect(tokens[2]).to have_attributes( :type => :DQPOST, :value => '$', :line => 1, :column => 9 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"foo$bar$"') end end context 'an interpolation with a complex function chain' do let(:segments) do [ [:STRING, ''], [:INTERP, 'key'], [:STRING, ' '], [:INTERP, 'flatten([$value]).join("\nkey ")'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(15).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'key', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DQMID, :value => ' ', :line => 1, :column => 7 ) expect(tokens[3]).to have_attributes( :type => :FUNCTION_NAME, :value => 'flatten', :line => 1, :column => 11 ) expect(tokens[4]).to have_attributes( :type => :LPAREN, :value => '(', :line => 1, :column => 18 ) expect(tokens[5]).to have_attributes( :type => :LBRACK, :value => '[', :line => 1, :column => 19 ) expect(tokens[6]).to have_attributes( :type => :VARIABLE, :value => 'value', :line => 1, :column => 20 ) expect(tokens[7]).to have_attributes( :type => :RBRACK, :value => ']', :line => 1, :column => 26 ) expect(tokens[8]).to have_attributes( :type => :RPAREN, :value => ')', :line => 1, :column => 27 ) expect(tokens[9]).to have_attributes( :type => :DOT, :value => '.', :line => 1, :column => 28 ) expect(tokens[10]).to have_attributes( :type => :FUNCTION_NAME, :value => 'join', :line => 1, :column => 29 ) expect(tokens[11]).to have_attributes( :type => :LPAREN, :value => '(', :line => 1, :column => 33 ) expect(tokens[12]).to have_attributes( :type => :STRING, :value => '\nkey ', :line => 1, :column => 34 ) expect(tokens[13]).to have_attributes( :type => :RPAREN, :value => ')', :line => 1, :column => 42 ) expect(tokens[14]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 43 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${key} ${flatten([$value]).join("\nkey ")}"') end end context 'nested interpolations' do let(:segments) do [ [:STRING, ''], [:INTERP, 'facts["network_${iface}"]'], [:STRING, '/'], [:INTERP, 'facts["netmask_${iface}"]'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(15).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'facts', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :LBRACK, :value => '[', :line => 1, :column => 9 ) expect(tokens[3]).to have_attributes( :type => :DQPRE, :value => 'network_', :line => 1, :column => 10 ) expect(tokens[4]).to have_attributes( :type => :VARIABLE, :value => 'iface', :line => 1, :column => 21 ) expect(tokens[5]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 26 ) expect(tokens[6]).to have_attributes( :type => :RBRACK, :value => ']', :line => 1, :column => 28 ) expect(tokens[7]).to have_attributes( :type => :DQMID, :value => '/', :line => 1, :column => 29 ) expect(tokens[8]).to have_attributes( :type => :VARIABLE, :value => 'facts', :line => 1, :column => 33 ) expect(tokens[9]).to have_attributes( :type => :LBRACK, :value => '[', :line => 1, :column => 38 ) expect(tokens[10]).to have_attributes( :type => :DQPRE, :value => 'netmask_', :line => 1, :column => 39 ) expect(tokens[11]).to have_attributes( :type => :VARIABLE, :value => 'iface', :line => 1, :column => 50 ) expect(tokens[12]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 55 ) expect(tokens[13]).to have_attributes( :type => :RBRACK, :value => ']', :line => 1, :column => 57 ) expect(tokens[14]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 58 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${facts["network_${iface}"]}/${facts["netmask_${iface}"]}"') end end context 'interpolation with nested braces' do let(:segments) do [ [:STRING, ''], [:INTERP, '$foo.map |$bar| { something($bar) }'], [:STRING, ''], ] end it 'creates a tokenised string' do expect(tokens).to have(18).tokens expect(tokens[0]).to have_attributes( :type => :DQPRE, :value => '', :line => 1, :column => 1 ) expect(tokens[1]).to have_attributes( :type => :VARIABLE, :value => 'foo', :line => 1, :column => 4 ) expect(tokens[2]).to have_attributes( :type => :DOT, :value => '.', :line => 1, :column => 8 ) expect(tokens[3]).to have_attributes( :type => :NAME, :value => 'map', :line => 1, :column => 9 ) expect(tokens[4]).to have_attributes( :type => :WHITESPACE, :value => ' ', :line => 1, :column => 12 ) expect(tokens[5]).to have_attributes( :type => :PIPE, :value => '|', :line => 1, :column => 13 ) expect(tokens[6]).to have_attributes( :type => :VARIABLE, :value => 'bar', :line => 1, :column => 14 ) expect(tokens[7]).to have_attributes( :type => :PIPE, :value => '|', :line => 1, :column => 18 ) expect(tokens[8]).to have_attributes( :type => :WHITESPACE, :value => ' ', :line => 1, :column => 19 ) expect(tokens[9]).to have_attributes( :type => :LBRACE, :value => '{', :line => 1, :column => 20 ) expect(tokens[10]).to have_attributes( :type => :WHITESPACE, :value => ' ', :line => 1, :column => 21 ) expect(tokens[11]).to have_attributes( :type => :FUNCTION_NAME, :value => 'something', :line => 1, :column => 22 ) expect(tokens[12]).to have_attributes( :type => :LPAREN, :value => '(', :line => 1, :column => 31 ) expect(tokens[13]).to have_attributes( :type => :VARIABLE, :value => 'bar', :line => 1, :column => 32 ) expect(tokens[14]).to have_attributes( :type => :RPAREN, :value => ')', :line => 1, :column => 36 ) expect(tokens[15]).to have_attributes( :type => :WHITESPACE, :value => ' ', :line => 1, :column => 37 ) expect(tokens[16]).to have_attributes( :type => :RBRACE, :value => '}', :line => 1, :column => 38 ) expect(tokens[17]).to have_attributes( :type => :DQPOST, :value => '', :line => 1, :column => 39 ) end it 'can render the result back into a manifest' do expect(manifest).to eq('"${$foo.map |$bar| { something($bar) }}"') end end end context ':STRING / :DQ' do it 'should handle a string with newline characters' do # rubocop:disable Layout/TrailingWhitespace manifest = < "echo > /home/bar/.token; kdestroy; kinit ${pseudouser}@EXAMPLE.COM -kt ${keytab_path}; test $(klist | egrep '^Default principal:' | sed 's/Default principal:\\s//') = '${pseudouser}'@EXAMPLE.COM", refreshonly => true; } END # rubocop:enable Layout/TrailingWhitespace tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(34) expect(tokens[0].type).to eq(:WHITESPACE) expect(tokens[0].value).to eq(' ') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:NAME) expect(tokens[1].value).to eq('exec') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(3) expect(tokens[2].type).to eq(:WHITESPACE) expect(tokens[2].value).to eq(' ') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(7) expect(tokens[3].type).to eq(:LBRACE) expect(tokens[3].value).to eq('{') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(8) expect(tokens[4].type).to eq(:NEWLINE) expect(tokens[4].value).to eq("\n") expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(9) expect(tokens[5].type).to eq(:INDENT) expect(tokens[5].value).to eq(' ') expect(tokens[5].line).to eq(2) expect(tokens[5].column).to eq(1) expect(tokens[6].type).to eq(:SSTRING) expect(tokens[6].value).to eq('do-something') expect(tokens[6].line).to eq(2) expect(tokens[6].column).to eq(5) expect(tokens[7].type).to eq(:COLON) expect(tokens[7].value).to eq(':') expect(tokens[7].line).to eq(2) expect(tokens[7].column).to eq(19) expect(tokens[8].type).to eq(:NEWLINE) expect(tokens[8].value).to eq("\n") expect(tokens[8].line).to eq(2) expect(tokens[8].column).to eq(20) expect(tokens[9].type).to eq(:INDENT) expect(tokens[9].value).to eq(' ') expect(tokens[9].line).to eq(3) expect(tokens[9].column).to eq(1) expect(tokens[10].type).to eq(:NAME) expect(tokens[10].value).to eq('command') expect(tokens[10].line).to eq(3) expect(tokens[10].column).to eq(7) expect(tokens[11].type).to eq(:WHITESPACE) expect(tokens[11].value).to eq(' ') expect(tokens[11].line).to eq(3) expect(tokens[11].column).to eq(14) expect(tokens[12].type).to eq(:FARROW) expect(tokens[12].value).to eq('=>') expect(tokens[12].line).to eq(3) expect(tokens[12].column).to eq(19) expect(tokens[13].type).to eq(:WHITESPACE) expect(tokens[13].value).to eq(' ') expect(tokens[13].line).to eq(3) expect(tokens[13].column).to eq(21) expect(tokens[14].type).to eq(:DQPRE) expect(tokens[14].value).to eq("echo > /home/bar/.token; \n kdestroy; \n kinit ") expect(tokens[14].line).to eq(3) expect(tokens[14].column).to eq(22) expect(tokens[15].type).to eq(:VARIABLE) expect(tokens[15].value).to eq('pseudouser') expect(tokens[15].line).to eq(5) expect(tokens[15].column).to eq(41) expect(tokens[16].type).to eq(:DQMID) expect(tokens[16].value).to eq('@EXAMPLE.COM -kt ') expect(tokens[16].line).to eq(5) expect(tokens[16].column).to eq(51) expect(tokens[17].type).to eq(:VARIABLE) expect(tokens[17].value).to eq('keytab_path') expect(tokens[17].line).to eq(5) expect(tokens[17].column).to eq(71) expect(tokens[18].type).to eq(:DQMID) expect(tokens[18].value).to eq("; \n test $(klist | egrep '^Default principal:' | sed 's/Default principal:\\s//') = '") expect(tokens[18].line).to eq(5) expect(tokens[18].column).to eq(82) expect(tokens[19].type).to eq(:VARIABLE) expect(tokens[19].value).to eq('pseudouser') expect(tokens[19].line).to eq(6) expect(tokens[19].column).to eq(115) expect(tokens[20].type).to eq(:DQPOST) expect(tokens[20].value).to eq("'@EXAMPLE.COM") expect(tokens[20].line).to eq(6) expect(tokens[20].column).to eq(125) expect(tokens[21].type).to eq(:COMMA) expect(tokens[21].value).to eq(',') expect(tokens[21].line).to eq(6) expect(tokens[21].column).to eq(140) expect(tokens[22].type).to eq(:NEWLINE) expect(tokens[22].value).to eq("\n") expect(tokens[22].line).to eq(6) expect(tokens[22].column).to eq(141) expect(tokens[23].type).to eq(:INDENT) expect(tokens[23].value).to eq(' ') expect(tokens[23].line).to eq(7) expect(tokens[23].column).to eq(1) expect(tokens[24].type).to eq(:NAME) expect(tokens[24].value).to eq('refreshonly') expect(tokens[24].line).to eq(7) expect(tokens[24].column).to eq(7) expect(tokens[25].type).to eq(:WHITESPACE) expect(tokens[25].value).to eq(' ') expect(tokens[25].line).to eq(7) expect(tokens[25].column).to eq(18) expect(tokens[26].type).to eq(:FARROW) expect(tokens[26].value).to eq('=>') expect(tokens[26].line).to eq(7) expect(tokens[26].column).to eq(19) expect(tokens[27].type).to eq(:WHITESPACE) expect(tokens[27].value).to eq(' ') expect(tokens[27].line).to eq(7) expect(tokens[27].column).to eq(21) expect(tokens[28].type).to eq(:TRUE) expect(tokens[28].value).to eq('true') expect(tokens[28].line).to eq(7) expect(tokens[28].column).to eq(22) expect(tokens[29].type).to eq(:SEMIC) expect(tokens[29].value).to eq(';') expect(tokens[29].line).to eq(7) expect(tokens[29].column).to eq(26) expect(tokens[30].type).to eq(:NEWLINE) expect(tokens[30].value).to eq("\n") expect(tokens[30].line).to eq(7) expect(tokens[30].column).to eq(27) expect(tokens[31].type).to eq(:INDENT) expect(tokens[31].value).to eq(' ') expect(tokens[31].line).to eq(8) expect(tokens[31].column).to eq(1) expect(tokens[32].type).to eq(:RBRACE) expect(tokens[32].value).to eq('}') expect(tokens[32].line).to eq(8) expect(tokens[32].column).to eq(3) expect(tokens[33].type).to eq(:NEWLINE) expect(tokens[33].value).to eq("\n") expect(tokens[33].line).to eq(8) expect(tokens[33].column).to eq(4) end it 'should calculate the column number correctly after an enclosed variable' do token = @lexer.tokenise(' "${foo}" =>').last expect(token.type).to eq(:FARROW) expect(token.column).to eq(12) end it 'should calculate the column number correctly after an enclosed variable starting with a string' do token = @lexer.tokenise(' "bar${foo}" =>').last expect(token.type).to eq(:FARROW) expect(token.column).to eq(15) end it 'should calculate the column number correctly after an enclosed variable ending with a string' do token = @lexer.tokenise(' "${foo}bar" =>').last expect(token.type).to eq(:FARROW) expect(token.column).to eq(15) end it 'should calculate the column number correctly after an enclosed variable surround by a string' do token = @lexer.tokenise(' "foo${bar}baz" =>').last expect(token.type).to eq(:FARROW) expect(token.column).to eq(18) end it 'should not enclose variable with a chained function call' do manifest = '"This is ${a.test}"' tokens = @lexer.tokenise(manifest) expect(tokens.map(&:to_manifest).join('')).to eq(manifest) end end %w[ case class default define import if elsif else inherits node and or undef true false in unless ].each do |keyword| it "should handle '#{keyword}' as a keyword" do token = @lexer.tokenise(keyword).first expect(token.type).to eq(keyword.upcase.to_sym) expect(token.value).to eq(keyword) end end [ [:LBRACK, '['], [:RBRACK, ']'], [:LBRACE, '{'], [:RBRACE, '}'], [:LPAREN, '('], [:RPAREN, ')'], [:EQUALS, '='], [:ISEQUAL, '=='], [:GREATEREQUAL, '>='], [:GREATERTHAN, '>'], [:LESSTHAN, '<'], [:LESSEQUAL, '<='], [:NOTEQUAL, '!='], [:NOT, '!'], [:COMMA, ','], [:DOT, '.'], [:COLON, ':'], [:AT, '@'], [:LLCOLLECT, '<<|'], [:RRCOLLECT, '|>>'], [:LCOLLECT, '<|'], [:RCOLLECT, '|>'], [:SEMIC, ';'], [:QMARK, '?'], [:BACKSLASH, '\\'], [:FARROW, '=>'], [:PARROW, '+>'], [:APPENDS, '+='], [:PLUS, '+'], [:MINUS, '-'], [:DIV, '/'], [:TIMES, '*'], [:MODULO, '%'], [:PIPE, '|'], [:LSHIFT, '<<'], [:RSHIFT, '>>'], [:MATCH, '=~'], [:NOMATCH, '!~'], [:IN_EDGE, '->'], [:OUT_EDGE, '<-'], [:IN_EDGE_SUB, '~>'], [:OUT_EDGE_SUB, '<~'], [:NEWLINE, "\r"], [:NEWLINE, "\n"], [:NEWLINE, "\r\n"], ].each do |name, string| it "should have a token named '#{name}'" do token = @lexer.tokenise(string).first expect(token.type).to eq(name) expect(token.value).to eq(string) end end context ':TYPE' do it 'should match Data Types' do token = @lexer.tokenise('Integer').first expect(token.type).to eq(:TYPE) expect(token.value).to eq('Integer') end it 'should match Catalog Types' do token = @lexer.tokenise('Resource').first expect(token.type).to eq(:TYPE) expect(token.value).to eq('Resource') end it 'should match Abstract Types' do token = @lexer.tokenise('Collection').first expect(token.type).to eq(:TYPE) expect(token.value).to eq('Collection') end describe 'Platform Types' do it 'should match Callable' do token = @lexer.tokenise('Callable').first expect(token.type).to eq(:TYPE) expect(token.value).to eq('Callable') end it 'should match Sensitive' do token = @lexer.tokenise('Sensitive').first expect(token.type).to eq(:TYPE) expect(token.value).to eq('Sensitive') end end end context ':HEREDOC without interpolation' do it 'should parse a simple heredoc' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @(myheredoc) SOMETHING ELSE : |-myheredoc END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(8) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:WHITESPACE) expect(tokens[1].value).to eq(' ') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(5) expect(tokens[2].type).to eq(:EQUALS) expect(tokens[2].value).to eq('=') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(6) expect(tokens[3].type).to eq(:WHITESPACE) expect(tokens[3].value).to eq(' ') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(7) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('myheredoc') expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(8) expect(tokens[5].type).to eq(:NEWLINE) expect(tokens[5].value).to eq("\n") expect(tokens[5].line).to eq(1) expect(tokens[5].column).to eq(20) expect(tokens[6].type).to eq(:HEREDOC) expect(tokens[6].value).to eq(" SOMETHING\n ELSE\n :\n ") expect(tokens[6].raw).to eq(" SOMETHING\n ELSE\n :\n |-myheredoc") expect(tokens[6].line).to eq(2) expect(tokens[6].column).to eq(1) expect(tokens[7].type).to eq(:NEWLINE) expect(tokens[7].line).to eq(5) expect(tokens[7].column).to eq(14) end it 'should not interpolate the contents of the heredoc' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @(myheredoc) SOMETHING ${else} : |-myheredoc END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(8) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:WHITESPACE) expect(tokens[1].value).to eq(' ') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(5) expect(tokens[2].type).to eq(:EQUALS) expect(tokens[2].value).to eq('=') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(6) expect(tokens[3].type).to eq(:WHITESPACE) expect(tokens[3].value).to eq(' ') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(7) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('myheredoc') expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(8) expect(tokens[5].type).to eq(:NEWLINE) expect(tokens[5].value).to eq("\n") expect(tokens[5].line).to eq(1) expect(tokens[5].column).to eq(20) expect(tokens[6].type).to eq(:HEREDOC) expect(tokens[6].value).to eq(" SOMETHING\n ${else}\n :\n ") expect(tokens[6].raw).to eq(" SOMETHING\n ${else}\n :\n |-myheredoc") expect(tokens[6].line).to eq(2) expect(tokens[6].column).to eq(1) expect(tokens[7].type).to eq(:NEWLINE) expect(tokens[7].value).to eq("\n") expect(tokens[7].line).to eq(5) expect(tokens[7].column).to eq(14) end it 'should handle multiple heredoc declarations on a single line' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = "${@(end1)} ${@(end2)}" foo |-end1 bar |-end2 END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(14) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:WHITESPACE) expect(tokens[1].value).to eq(' ') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(5) expect(tokens[2].type).to eq(:EQUALS) expect(tokens[2].value).to eq('=') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(6) expect(tokens[3].type).to eq(:WHITESPACE) expect(tokens[3].value).to eq(' ') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(7) expect(tokens[4].type).to eq(:DQPRE) expect(tokens[4].value).to eq('') expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(8) expect(tokens[5].type).to eq(:HEREDOC_OPEN) expect(tokens[5].value).to eq('end1') expect(tokens[5].line).to eq(1) expect(tokens[5].column).to eq(11) expect(tokens[6].type).to eq(:DQMID) expect(tokens[6].value).to eq(' ') expect(tokens[6].line).to eq(1) expect(tokens[6].column).to eq(18) expect(tokens[7].type).to eq(:HEREDOC_OPEN) expect(tokens[7].value).to eq('end2') expect(tokens[7].line).to eq(1) expect(tokens[7].column).to eq(22) expect(tokens[8].type).to eq(:DQPOST) expect(tokens[8].value).to eq('') expect(tokens[8].line).to eq(1) expect(tokens[8].column).to eq(29) expect(tokens[9].type).to eq(:NEWLINE) expect(tokens[9].value).to eq("\n") expect(tokens[9].line).to eq(1) expect(tokens[9].column).to eq(31) expect(tokens[10].type).to eq(:HEREDOC) expect(tokens[10].value).to eq(" foo\n ") expect(tokens[10].raw).to eq(" foo\n |-end1") expect(tokens[10].line).to eq(2) expect(tokens[10].column).to eq(1) expect(tokens[11].type).to eq(:NEWLINE) expect(tokens[11].value).to eq("\n") expect(tokens[11].line).to eq(3) expect(tokens[11].column).to eq(9) expect(tokens[12].type).to eq(:HEREDOC) expect(tokens[12].value).to eq(" bar\n ") expect(tokens[12].raw).to eq(" bar\n |-end2") expect(tokens[12].line).to eq(4) expect(tokens[12].column).to eq(1) expect(tokens[13].type).to eq(:NEWLINE) expect(tokens[13].value).to eq("\n") expect(tokens[13].line).to eq(5) expect(tokens[13].column).to eq(9) end it 'should handle a heredoc that specifies a syntax' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @("end":json/) { "foo": "bar" } |-end END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(8) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:WHITESPACE) expect(tokens[1].value).to eq(' ') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(5) expect(tokens[2].type).to eq(:EQUALS) expect(tokens[2].value).to eq('=') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(6) expect(tokens[3].type).to eq(:WHITESPACE) expect(tokens[3].value).to eq(' ') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(7) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('"end":json/') expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(8) expect(tokens[5].type).to eq(:NEWLINE) expect(tokens[5].value).to eq("\n") expect(tokens[5].line).to eq(1) expect(tokens[5].column).to eq(22) expect(tokens[6].type).to eq(:HEREDOC) expect(tokens[6].value).to eq(" {\n \"foo\": \"bar\"\n }\n ") expect(tokens[6].raw).to eq(" {\n \"foo\": \"bar\"\n }\n |-end") expect(tokens[6].line).to eq(2) expect(tokens[6].column).to eq(1) expect(tokens[7].type).to eq(:NEWLINE) expect(tokens[7].value).to eq("\n") expect(tokens[7].line).to eq(5) expect(tokens[7].column).to eq(8) end it 'should handle a heredoc with spaces in the tag' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @("myheredoc" /) foo |-myheredoc END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(8) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('"myheredoc" /') expect(tokens[6].type).to eq(:HEREDOC) expect(tokens[6].value).to eq(" foo\n ") end it 'should handle a heredoc with no indentation' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @(EOT) something EOT END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(8) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('EOT') expect(tokens[6].type).to eq(:HEREDOC) expect(tokens[6].value).to eq('something') end end context ':HEREDOC with interpolation' do it 'should parse a heredoc with no interpolated values as a :HEREDOC' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @("myheredoc"/) SOMETHING ELSE : |-myheredoc END tokens = @lexer.tokenise(manifest) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:WHITESPACE) expect(tokens[1].value).to eq(' ') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(5) expect(tokens[2].type).to eq(:EQUALS) expect(tokens[2].value).to eq('=') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(6) expect(tokens[3].type).to eq(:WHITESPACE) expect(tokens[3].value).to eq(' ') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(7) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('"myheredoc"/') expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(8) expect(tokens[5].type).to eq(:NEWLINE) expect(tokens[5].value).to eq("\n") expect(tokens[5].line).to eq(1) expect(tokens[5].column).to eq(23) expect(tokens[6].type).to eq(:HEREDOC) expect(tokens[6].value).to eq(" SOMETHING\n ELSE\n :\n ") expect(tokens[6].raw).to eq(" SOMETHING\n ELSE\n :\n |-myheredoc") expect(tokens[6].line).to eq(2) expect(tokens[6].column).to eq(1) expect(tokens[7].type).to eq(:NEWLINE) expect(tokens[7].value).to eq("\n") expect(tokens[7].line).to eq(5) expect(tokens[7].column).to eq(14) end it 'should parse a heredoc with interpolated values' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @("myheredoc"/) SOMETHING ${here} AND : $another THING | myheredoc END tokens = @lexer.tokenise(manifest) expect(tokens.map(&:to_manifest).join('')).to eq(manifest) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') expect(tokens[0].line).to eq(1) expect(tokens[0].column).to eq(1) expect(tokens[1].type).to eq(:WHITESPACE) expect(tokens[1].value).to eq(' ') expect(tokens[1].line).to eq(1) expect(tokens[1].column).to eq(5) expect(tokens[2].type).to eq(:EQUALS) expect(tokens[2].value).to eq('=') expect(tokens[2].line).to eq(1) expect(tokens[2].column).to eq(6) expect(tokens[3].type).to eq(:WHITESPACE) expect(tokens[3].value).to eq(' ') expect(tokens[3].line).to eq(1) expect(tokens[3].column).to eq(7) expect(tokens[4].type).to eq(:HEREDOC_OPEN) expect(tokens[4].value).to eq('"myheredoc"/') expect(tokens[4].line).to eq(1) expect(tokens[4].column).to eq(8) expect(tokens[5].type).to eq(:NEWLINE) expect(tokens[5].value).to eq("\n") expect(tokens[5].line).to eq(1) expect(tokens[5].column).to eq(23) expect(tokens[6].type).to eq(:HEREDOC_PRE) expect(tokens[6].value).to eq(" SOMETHING\n ") expect(tokens[6].line).to eq(2) expect(tokens[6].column).to eq(1) expect(tokens[7].type).to eq(:VARIABLE) expect(tokens[7].value).to eq('here') expect(tokens[7].line).to eq(3) expect(tokens[7].column).to eq(5) expect(tokens[7].to_manifest).to eq('here') expect(tokens[8].type).to eq(:HEREDOC_MID) expect(tokens[8].value).to eq("\n AND :\n ") expect(tokens[8].line).to eq(3) expect(tokens[8].column).to eq(9) expect(tokens[8].to_manifest).to eq("}\n AND :\n ") expect(tokens[9].type).to eq(:UNENC_VARIABLE) expect(tokens[9].value).to eq('another') expect(tokens[9].line).to eq(5) expect(tokens[9].column).to eq(3) expect(tokens[9].to_manifest).to eq('$another') expect(tokens[10].type).to eq(:HEREDOC_POST) expect(tokens[10].value).to eq("\n THING\n ") expect(tokens[10].raw).to eq("\n THING\n | myheredoc") expect(tokens[10].line).to eq(5) expect(tokens[10].column).to eq(11) end it 'should not remove the unnecessary $ from enclosed variables' do manifest = <<-END.gsub(%r{^ {6}}, '') $str = @("myheredoc"/) ${$myvar} |-myheredoc END tokens = @lexer.tokenise(manifest) expect(tokens.length).to eq(10) expect(tokens[7].type).to eq(:VARIABLE) expect(tokens[7].value).to eq('myvar') expect(tokens[7].raw).to eq('$myvar') expect(tokens[7].to_manifest).to eq('$myvar') expect(tokens.map(&:to_manifest).join('')).to eq(manifest) end end context ':CLASSREF' do it 'should match single capitalised alphanumeric term' do token = @lexer.tokenise('One').first expect(token.type).to eq(:CLASSREF) expect(token.value).to eq('One') end it 'should match two capitalised alphanumeric terms sep by ::' do token = @lexer.tokenise('One::Two').first expect(token.type).to eq(:CLASSREF) expect(token.value).to eq('One::Two') end it 'should match many capitalised alphanumeric terms sep by ::' do token = @lexer.tokenise('One::Two::Three::Four::Five').first expect(token.type).to eq(:CLASSREF) expect(token.value).to eq('One::Two::Three::Four::Five') end it 'should match capitalised terms prefixed by ::' do token = @lexer.tokenise('::One').first expect(token.type).to eq(:CLASSREF) expect(token.value).to eq('::One') end it 'should match terms that start with Types' do token = @lexer.tokenise('Regexp_foo').first expect(token.type).to eq(:CLASSREF) expect(token.value).to eq('Regexp_foo') end end context ':NAME' do it 'should match lowercase alphanumeric terms' do token = @lexer.tokenise('one-two').first expect(token.type).to eq(:NAME) expect(token.value).to eq('one-two') end it 'should match lowercase alphanumeric terms sep by ::' do token = @lexer.tokenise('one::two').first expect(token.type).to eq(:NAME) expect(token.value).to eq('one::two') end it 'should match many lowercase alphanumeric terms sep by ::' do token = @lexer.tokenise('one::two::three::four::five').first expect(token.type).to eq(:NAME) expect(token.value).to eq('one::two::three::four::five') end it 'should match lowercase alphanumeric terms prefixed by ::' do token = @lexer.tokenise('::1one::2two::3three').first expect(token.type).to eq(:NAME) expect(token.value).to eq('::1one::2two::3three') end it 'should match barewords beginning with an underscore' do token = @lexer.tokenise('_bareword').first expect(token.type).to eq(:NAME) expect(token.value).to eq('_bareword') end end context ':FUNCTION_NAME' do it 'should match when a :NAME is followed by a :LPAREN' do token = @lexer.tokenise('my_function(').first expect(token.type).to eq(:FUNCTION_NAME) expect(token.value).to eq('my_function') end end context ':NUMBER' do it 'should match numeric terms' do token = @lexer.tokenise('1234567890').first expect(token.type).to eq(:NUMBER) expect(token.value).to eq('1234567890') end it 'should match float terms' do token = @lexer.tokenise('12345.6789').first expect(token.type).to eq(:NUMBER) expect(token.value).to eq('12345.6789') end it 'should match hexadecimal terms' do token = @lexer.tokenise('0xCAFE1029').first expect(token.type).to eq(:NUMBER) expect(token.value).to eq('0xCAFE1029') end it 'should match float with exponent terms' do token = @lexer.tokenise('10e23').first expect(token.type).to eq(:NUMBER) expect(token.value).to eq('10e23') end it 'should match float with negative exponent terms' do token = @lexer.tokenise('10e-23').first expect(token.type).to eq(:NUMBER) expect(token.value).to eq('10e-23') end it 'should match float with exponent terms' do token = @lexer.tokenise('1.234e5').first expect(token.type).to eq(:NUMBER) expect(token.value).to eq('1.234e5') end end context ':COMMENT' do it 'should match everything on a line after #' do token = @lexer.tokenise('foo # bar baz')[2] expect(token.type).to eq(:COMMENT) expect(token.value).to eq(' bar baz') end it 'should not include DOS line endings in the comment value' do tokens = @lexer.tokenise("foo # bar baz\r\n") expect(tokens[2]).to have_attributes(:type => :COMMENT, :value => ' bar baz') expect(tokens[3]).to have_attributes(:type => :NEWLINE, :value => "\r\n") end it 'should not include Unix line endings in the comment value' do tokens = @lexer.tokenise("foo # bar baz\n") expect(tokens[2]).to have_attributes(:type => :COMMENT, :value => ' bar baz') expect(tokens[3]).to have_attributes(:type => :NEWLINE, :value => "\n") end end context ':MLCOMMENT' do it 'should match comments on a single line' do token = @lexer.tokenise('/* foo bar */').first expect(token.type).to eq(:MLCOMMENT) expect(token.value).to eq('foo bar') end it 'should match comments on multiple lines' do token = @lexer.tokenise("/* foo\n * bar\n*/").first expect(token.type).to eq(:MLCOMMENT) expect(token.value).to eq("foo\n bar\n") end end context ':SLASH_COMMENT' do it 'should match everyone on a line after //' do token = @lexer.tokenise('foo // bar baz')[2] expect(token.type).to eq(:SLASH_COMMENT) expect(token.value).to eq(' bar baz') end it 'should not include DOS line endings in the comment value' do tokens = @lexer.tokenise("foo // bar baz\r\n") expect(tokens[2]).to have_attributes(:type => :SLASH_COMMENT, :value => ' bar baz') expect(tokens[3]).to have_attributes(:type => :NEWLINE, :value => "\r\n") end it 'should not include Unix line endings in the comment value' do tokens = @lexer.tokenise("foo // bar baz\n") expect(tokens[2]).to have_attributes(:type => :SLASH_COMMENT, :value => ' bar baz') expect(tokens[3]).to have_attributes(:type => :NEWLINE, :value => "\n") end end context ':SSTRING' do it 'should match a single quoted string' do token = @lexer.tokenise("'single quoted string'").first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('single quoted string') end it "should match a single quoted string with an escaped '" do token = @lexer.tokenise(%q('single quoted string with "\\'"')).first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('single quoted string with "\\\'"') end it 'should match a single quoted string with an escaped $' do token = @lexer.tokenise(%q('single quoted string with "\$"')).first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('single quoted string with "\\$"') end it 'should match a single quoted string with an escaped .' do token = @lexer.tokenise(%q('single quoted string with "\."')).first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('single quoted string with "\\."') end it 'should match a single quoted string with an escaped \\n' do token = @lexer.tokenise(%q('single quoted string with "\n"')).first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('single quoted string with "\\n"') end it 'should match a single quoted string with an escaped \\' do token = @lexer.tokenise(%q('single quoted string with "\\\\"')).first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('single quoted string with "\\\\"') end it 'should match an empty string' do token = @lexer.tokenise("''").first expect(token.type).to eq(:SSTRING) expect(token.value).to eq('') end it 'should match an empty string ending with \\\\' do token = @lexer.tokenise("'foo\\\\'").first expect(token.type).to eq(:SSTRING) expect(token.value).to eq(%(foo\\\\)) end it 'should match single quoted string containing a line break' do token = @lexer.tokenise("'\n'").first expect(token.type).to eq(:SSTRING) expect(token.value).to eq("\n") end end context ':REGEX' do it 'should match anything enclosed in //' do token = @lexer.tokenise('/this is a regex/').first expect(token.type).to eq(:REGEX) expect(token.value).to eq('this is a regex') end it 'should match even if there is \n in the regex' do token = @lexer.tokenise("/this is a regex,\ntoo/").first expect(token.type).to eq(:REGEX) expect(token.value).to eq("this is a regex,\ntoo") end it 'should not consider \/ to be the end of the regex' do token = @lexer.tokenise('/this is \/ a regex/').first expect(token.type).to eq(:REGEX) expect(token.value).to eq('this is \\/ a regex') end it 'should be allowed as a param to a data type' do tokens = @lexer.tokenise('Foo[/bar/]') expect(tokens[2].type).to eq(:REGEX) expect(tokens[2].value).to eq('bar') end it 'should be allowed as a param to an optional data type' do tokens = @lexer.tokenise('Optional[Regexp[/^puppet/]]') expect(tokens[4].type).to eq(:REGEX) expect(tokens[4].value).to eq('^puppet') end it 'should not match chained division' do tokens = @lexer.tokenise('$x = $a/$b/$c') expect(tokens.select { |r| r.type == :REGEX }).to be_empty end it 'should properly parse when regex follows an if' do tokens = @lexer.tokenise('if /^icinga_service_icon_.*/ in $location_info { }') expect(tokens[2].type).to eq(:REGEX) end it 'should properly parse when a regex follows an elsif' do tokens = @lexer.tokenise('if /a/ in $location_info { } elsif /b/ in $location_info { }') expect(tokens[2].type).to eq(:REGEX) expect(tokens[14].type).to eq(:REGEX) end it 'should properly parse when a regex is provided as a function argument' do tokens = @lexer.tokenise('$somevar = $other_var.match(/([\w\.]+(:\d+)?(\/\w+)?)(:(\w+))?/)') expect(tokens[8].type).to eq(:REGEX) expect(tokens[8].value).to eq('([\w\.]+(:\d+)?(\/\w+)?)(:(\w+))?') end it 'should discriminate between division and regexes' do tokens = @lexer.tokenise('if $a/10==0 or $b=~/{}/') expect(tokens[3].type).to eq(:DIV) expect(tokens[12].type).to eq(:REGEX) expect(tokens[12].value).to eq('{}') end end context ':STRING' do it 'should parse strings with embedded strings' do expect { @lexer.tokenise('exec { "/bin/echo \"${environment}\"": }') }.to_not raise_error end it 'should match double quoted string containing a line break' do token = @lexer.tokenise(%("\n")).first expect(token.type).to eq(:STRING) expect(token.value).to eq("\n") end it 'should handle interpolated values that contain double quotes' do manifest = %{"export bar=\\"${join(hiera('test'), "," )}\\""} tokens = @lexer.tokenise(manifest) expect(tokens[0].type).to eq(:DQPRE) expect(tokens[0].value).to eq('export bar=\"') expect(tokens[1].type).to eq(:FUNCTION_NAME) expect(tokens[1].value).to eq('join') expect(tokens[2].type).to eq(:LPAREN) expect(tokens[3].type).to eq(:FUNCTION_NAME) expect(tokens[3].value).to eq('hiera') expect(tokens[4].type).to eq(:LPAREN) expect(tokens[5].type).to eq(:SSTRING) expect(tokens[5].value).to eq('test') expect(tokens[6].type).to eq(:RPAREN) expect(tokens[7].type).to eq(:COMMA) expect(tokens[8].type).to eq(:WHITESPACE) expect(tokens[8].value).to eq(' ') expect(tokens[9].type).to eq(:STRING) expect(tokens[9].value).to eq(',') expect(tokens[10].type).to eq(:WHITESPACE) expect(tokens[10].value).to eq(' ') expect(tokens[11].type).to eq(:RPAREN) expect(tokens[12].type).to eq(:DQPOST) expect(tokens[12].value).to eq('\"') end end context ':WHITESPACE' do it 'should parse spaces' do token = @lexer.tokenise(' ').first expect(token.type).to eq(:WHITESPACE) expect(token.value).to eq(' ') end it 'should parse tabs' do token = @lexer.tokenise("\t").first expect(token.type).to eq(:WHITESPACE) expect(token.value).to eq("\t") end it 'should parse unicode spaces', :unless => RUBY_VERSION == '1.8.7' do token = @lexer.tokenise("\xc2\xa0").first expect(token.type).to eq(:WHITESPACE) expect(token.value).to eq("\xc2\xa0") end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/0000755000004100000410000000000013611752231020725 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_conditionals/0000755000004100000410000000000013611752231024550 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb0000644000004100000410000000641313611752231032315 0ustar www-datawww-datarequire 'spec_helper' describe 'case_without_default' do let(:msg) { 'case statement without a default case' } context 'case statement with a default case' do let(:code) do <<-END case $foo { bar: { } default: { } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'case statement without a default case' do let(:code) do <<-END case $foo { bar: { } baz: { } } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) end end context 'nested case statements without a default case on the outermost' do let(:code) do <<-END case $foo { case $foop { bar: {} default: {} } } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg) end end context 'three nested case statements with two missing default cases' do let(:code) do <<-END case $foo { case $foop { bar: {} case $woop { baz: {} } default: {} } } END end it 'should detect two problems' do expect(problems).to have(2).problems end it 'should create two warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) expect(problems).to contain_warning(msg).on_line(4).in_column(13) end end context 'issue-117' do let(:code) do <<-END $mem = inline_template('<% mem,unit = scope.lookupvar(\'::memorysize\').split mem = mem.to_f # Normalize mem to bytes case unit when nil: mem *= (1<<0) when \'kB\': mem *= (1<<10) when \'MB\': mem *= (1<<20) when \'GB\': mem *= (1<<30) when \'TB\': mem *= (1<<40) end %><%= mem.to_i %>') END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'issue-829 nested selector with default in case without default' do let(:code) do <<-END case $::operatingsystem { 'centos': { $variable = $::operatingsystemmajrelease ? { '7' => 'value1' default => 'value2', } } } END end it 'should create one warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(9) end end context 'issue-829 nested selector with default in case with default' do let(:code) do <<-END case $::operatingsystem { 'centos': { $variable = $::operatingsystemmajrelease ? { '7' => 'value1' default => 'value2', } } default: {} } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb0000644000004100000410000000147513611752231033200 0ustar www-datawww-datarequire 'spec_helper' describe 'selector_inside_resource' do let(:msg) { 'selector inside resource block' } context 'resource with a selector' do let(:code) do <<-END file { 'foo': ensure => $bar ? { true => present, default => absent, }, } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(2).in_column(18) end end context 'resource with a variable as a attr value' do let(:code) do <<-END file { 'foo', ensure => $bar, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/0000755000004100000410000000000013611752231023553 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb0000644000004100000410000000226613611752231034267 0ustar www-datawww-datarequire 'spec_helper' describe 'single_quote_string_with_variables' do let(:msg) { 'single quoted string containing a variable found' } context 'multiple strings in a line' do let(:code) { "\"aoeu\" '${foo}'" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(1).in_column(8) end end context 'single quoted inline template with dollar signs has no problems' do let(:code) do <<-END $list = ['one', 'two', 'three'] file { '/tmp/text.txt': ensure => file, content => inline_template('<% $list.each |$item| { %><%= "${item}\n" %><% } %>'), } END end it { expect(problems).to have(0).problem } end context 'single quoted inline epp with dollar signs has no problems' do let(:code) do <<-END $list = ['one', 'two', 'three'] file { '/tmp/text.txt': ensure => file, content => inline_template('<% @list.each do |item| %><%= @item %>\n<% end %>'), } END end it { expect(problems).to have(0).problem } end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb0000644000004100000410000000556713611752231031343 0ustar www-datawww-datarequire 'spec_helper' describe 'only_variable_string' do let(:msg) { 'string containing only a variable' } context 'with fix disabled' do context 'string containing only a variable' do let(:code) { '"${foo}"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(4) end end context 'string containing only a variable w/ ref' do let(:code) { '"${foo[0]}"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(4) end end context 'string containing only a variable w/ lots of refs' do let(:code) { '"${foo[0][aoeuaoeu][bar][999]}"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(4) end end context 'string containing only a variable as a hash key' do let(:code) do <<-END $bar = 'key' $foo = { \"$bar\" => 1, } END end it 'should not detect any problems' do expect(problems).to be_empty end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'string containing only a variable' do let(:code) { '"${foo}"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(4) end it 'should unquote the variable' do expect(manifest).to eq('$foo') end end context 'string contaiting only a variable w/ ref' do let(:code) { '"${foo[0]}"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(4) end it 'should unquoted the variable' do expect(manifest).to eq('$foo[0]') end end context 'string containing only a variable w/ lots of refs' do let(:code) { '"${foo[0][aoeuaoeu][bar][999]}"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(4) end it 'should unquote the variable' do expect(manifest).to eq('$foo[0][aoeuaoeu][bar][999]') end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb0000644000004100000410000000654313611752231030305 0ustar www-datawww-datarequire 'spec_helper' describe 'quoted_booleans' do let(:msg) { 'quoted boolean value found' } context 'with fix disabled' do context 'quoted false' do let(:code) { "class { 'foo': boolFlag => 'false' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(28) end end context 'quoted true' do let(:code) { "class { 'foo': boolFlag => 'true' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(28) end end context 'double quoted true' do let(:code) { "class { 'foo': boolFlag => \"true\" }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(28) end end context 'double quoted false' do let(:code) { "class { 'foo': boolFlag => \"false\" }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(28) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'quoted false' do let(:code) { "class { 'foo': boolFlag => 'false' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(28) end it 'should unquote the boolean' do expect(manifest).to eq("class { 'foo': boolFlag => false }") end end context 'quoted true' do let(:code) { "class { 'foo': boolFlag => 'true' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(28) end it 'should unquote the boolean' do expect(manifest).to eq("class { 'foo': boolFlag => true }") end end context 'double quoted true' do let(:code) { "class { 'foo': boolFlag => \"true\" }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(28) end it 'should unquote the boolean' do expect(manifest).to eq("class { 'foo': boolFlag => true }") end end context 'double quoted false' do let(:code) { "class { 'foo': boolFlag => \"false\" }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(28) end it 'should unquote the boolean' do expect(manifest).to eq("class { 'foo': boolFlag => false }") end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb0000644000004100000410000000275313611752231032633 0ustar www-datawww-datarequire 'spec_helper' describe 'puppet_url_without_modules' do let(:msg) { 'puppet:// URL without modules/ found' } context 'puppet:// url with modules' do let(:code) { "'puppet:///modules/foo'" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'with fix disabled' do context 'puppet:// url without modules' do let(:code) { "'puppet:///foo'" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(1) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'puppet:// url without modules' do let(:code) { "'puppet:///foo'" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(1) end it 'should insert modules into the path' do expect(manifest).to eq("'puppet:///modules/foo'") end end end context 'double string wrapped puppet:// urls' do let(:code) { File.read('spec/fixtures/test/manifests/url_interpolation.pp') } it 'should detect several problems' do expect(problems).to have(4).problem end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb0000644000004100000410000001357313611752231031527 0ustar www-datawww-datarequire 'spec_helper' describe 'double_quoted_strings' do let(:msg) { 'double quoted string containing no variables' } context 'with fix disabled' do context 'double quoted string containing a variable inside single quotes' do let(:code) { "exec { \"/usr/bin/wget -O - '${source}' | /usr/bin/apt-key add -\": }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multiple strings in a line' do let(:code) { "\"aoeu\" '${foo}'" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(1) end end context 'double quoted string nested in a single quoted string' do let(:code) { "'grep \"status=sent\" /var/log/mail.log'" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'double quoted string after a comment' do let(:code) { "service { 'foo': } # \"bar\"" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'double quoted string containing newline but no variables' do let(:code) { %("foo\n") } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'double quoted string with backslash for continuation' do let(:code) do <<-END class puppet::master::maintenance ( ) { cron { 'puppet_master_reports_cleanup': command => "/usr/bin/find /var/lib/puppet/reports -type f -mtime +15 \ -delete && /usr/bin/find /var/lib/puppet/reports -mindepth 1 \ -empty -type d -delete", minute => '15', hour => '5', } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'double quoted true' do let(:code) { "class { 'foo': boolFlag => \"true\" }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(28) end end context 'double quoted false' do let(:code) { "class { 'foo': boolFlag => \"false\" }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(28) end end context 'double quoted stings containing supported escape patterns' do let(:code) do <<-END $string1 = "this string contins \n newline" $string2 = "this string contains \ttab" $string3 = "this string contains \${escaped} var" $string4 = "this string contains \\"escaped \\" double quotes" $string5 = "this string contains \\'escaped \\' single quotes" $string6 = "this string contains \r line return" $string7 = "this string contains \\\\ an escaped backslash" END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'double quoted string with random escape should be rejected' do let(:code) { %( $ztring = "this string contains \l random esape" ) } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(12) end end context 'single quotes in a double quoted string' do let(:code) { "\"this 'string' 'has' lots of 'quotes'\"" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'double quoted string containing single quoted string' do let(:code) { %(notify { "'foo'": }) } it 'should not detect any problems' do expect(problems).to have(0).problems end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'double quoted string containing a variable inside single quotes' do let(:code) { "exec { \"/usr/bin/wget -O - '${source}' | /usr/bin/apt-key add -\": }" } it 'should not detect any problems' do expect(problems).to have(0).problems end it 'should not modify the manifest' do expect(manifest).to eq(code) end end context 'double quoted string containing a lone dollar' do let(:code) { "\"sed -i 's/^;*[[:space:]]*${name}[[:space:]]*=.*$/${name} = ${value}/g' file\"" } it 'should not detect any problems' do expect(problems).to have(0).problems end it 'should not modify the manifest' do expect(manifest).to eq(code) end end context 'multiple strings in a line' do let(:code) { "\"aoeu\" '${foo}'" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(1) end it 'should convert the double quoted string into single quotes' do expect(manifest).to eq("'aoeu' '${foo}'") end end context 'single quotes in a double quoted string' do let(:code) { "\"this 'string' 'has' lots of 'quotes'\"" } it 'should not detect any problems' do expect(problems).to have(0).problems end it 'should not modify the manifest' do expect(manifest).to eq(code) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb0000644000004100000410000000645213611752231031625 0ustar www-datawww-datarequire 'spec_helper' describe 'variables_not_enclosed' do let(:msg) { 'variable not enclosed in {}' } context 'with fix disabled' do context 'variable not enclosed in {}' do let(:code) { '" $gronk"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(3) end end context 'variable not enclosed in {} after many tokens' do let(:code) { ("'groovy'\n" * 20) + '" $gronk"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(21).in_column(3) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'variable not enclosed in {}' do let(:code) { '" $gronk"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(3) end it 'should enclose the variable in braces' do expect(manifest).to eq('" ${gronk}"') end end context 'variable not enclosed in {} after many tokens' do let(:code) { ("'groovy'\n" * 20) + '" $gronk"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(21).in_column(3) end it 'should enclose the variable in braces' do expect(manifest).to eq(("'groovy'\n" * 20) + '" ${gronk}"') end end context 'variables not enclosed in {}, delimited by -' do let(:code) { '"$foo-$bar"' } it 'should only detect two problems' do expect(problems).to have(2).problems end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(2) expect(problems).to contain_fixed(msg).on_line(1).in_column(7) end it 'should enclose both variables in braces' do expect(manifest).to eq('"${foo}-${bar}"') end end context 'variable with a hash or array reference not enclosed' do let(:code) { %("$foo['bar'][2]something") } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(2) end it 'should enclose the variable with the references' do expect(manifest).to eq(%("${foo['bar'][2]}something")) end end context 'unenclosed variable followed by a dash and then text' do let(:code) { '"$hostname-keystore"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(2) end it 'should enclose the variable but not the text' do expect(manifest).to eq('"${hostname}-keystore"') end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_variables/0000755000004100000410000000000013611752231024032 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_variables/variable_is_lowercase_spec.rb0000644000004100000410000000115213611752231031714 0ustar www-datawww-datarequire 'spec_helper' describe 'variable_is_lowercase' do let(:msg) { 'variable contains an uppercase letter' } context 'a variable containing an uppercase letter' do let(:code) { '$fooBar' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(1) end end context 'a variable containing only lowercase letters' do let(:code) { '$foobar' } it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb0000644000004100000410000000210613611752231032052 0ustar www-datawww-datarequire 'spec_helper' describe 'variable_contains_dash' do let(:msg) { 'variable contains a dash' } context 'a variable containing a dash' do let(:code) { '$foo-bar' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(1) end end context 'variable containing a dash' do let(:code) { '" $foo-bar"' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(3) end end context 'variable with an array reference containing a dash' do let(:code) { '$foo[bar-baz]' } it 'should not detect any problems' do expect(problems).to be_empty end end context 'enclosed variable in a string followed by a dash' do let(:code) { '"${variable}-is-ok"' } it 'should not detect any problems' do expect(problems).to be_empty end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_comments/0000755000004100000410000000000013611752231023707 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb0000644000004100000410000000175113611752231030271 0ustar www-datawww-datarequire 'spec_helper' describe 'slash_comments' do let(:msg) { '// comment found' } context 'with fix disabled' do context 'slash comments' do let(:code) { '// foo' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(1) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'slash comments' do let(:code) { '// foo' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(1) end it 'should replace the double slash with a hash' do expect(manifest).to eq('# foo') end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb0000644000004100000410000000500713611752231030126 0ustar www-datawww-datarequire 'spec_helper' describe 'star_comments' do let(:msg) { '/* */ comment found' } context 'with fix disabled' do context 'multiline comment w/ one line of content' do let(:code) do <<-END /* foo */ END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(11) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'multiline comment w/ no indents' do let(:code) do <<-END.gsub(%r{^ {10}}, '') /* foo * * * * bar */ END end let(:fixed) do <<-END.gsub(%r{^ {10}}, '') # foo * # * # bar END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_fixed(msg).on_line(1).in_column(1) end it 'should convert the multiline comment' do expect(manifest).to eq(fixed) end end context 'multiline comment w/ one line of content' do let(:code) do <<-END /* foo */ END end let(:fixed) do <<-END # foo END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_fixed(msg).on_line(1).in_column(11) end it 'should convert the multiline comment' do expect(manifest).to eq(fixed) end end context 'multiline comment w/ multiple line of content' do let(:code) do <<-END /* foo * bar * baz */ notify { 'foo': } END end let(:fixed) do <<-END # foo # bar # baz notify { 'foo': } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_fixed(msg).on_line(1).in_column(11) end it 'should convert the multiline comment' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_nodes/0000755000004100000410000000000013611752231023172 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb0000644000004100000410000001032613611752231030404 0ustar www-datawww-datarequire 'spec_helper' describe 'unquoted_node_name' do let(:msg) { 'unquoted node name found' } context 'with fix disabled' do context 'unquoted node name' do let(:code) { 'node foo { }' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(6) end end context 'default node' do let(:code) { 'node default { }' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'single quoted node name' do let(:code) { "node 'foo' { }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'regex node name' do let(:code) { 'node /foo/ { }' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multiple bare node names' do let(:code) { 'node foo, bar, baz { }' } it 'should detect 3 problems' do expect(problems).to have(3).problems end it 'should create 3 warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(6) expect(problems).to contain_warning(msg).on_line(1).in_column(11) expect(problems).to contain_warning(msg).on_line(1).in_column(16) end end context 'mixed node name types' do let(:code) { "node foo, 'bar', baz { }" } it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should create 2 warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(6) expect(problems).to contain_warning(msg).on_line(1).in_column(18) end end context 'multiple node blocks' do let(:code) { 'node foo { } node bar { }' } it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should create 2 warnings' do expect(problems).to contain_warning(msg).on_line(1).in_column(6) expect(problems).to contain_warning(msg).on_line(1).in_column(19) end end context 'incomplete node block' do let(:code) { 'node foo' } it 'should detect a problem' do expect(problems).to have(1).problem end it 'should create 1 error' do expect(problems).to contain_error('Syntax error (try running `puppet parser validate `)').on_line(1).in_column(1) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'unquoted node name' do let(:code) { 'node foo { }' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(6) end it 'should quote the node name' do expect(manifest).to eq("node 'foo' { }") end end context 'multiple bare node names' do let(:code) { 'node foo, bar, baz { }' } let(:fixed) { "node 'foo', 'bar', 'baz' { }" } it 'should detect 3 problems' do expect(problems).to have(3).problems end it 'should fix the 3 problems' do expect(problems).to contain_fixed(msg).on_line(1).in_column(6) expect(problems).to contain_fixed(msg).on_line(1).in_column(11) expect(problems).to contain_fixed(msg).on_line(1).in_column(16) end it 'should quote all three node names' do expect(manifest).to eq(fixed) end end context 'mixed node name types' do let(:code) { "node foo, 'bar', baz { }" } let(:fixed) { "node 'foo', 'bar', 'baz' { }" } it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should fix the 2 problems' do expect(problems).to contain_fixed(msg).on_line(1).in_column(6) expect(problems).to contain_fixed(msg).on_line(1).in_column(18) end it 'should quote the 2 unquoted node names' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/0000755000004100000410000000000013611752231024216 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb0000644000004100000410000000314313611752231027026 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' describe '80chars' do before do PuppetLint.configuration.send('enable_80chars') end let(:msg) { 'line has more than 80 characters' } context 'file resource with a source line > 80c' do let(:code) do <<-END file { source => 'puppet:///modules/certificates/etc/ssl/private/wildcard.example.com.crt', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'file resource with a template line > 80c' do let(:code) do <<-END file { content => template('mymodule/this/is/a/truely/absurdly/long/path/that/should/make/you/feel/bad'), } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'length of lines with UTF-8 characters' do let(:code) do <<-END # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ # ┃ Configuration ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛" END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context '81 character line' do let(:code) { 'a' * 81 } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(80) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb0000644000004100000410000006421113611752231030751 0ustar www-datawww-datarequire 'spec_helper' describe 'arrow_alignment' do let(:msg) { 'indentation of => is not properly aligned (expected in column %d, but found it in column %d)' } context 'with fix disabled' do context 'selectors inside a resource' do let(:code) do <<-END file { 'foo': ensure => $ensure, require => $ensure ? { present => Class['tomcat::install'], absent => undef; }, foo => bar, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'selectors in the middle of a resource' do let(:code) do <<-END file { 'foo': ensure => $ensure ? { present => directory, absent => undef, }, owner => 'tomcat6', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'selector inside a resource' do let(:code) do <<-END ensure => $ensure ? { present => directory, absent => undef, }, owner => 'foo4', group => 'foo4', mode => '0755', END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'selector inside a hash inside a resource' do let(:code) do <<-END server => { ensure => ensure => $ensure ? { present => directory, absent => undef, }, ip => '192.168.1.1' }, owner => 'foo4', group => 'foo4', mode => '0755', END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'nested hashes with correct indentation' do let(:code) do <<-END class { 'lvs::base': virtualeservers => { '192.168.2.13' => { vport => '11025', service => 'smtp', scheduler => 'wlc', protocol => 'tcp', checktype => 'external', checkcommand => '/path/to/checkscript', real_servers => { 'server01' => { real_server => '192.168.2.14', real_port => '25', forwarding => 'masq', }, 'server02' => { real_server => '192.168.2.15', real_port => '25', forwarding => 'masq', } } } } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'single resource with a misaligned =>' do let(:code) do <<-END file { '/tmp/foo': foo => 1, bar => 2, gronk => 3, baz => 4, meh => 5, } END end it 'should detect four problems' do expect(problems).to have(4).problems end it 'should create four warnings' do expect(problems).to contain_warning(format(msg, 19, 17)).on_line(2).in_column(17) expect(problems).to contain_warning(format(msg, 19, 17)).on_line(3).in_column(17) expect(problems).to contain_warning(format(msg, 19, 18)).on_line(5).in_column(18) expect(problems).to contain_warning(format(msg, 19, 17)).on_line(6).in_column(17) end end context 'single resource with a misaligned => and semicolon at the end' do let(:code) do <<-END file { '/tmp/bar': foo => 1, bar => 2, gronk => 3, baz => 4, meh => 5; } END end it 'should detect four problems' do expect(problems).to have(4).problems end it 'should create four warnings' do expect(problems).to contain_warning(format(msg, 19, 17)).on_line(2).in_column(17) expect(problems).to contain_warning(format(msg, 19, 17)).on_line(3).in_column(17) expect(problems).to contain_warning(format(msg, 19, 18)).on_line(5).in_column(18) expect(problems).to contain_warning(format(msg, 19, 17)).on_line(6).in_column(17) end end context 'complex resource with a misaligned =>' do let(:code) do <<-END file { '/tmp/foo': foo => 1, bar => $baz ? { gronk => 2, meh => 3, }, meep => 4, bah => 5, } END end it 'should detect three problems' do expect(problems).to have(3).problems end it 'should create three warnings' do expect(problems).to contain_warning(format(msg, 18, 17)).on_line(2).in_column(17) expect(problems).to contain_warning(format(msg, 21, 19)).on_line(5).in_column(19) expect(problems).to contain_warning(format(msg, 18, 17)).on_line(8).in_column(17) end end context 'multi-resource with a misaligned =>' do let(:code) do <<-END file { '/tmp/foo': ; '/tmp/bar': foo => 'bar'; '/tmp/baz': gronk => 'bah', meh => 'no' } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(format(msg, 21, 19)).on_line(7).in_column(19) end end context 'multi-resource with a misaligned => and semicolons' do let(:code) do <<-END file { '/tmp/foo': ensure => 'directory', owner => 'root', mode => '0755'; '/tmp/bar': ensure => 'directory'; '/tmp/baz': ensure => 'directory', owner => 'root', mode => '0755'; } END end it 'should only detect a single problem' do expect(problems).to have(4).problem end it 'should create a warning' do expect(problems).to contain_warning(format(msg, 22, 21)).on_line(4).in_column(21) expect(problems).to contain_warning(format(msg, 22, 20)).on_line(5).in_column(20) expect(problems).to contain_warning(format(msg, 22, 21)).on_line(10).in_column(21) expect(problems).to contain_warning(format(msg, 22, 20)).on_line(11).in_column(20) end end context 'multiple single line resources' do let(:code) do <<-END file { 'foo': ensure => file } package { 'bar': ensure => present } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'resource with unaligned => in commented line' do let(:code) do <<-END file { 'foo': ensure => directory, # purge => true, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'single line resource spread out on multiple lines' do let(:code) do <<-END file { 'foo': ensure => present, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multiline resource with a single line of params' do let(:code) do <<-END mymodule::do_thing { 'some thing': whatever => { foo => 'bar', one => 'two' }, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'resource with aligned => too far out' do let(:code) do <<-END file { '/tmp/foo': ensure => file, mode => '0444', } END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should create 2 warnings' do expect(problems).to contain_warning(format(msg, 20, 21)).on_line(2).in_column(21) expect(problems).to contain_warning(format(msg, 20, 21)).on_line(3).in_column(21) end end context 'resource with multiple params where one is an empty hash' do let(:code) do <<-END foo { 'foo': a => true, b => { } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multiline resource with multiple params on a line' do let(:code) do <<-END user { 'test': a => 'foo', bb => 'bar', ccc => 'baz', } END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should create 2 warnings' do expect(problems).to contain_warning(format(msg, 17, 15)).on_line(2).in_column(15) expect(problems).to contain_warning(format(msg, 17, 28)).on_line(2).in_column(28) end end context 'resource param containing a single-element same-line hash' do let(:code) do <<-END foo { 'foo': a => true, b => { 'a' => 'b' } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multiline hash with opening brace on same line as first pair' do let(:code) do <<-END foo { 'foo': bar => [ { aa => bb, c => d}, ], } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'unaligned multiline hash with opening brace on the same line as the first pair' do let(:code) do <<-END foo { 'foo': bar => [ { aa => bb, c => d}, ], } END end it 'should detect one problem' do expect(problems).to have(1).problem end it 'should create one warning' do expect(problems).to contain_warning(format(msg, 20, 19)).on_line(4).in_column(19) end end context 'hash with strings containing variables as keys properly aligned' do let(:code) do <<-END foo { foo: param => { a => 1 "${aoeu}" => 2, b => 3, }, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'hash with strings containing variables as keys incorrectly aligned' do let(:code) do <<-END foo { foo: param => { a => 1 "${aoeu}" => 2, b => 3, }, } END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should create 2 warnings' do expect(problems).to contain_warning(format(msg, 25, 17)).on_line(3).in_column(17) expect(problems).to contain_warning(format(msg, 25, 21)).on_line(5).in_column(21) end end context 'complex data structure with different indentation levels at the same depth' do let(:code) do <<-END class { 'some_class': config_hash => { 'a_hash' => { 'foo' => 'bar', }, 'an_array' => [ { foo => 'bar', bar => 'baz', }, ], }, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'where the top level of the block has no parameters' do let(:code) do <<-END case $::osfamily { 'RedHat': { $datadir = $::operatingsystem ? { 'Amazon' => pick($datadir, 'value'), default => pick($datadir, 'value'), } } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'single resource with a misaligned =>' do let(:code) do <<-END file { '/tmp/foo': foo => 1, bar => 2, gronk => 3, baz => 4, meh => 5, } END end let(:fixed) do <<-END file { '/tmp/foo': foo => 1, bar => 2, gronk => 3, baz => 4, meh => 5, } END end it 'should detect four problems' do expect(problems).to have(4).problems end it 'should fix the manifest' do expect(problems).to contain_fixed(format(msg, 19, 17)).on_line(2).in_column(17) expect(problems).to contain_fixed(format(msg, 19, 17)).on_line(3).in_column(17) expect(problems).to contain_fixed(format(msg, 19, 18)).on_line(5).in_column(18) expect(problems).to contain_fixed(format(msg, 19, 17)).on_line(6).in_column(17) end it 'should align the arrows' do expect(manifest).to eq(fixed) end end context 'complex resource with a misaligned =>' do let(:code) do <<-END file { '/tmp/foo': foo => 1, bar => $baz ? { gronk => 2, meh => 3, }, meep => 4, bah => 5, } END end let(:fixed) do <<-END file { '/tmp/foo': foo => 1, bar => $baz ? { gronk => 2, meh => 3, }, meep => 4, bah => 5, } END end it 'should detect three problems' do expect(problems).to have(3).problems end it 'should fix the manifest' do expect(problems).to contain_fixed(format(msg, 18, 17)).on_line(2).in_column(17) expect(problems).to contain_fixed(format(msg, 21, 19)).on_line(5).in_column(19) expect(problems).to contain_fixed(format(msg, 18, 17)).on_line(8).in_column(17) end it 'should align the arrows' do expect(manifest).to eq(fixed) end end context 'multi-resource with a misaligned =>' do let(:code) do <<-END file { '/tmp/foo': ; '/tmp/bar': foo => 'bar'; '/tmp/baz': gronk => 'bah', meh => 'no' } END end let(:fixed) do <<-END file { '/tmp/foo': ; '/tmp/bar': foo => 'bar'; '/tmp/baz': gronk => 'bah', meh => 'no' } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(format(msg, 21, 19)).on_line(7).in_column(19) end it 'should align the arrows' do expect(manifest).to eq(fixed) end end context 'resource with aligned => too far out' do let(:code) do <<-END file { '/tmp/foo': ensure => file, mode => '0444', } END end let(:fixed) do <<-END file { '/tmp/foo': ensure => file, mode => '0444', } END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should create 2 warnings' do expect(problems).to contain_fixed(format(msg, 20, 21)).on_line(2).in_column(21) expect(problems).to contain_fixed(format(msg, 20, 21)).on_line(3).in_column(21) end it 'should realign the arrows with the minimum whitespace' do expect(manifest).to eq(fixed) end end context 'resource with unaligned => and no whitespace between param and =>' do let(:code) do <<-END user { 'test': param1 => 'foo', param2=> 'bar', } END end let(:fixed) do <<-END user { 'test': param1 => 'foo', param2 => 'bar', } END end it 'should detect 1 problem' do expect(problems).to have(1).problem end it 'should fix the problem' do expect(problems).to contain_fixed(format(msg, 20, 19)).on_line(3).in_column(19) end it 'should add whitespace between the param and the arrow' do expect(manifest).to eq(fixed) end end context 'multiline resource with multiple params on a line' do let(:code) do <<-END user { 'test': a => 'foo', bb => 'bar', ccc => 'baz', } END end let(:fixed) do <<-END user { 'test': a => 'foo', bb => 'bar', ccc => 'baz', } END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should fix 2 problems' do expect(problems).to contain_fixed(format(msg, 17, 15)).on_line(2).in_column(15) expect(problems).to contain_fixed(format(msg, 17, 28)).on_line(2).in_column(28) end it 'should move the extra param onto its own line and realign' do expect(manifest).to eq(fixed) end end context 'multiline resource with multiple params on a line, extra one longer' do let(:code) do <<-END user { 'test': a => 'foo', bbccc => 'bar', ccc => 'baz', } END end let(:fixed) do <<-END user { 'test': a => 'foo', bbccc => 'bar', ccc => 'baz', } END end it 'should detect 2 problems' do expect(problems).to have(3).problems end it 'should fix 2 problems' do expect(problems).to contain_fixed(format(msg, 19, 15)).on_line(2).in_column(15) expect(problems).to contain_fixed(format(msg, 19, 31)).on_line(2).in_column(31) expect(problems).to contain_fixed(format(msg, 19, 17)).on_line(3).in_column(17) end it 'should move the extra param onto its own line and realign' do expect(manifest).to eq(fixed) end end context 'hash with strings containing variables as keys incorrectly aligned' do let(:code) do <<-END foo { foo: param => { a => 1 "${aoeu}" => 2, b => 3, }, } END end let(:fixed) do <<-END foo { foo: param => { a => 1 "${aoeu}" => 2, b => 3, }, } END end it 'should detect 2 problems' do expect(problems).to have(2).problems end it 'should fix 2 problems' do expect(problems).to contain_fixed(format(msg, 25, 17)).on_line(3).in_column(17) expect(problems).to contain_fixed(format(msg, 25, 21)).on_line(5).in_column(21) end it 'should align the hash rockets' do expect(manifest).to eq(fixed) end end context 'complex data structure with different indentation levels at the same depth' do let(:code) do <<-END class { 'some_class': config_hash => { 'a_hash' => { 'foo' => 'bar', }, 'an_array' => [ { foo => 'bar', bar => 'baz', }, ], }, } END end let(:fixed) do <<-END class { 'some_class': config_hash => { 'a_hash' => { 'foo' => 'bar', }, 'an_array' => [ { foo => 'bar', bar => 'baz', }, ], }, } END end it 'should detect 1 problem' do expect(problems).to have(1).problems end it 'should fix 1 problem' do expect(problems).to contain_fixed(format(msg, 23, 24)).on_line(9).in_column(24) end it 'should align the hash rockets' do expect(manifest).to eq(fixed) end end context 'complex data structure with multiple token keys' do let(:code) do <<-END.gsub(%r{^ {10}}, '') class example ( $external_ip_base, ) { bar { 'xxxxxxxxx': inputs => { 'ny' => { "${external_ip_base}.16:443 ${a} ${b} ${c}" => 'foo', 'veryveryverylongstring8:443'=> 'foo', 'simple'=> 'foo', '3'=> :foo, :baz=> :qux, 3=> 3, }, }, } } END end let(:fixed) do <<-END.gsub(%r{^ {10}}, '') class example ( $external_ip_base, ) { bar { 'xxxxxxxxx': inputs => { 'ny' => { "${external_ip_base}.16:443 ${a} ${b} ${c}" => 'foo', 'veryveryverylongstring8:443' => 'foo', 'simple' => 'foo', '3' => :foo, :baz => :qux, 3 => 3, }, }, } } END end it 'should detect 5 problems' do expect(problems).to have(5).problems end it 'should fix 5 problems' do expect(problems).to contain_fixed(format(msg, 53, 38)).on_line(9).in_column(38) expect(problems).to contain_fixed(format(msg, 53, 17)).on_line(10).in_column(17) expect(problems).to contain_fixed(format(msg, 53, 12)).on_line(11).in_column(12) expect(problems).to contain_fixed(format(msg, 53, 13)).on_line(12).in_column(13) expect(problems).to contain_fixed(format(msg, 53, 10)).on_line(13).in_column(10) end it 'should realign the arrows' do expect(manifest).to eq(fixed) end end context 'realignment of resource with an inline single line hash' do let(:code) do <<-END.gsub(%r{^ {10}}, '') class { 'puppetdb': database => 'embedded', #database => 'postgres', #postgres_version => '9.3', java_args => { '-Xmx' => '512m', '-Xms' => '256m' }, listen_address => $::ipaddress_eth0, listen_port => 4998, ssl_listen_address => $::ipaddress_eth0, ssl_listen_port => 4999, open_listen_port => false, open_ssl_listen_port => false; } END end let(:fixed) do <<-END.gsub(%r{^ {10}}, '') class { 'puppetdb': database => 'embedded', #database => 'postgres', #postgres_version => '9.3', java_args => { '-Xmx' => '512m', '-Xms' => '256m' }, listen_address => $::ipaddress_eth0, listen_port => 4998, ssl_listen_address => $::ipaddress_eth0, ssl_listen_port => 4999, open_listen_port => false, open_ssl_listen_port => false; } END end it 'should detect 8 problems' do expect(problems).to have(8).problems end it 'should fix 8 problems' do expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(2).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(5).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(6).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(7).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(8).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(9).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(10).in_column(27) expect(problems).to contain_fixed(format(msg, 24, 27)).on_line(11).in_column(27) end it 'should realign the arrows' do expect(manifest).to eq(fixed) end end context 'negative argument' do let(:code) do <<-END res { 'a': x => { 'a' => '', 'ab' => '', } } END end # TODO: This is not the desired behaviour, but adjusting the check to # properly format the hashes will need to wait until a major version # bump. let(:fixed) do <<-END res { 'a': x => { 'a' => '', 'ab' => '', } } END end it 'should detect a problem' do expect(problems).to have(1).problem end it 'should fix the problems' do expect(problems).to contain_fixed(format(msg, 24, 20)).on_line(3).in_column(20) end it 'should realign the arrows' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/140chars_spec.rb0000644000004100000410000000304313611752231027102 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' describe '140chars' do let(:msg) { 'line has more than 140 characters' } context 'file resource with a source line > 140c' do let(:code) do <<-END file { source => 'puppet:///modules/certificates/etc/ssl/private/wildcard.example.com.crt', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'file resource with a template line > 140c' do let(:code) do <<-END file { content => template('mymodule/this/is/a/truely/absurdly/long/path/that/should/make/you/feel/bad'), } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'length of lines with UTF-8 characters' do let(:code) do <<-END # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ # ┃ Configuration ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛" END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context '141 character line' do let(:code) { 'a' * 141 } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(140) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb0000644000004100000410000000470613611752231031611 0ustar www-datawww-datarequire 'spec_helper' describe 'trailing_whitespace' do let(:msg) { 'trailing whitespace found' } context 'with fix disabled' do context 'line with trailing whitespace' do let(:code) { 'foo ' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(1).in_column(4) end end context 'line without code and trailing whitespace' do let(:code) do [ 'class {', ' ', '}', ].join("\n") end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(2).in_column(1) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'single line with trailing whitespace' do let(:code) { 'foo ' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(4) end it 'should remove the trailing whitespace' do expect(manifest).to eq('foo') end end context 'multiple lines with trailing whitespace' do let(:code) { "foo \nbar" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(4) end it 'should remove the trailing whitespace' do expect(manifest).to eq("foo\nbar") end end context 'line without code and trailing whitespace' do let(:code) do [ 'class foo {', ' ', '}', ].join("\n") end let(:fixed) do [ 'class foo {', '', '}', ].join("\n") end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_fixed(msg).on_line(2).in_column(1) end it 'should remove the trailing whitespace' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb0000644000004100000410000000073413611752231030331 0ustar www-datawww-datarequire 'spec_helper' describe '2sp_soft_tabs' do let(:msg) { 'two-space soft tabs not used' } context 'when a line is indented by 3 spaces' do let(:code) do <<-END file { 'foo': foo => bar, } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(2).in_column(1) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb0000644000004100000410000000200213611752231027476 0ustar www-datawww-datarequire 'spec_helper' describe 'hard_tabs' do let(:msg) { 'tab character found' } context 'with fix disabled' do context 'hard tabs indents' do let(:code) { "\tfoo => bar," } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(1).in_column(1) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'hard tabs indents' do let(:code) { "\tfoo => bar," } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(1) end it 'should convert the tab characters into spaces' do expect(manifest).to eq(' foo => bar,') end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/0000755000004100000410000000000013611752231023517 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb0000644000004100000410000000152413611752231033645 0ustar www-datawww-datarequire 'spec_helper' describe 'class_inherits_from_params_class' do let(:msg) { 'class inheriting from params class' } context 'parameterised class that inherits from a params class' do let(:code) do <<-END # commented class foo($bar = $name) inherits foo::params { } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(2).in_column(42) end end context 'class without parameters' do let(:code) do <<-END class myclass { if ( $::lsbdistcodename == 'squeeze' ) { #TODO } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/name_contains_uppercase_spec.rb0000644000004100000410000000334413611752231031747 0ustar www-datawww-datarequire 'spec_helper' describe 'names_containing_uppercase' do context 'defined type named FooBar' do let(:code) { 'define FooBar { }' } let(:path) { 'foobar/manifests/init.pp' } let(:class_msg) { "defined type 'FooBar' contains illegal uppercase" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(class_msg).on_line(1).in_column(8) end end context 'class named FooBar' do let(:code) { 'class FooBar { }' } let(:path) { 'foobar/manifests/init.pp' } let(:class_msg) { "class 'FooBar' contains illegal uppercase" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(class_msg).on_line(1).in_column(7) end end context 'class named Foo::BarFoo' do let(:code) { 'class Foo::BarFoo { }' } let(:path) { 'foo/manifests/barfoo.pp' } let(:class_msg) { "class 'Foo::BarFoo' contains illegal uppercase" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(class_msg).on_line(1).in_column(7) end context 'check fix -' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end let(:fixed) { code.downcase } it 'should create an error' do expect(problems).to contain_fixed(class_msg).on_line(1).in_column(7) end it 'should downcase the class name' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/arrow_on_right_operand_line_spec.rb0000644000004100000410000001026413611752231032623 0ustar www-datawww-datarequire 'spec_helper' describe 'arrow_on_right_operand_line' do msg = "arrow should be on the right operand's line" { 'chain' => '->', 'subscribe chain' => '~>' }.each do |name, operator| context "#{name} operator" do context 'both operands on same line' do let(:code) do <<-END Package['httpd'] #{operator} Service['httpd'] END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'arrow on the line of left operand' do let(:code) do <<-END Package['httpd'] #{operator} Service['httpd'] END end it 'should detect a problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(31) end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end let(:fixed) do <<-END.gsub(%r{^ {2}}, '') Package['httpd'] #{operator} Service['httpd'] END end it 'should fix the problem' do expect(problems).to contain_fixed(msg).on_line(1).in_column(31) end it 'should move the arrow to before the right operand' do expect(manifest).to eq(fixed) end end end context 'arrow on the line of right operand' do let(:code) do <<-END Package['httpd'] #{operator} Service['httpd'] END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'arrow on the line of left operand with comment in between' do let(:code) do <<-END Package['httpd'] #{operator} # a comment # another comment Service['httpd'] END end it 'should detect a problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(30) end context 'with fix enabled' do before(:each) do PuppetLint.configuration.fix = true end after(:each) do PuppetLint.configuration.fix = false end let(:fixed) do <<-END.gsub(%r{^ {2}}, '') Package['httpd'] # a comment # another comment #{operator} Service['httpd'] END end it 'should fix the problem' do expect(problems).to contain_fixed(msg).on_line(1).in_column(30) end it 'should move the arrow to before the right operand' do expect(manifest).to eq(fixed) end end end context 'arrow on the line of the left operand with a comment following the arrow' do let(:code) do <<-END Package['httpd'] #{operator} # something Service['httpd'] END end it 'should detect a problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(30) end context 'with fix enabled' do before(:each) do PuppetLint.configuration.fix = true end after(:each) do PuppetLint.configuration.fix = false end let(:fixed) do <<-END.gsub(%r{^ {2}}, '') Package['httpd'] # something #{operator} Service['httpd'] END end it 'should fix the problem' do expect(problems).to contain_fixed(msg).on_line(1).in_column(30) end it 'should move the arrow to before the right operand' do expect(manifest).to eq(fixed) end end end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb0000644000004100000410000000273113611752231031374 0ustar www-datawww-datarequire 'spec_helper' describe 'names_containing_dash' do let(:class_msg) { 'class name containing a dash' } let(:define_msg) { 'defined type name containing a dash' } context 'module named foo-bar' do let(:code) { 'class foo-bar { }' } let(:path) { 'foo-bar/manifests/init.pp' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(class_msg).on_line(1).in_column(7) end end context 'define named foo-bar' do let(:code) { 'define foo::foo-bar { }' } let(:path) { 'foo/manifests/foo-bar.pp' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(define_msg).on_line(1).in_column(8) end end context 'class named bar-foo' do let(:code) { 'class foo::bar-foo { }' } let(:path) { 'foo/manifests/bar-foo.pp' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(class_msg).on_line(1).in_column(7) end end context 'multiple classes' do let(:code) do <<-END class foo::bar_foo { } class foo::baz-foo { } END end it 'should create an error' do expect(problems).to contain_error(class_msg).on_line(2).in_column(15) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/code_on_top_scope_spec.rb0000644000004100000410000000142413611752231030540 0ustar www-datawww-datarequire 'spec_helper' describe 'code_on_top_scope' do describe 'comments outside class block' do let(:code) do <<-END # Baz class foo:bar { } END end its(:problems) { should be_empty } end describe 'new lines outside of class-define block' do let(:code) do <<-END class foo:bar { } END end its(:problems) { should be_empty } end describe 'code outside class block' do let(:code) do <<-END include('something') # Baz class foo:bar { } define whatever { } END end its(:problems) do should contain_warning('code outside of class or define block - include') should have(4).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb0000644000004100000410000000500313611752231030610 0ustar www-datawww-datarequire 'spec_helper' describe 'autoloader_layout' do context 'foo::bar in foo/manifests/bar.pp' do let(:code) { 'class foo::bar { }' } let(:path) { 'foo/manifests/bar.pp' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'foo::bar::baz in foo/manifests/bar/baz.pp' do let(:code) { 'define foo::bar::baz() { }' } let(:path) { 'foo/manifests/bar/baz.pp' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'foo in foo/manifests/init.pp' do let(:code) { 'class foo { }' } let(:path) { 'foo/manifests/init.pp' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'foo::bar in foo/manifests/init.pp' do let(:code) { 'class foo::bar { }' } let(:path) { 'foo/manifests/init.pp' } let(:msg) { 'foo::bar not in autoload module layout' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(1).in_column(7) end end context 'foo included in bar/manifests/init.pp' do let(:code) do <<-END class bar { class {'foo': someparam => 'somevalue', } } END end let(:path) { 'bar/manifests/init.pp' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'foo in puppet-foo/manifests/init.pp' do let(:code) { 'class foo { }' } let(:path) { 'puppet-foo/manifests/init.pp' } it 'should detect a single problem' do expect(problems).to have(1).problems end end context 'foo in puppet-foo/manifests/bar.pp with relative option' do before do PuppetLint.configuration.relative = true end after do PuppetLint.configuration.relative = false end let(:code) { 'class foo { }' } let(:path) { 'puppet-foo/manifests/bar.pp' } it 'should detect a single problem' do expect(problems).to have(1).problems end end context 'foo in puppet-foo/manifests/init.pp with relative option' do before do PuppetLint.configuration.relative = true end after do PuppetLint.configuration.relative = false end let(:code) { 'class foo { }' } let(:path) { 'puppet-foo/manifests/init.pp' } it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb0000644000004100000410000000715413611752231030240 0ustar www-datawww-datarequire 'spec_helper' describe 'parameter_order' do let(:msg) { 'optional parameter listed before required parameter' } %w[define class].each do |type| context "#{type} with attrs in order" do let(:code) { "#{type} foo($bar, $baz='gronk') { }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context "#{type} with parameter that calls a function" do let(:code) { "#{type} foo($bar=extlookup($name)) {}" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context "#{type} with attrs out of order" do let(:code) { "#{type} foo($bar='baz', $gronk) { }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end col = (type == 'class' ? 23 : 24) it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(col) end end context "#{type} parameter set to another variable" do let(:code) do <<-END #{type} foo($bar, $baz = $name, $gronk=$::fqdn) { } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context "#{type} parameter set to another variable with incorrect order" do let(:code) do <<-END #{type} foo($baz = $name, $bar, $gronk=$::fqdn) { } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end col = (type == 'class' ? 35 : 36) it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(col) end end context 'issue-101' do let(:code) do <<-END #{type} b ( $foo, $bar='', $baz={} ) { } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context "#{type} parameter w/a hash containing a variable and no optional parameters" do let(:code) do <<-END $var1 = 'test' #{type} test ( $entries = { '200 xxx' => { param1 => $var1, param2 => 'value2', param3 => 'value3', } }, $mandatory => undef, ) { } END end it { expect(problems).to have(0).problem } end context "#{type} parameter w/a hash containing a variable followed by an optional parameter" do let(:code) do <<-END $var1 = 'test' #{type} test ( $entries = { '200 xxx' => { param1 => $var1, param2 => 'value2', param3 => 'value3', } }, $optional, $mandatory => undef, ) { } END end it { expect(problems).to contain_warning(msg).on_line(11).in_column(13) } end context "#{type} parameter w/array containing a variable" do let(:code) do <<-END #{type} test ( $var1 = [$::hostname, 'host'], ) { } END end it { expect(problems).to have(0).problem } end context "#{type} parameter with Optional data type" do let(:code) do <<-END #{type} test( String $test = 'value', Optional[String] $optional, ) { } END end it { expect(problems).to have(0).problems } end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb0000644000004100000410000000116513611752231032473 0ustar www-datawww-datarequire 'spec_helper' describe 'right_to_left_relationship' do let(:msg) { 'right-to-left (<-) relationship' } context 'chain 2 resources left to right' do let(:code) { 'Class[foo] -> Class[bar]' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'chain 2 resources right to left' do let(:code) { 'Class[foo] <- Class[bar]' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(12) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb0000644000004100000410000001640113611752231030036 0ustar www-datawww-datarequire 'spec_helper' describe 'variable_scope' do let(:msg) { 'top-scope variable being used without an explicit namespace' } context 'class with no variables declared accessing top scope' do let(:code) do <<-END class foo { $bar = $baz } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(2).in_column(18) end end context 'class with no variables declared accessing top scope explicitly' do let(:code) do <<-END class foo { $bar = $::baz } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class with no variables declared accessing local array index' do let(:code) do <<-END class foo { $bar = ['one', 'two', 'three'] $baz = $bar[1] } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class with no variables declared accessing local hash key' do let(:code) do <<-END class foo { $bar = { 'one' => 1, 'two' => 2, 'three' => 3, } $baz = $bar['two'] } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class with variables declared accessing local scope' do let(:code) do <<-END class foo { $bar = 1 $baz = $bar } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class with parameters accessing local scope' do let(:code) do <<-END class foo($bar='UNSET') { $baz = $bar } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'defined type with no variables declared accessing top scope' do let(:code) do <<-END define foo() { $bar = $fqdn } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(2).in_column(18) end end context 'defined type with no variables declared accessing top scope explicitly' do let(:code) do <<-END define foo() { $bar = $::fqdn } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context '$name should be auto defined' do let(:code) do <<-END define foo() { $bar = $name $baz = $title $gronk = $module_name $meep = $1 } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'define with required parameter' do let(:code) do <<-END define tomcat::base ( $max_perm_gen, $owner = hiera('app_user'), $system_properties = {}, ) { } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'future parser blocks' do let(:code) do <<-END class foo() { $foo = {1=>2, 3=>4} $foo.each |$a, $b| { $a # should cause no warnings $c # top-scope variable warning } $b # top-scope variable warning $foo.each |$d| { $d[1] # should cause no warnings } } END end it 'should only detect two problems' do expect(problems).to have(2).problem end it 'should create two warnings' do expect(problems).to contain_warning(msg).on_line(7).in_column(11) expect(problems).to contain_warning(msg).on_line(5).in_column(13) end end context 'nested future parser blocks' do let(:code) do <<-END class foo() { $foo = {1=>2, 3=>4} $bar = [1, 2, 3] $foo.each |$k ,$v| { $k $v $x # top-scope warning $bar.each |$x| { $k $v $x $p # top-scope warning } $x # top-scope warning } } END end it 'should only detect three problems' do expect(problems).to have(3).problem end it 'should create three warnings' do expect(problems).to contain_warning(msg).on_line(7).in_column(13) expect(problems).to contain_warning(msg).on_line(12).in_column(15) expect(problems).to contain_warning(msg).on_line(14).in_column(13) end end %w[alias audit before loglevel noop notify require schedule stage subscribe tag].each do |metaparam| context "referencing #{metaparam} metaparam value as a variable" do let(:code) do <<-END class foo() { $#{metaparam} } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end context 'support the use of facts and trusted facts for Puppet 3.5 onwards' do let(:code) do <<-END class foo() { if $facts['osfamily'] == 'redhat' or $trusted['osfamily'] == 'redhat' { $redhat = true } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multiple left hand variable assign' do let(:code) do <<-END class test { [$foo, $bar] = something() } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'nested variable assignment' do let(:code) do <<-END class test { [$foo, [[$bar, $baz], $qux]] = something() } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'function calls inside string interpolation' do let(:code) do <<-END class test { "${split('1,2,3', ',')}" # split is a function "${lookup('foo::bar')}" # lookup is a function } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'variables in string interpolation' do let(:code) do <<-END class test { "${foo.split(',')}" # foo is a top-scope variable "${::bar.split(',')}" } END end it 'should only detect one problem' do expect(problems).to have(1).problems end it 'should create one warning' do expect(problems).to contain_warning(msg).on_line(2).in_column(14) end end context 'assigning regex with multiple alternations to variable' do let(:code) do <<-END class gh::issue859 { $regex = /5|6|7/ } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb0000644000004100000410000000331013611752231032247 0ustar www-datawww-datarequire 'spec_helper' describe 'nested_classes_or_defines' do let(:class_msg) { 'class defined inside a class' } let(:define_msg) { 'defined type defined inside a class' } context 'class on its own' do let(:code) { 'class foo { }' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class inside a class' do let(:code) do <<-END class foo { class bar { } } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(class_msg).on_line(2).in_column(11) end end context 'instantiating a parametised class inside a class' do let(:code) do <<-END class bar { class { 'foo': bar => 'foobar' } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'instantiating a parametised class inside a define' do let(:code) do <<-END define bar() { class { 'foo': bar => 'foobar' } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'define inside a class' do let(:code) do <<-END class foo { define bar() { } } END end it 'should only detect a single problem' do expect(problems).to have(1).problems end it 'should create a warning' do expect(problems).to contain_warning(define_msg).on_line(2).in_column(11) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb0000644000004100000410000000162513611752231032460 0ustar www-datawww-datarequire 'spec_helper' describe 'inherits_across_namespaces' do let(:msg) { 'class inherits across module namespaces' } context 'class inheriting from parent in same module namespace' do let(:code) { 'class foo::bar inherits foo { }' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class inheriting from sister in same module namespace' do let(:code) { 'class foo::bar inherits foo::baz { }' } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'class inheriting from another module namespace' do let(:code) { 'class foo::bar inherits baz { }' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(25) end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/0000755000004100000410000000000013611752231024074 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb0000644000004100000410000000466413611752231030762 0ustar www-datawww-datarequire 'spec_helper' describe 'duplicate_params' do let(:msg) { 'duplicate parameter found in resource' } context 'resource with duplicate parameters' do let(:code) do <<-END file { '/tmp/foo': ensure => present, foo => bar, baz => gronk, foo => meh, } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(5).in_column(11) end end context 'bug #145: resource with a hash and no duplicate parameters' do let(:code) do <<-END class {'fooname': hashes => [ { foo => 'bar01',}, { foo => 'bar02', }, ], } END end it 'should not detect any errors' do expect(problems).to have(0).problems end end context 'bug #145: resource with a hash and duplicate parameters in subhash' do let(:code) do <<-END class {'fooname': hashes => [ { foo => 'bar01', foo => 'bar02', }, ], } END end it 'should only detect a single error' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(4).in_column(15) end end context 'bug #145: resource with a hash and duplicate parameters in parent type' do let(:code) do <<-END class {'fooname': hashes => [ { foo => 'bar01', }, { foo => 'bar02', }, ], something => { hash => 'mini', }, hashes => 'dupe', } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create an error' do expect(problems).to contain_error(msg).on_line(7).in_column(11) end end describe 'bug #145: more hash tests and no duplicate parameters' do let(:code) do <<-END class test { $foo = { param => 'value', } $bar = { param => 'bar', } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'colon as last token in file' do let(:code) { '}:' } it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb0000644000004100000410000001743213611752231027365 0ustar www-datawww-datarequire 'spec_helper' describe 'file_mode' do let(:msg) { 'mode should be represented as a 4 digit octal value or symbolic mode' } context 'with fix disabled' do context '3 digit file mode' do let(:code) { "file { 'foo': mode => '777' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(23) end end context '4 digit file mode' do let(:code) { "file { 'foo': mode => '0777' }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'file mode as a variable' do let(:code) { "file { 'foo': mode => $file_mode }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'symbolic file mode' do let(:code) { "file { 'foo': mode => 'u=rw,og=r' }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'file mode undef unquoted' do let(:code) { "file { 'foo': mode => undef }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'file mode undef quoted' do let(:code) { "file { 'foo': mode => 'undef' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(23) end end context 'mode as audit value' do let(:code) { "file { '/etc/passwd': audit => [ owner, mode ], }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context '3 digit concat mode' do let(:code) { "concat { 'foo': mode => '777' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(25) end end context '4 digit concat mode' do let(:code) { "concat { 'foo': mode => '0777' }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'concat mode as a variable' do let(:code) { "concat { 'foo': mode => $concat_mode }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'symbolic concat mode' do let(:code) { "concat { 'foo': mode => 'u=rw,og=r' }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'concat mode undef unquoted' do let(:code) { "concat { 'foo': mode => undef }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'concat mode undef quoted' do let(:code) { "concat { 'foo': mode => 'undef' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(25) end end context 'mode as audit value' do let(:code) { "concat { '/etc/passwd': audit => [ owner, mode ], }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'mode as a function return value' do let(:code) { "file { 'foo': mode => lookup('bar'), }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multi body file bad modes selector' do let(:code) do <<-END file { '/tmp/foo1': ensure => $foo ? { default => absent }, mode => 644; '/tmp/foo2': mode => 644; '/tmp/foo3': mode => 644; } END end it 'should detect 3 problems' do expect(problems).to have(3).problems end it 'should create three warnings' do expect(problems).to contain_warning(sprintf(msg)).on_line(4).in_column(23) expect(problems).to contain_warning(sprintf(msg)).on_line(6).in_column(23) expect(problems).to contain_warning(sprintf(msg)).on_line(8).in_column(23) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context '3 digit file mode' do let(:code) { "file { 'foo': mode => '777' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(23) end it 'should zero pad the file mode' do expect(manifest).to eq("file { 'foo': mode => '0777' }") end end context 'file mode undef quoted' do let(:code) { "file { 'foo': mode => 'undef' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(23) end it 'should not modify the original manifest' do expect(manifest).to eq(code) end end context '3 digit concat mode' do let(:code) { "concat { 'foo': mode => '777' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(25) end it 'should zero pad the concat mode' do expect(manifest).to eq("concat { 'foo': mode => '0777' }") end end context 'concat mode undef quoted' do let(:code) { "concat { 'foo': mode => 'undef' }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(25) end it 'should not modify the original manifest' do expect(manifest).to eq(code) end end context 'mode as a function return value' do let(:code) { "file { 'foo': mode => lookup('bar'), }" } it 'should not detect any problems' do expect(problems).to have(0).problems end it 'should not change the manifest' do expect(manifest).to eq(code) end end context 'multi body file bad modes selector' do let(:code) do <<-END file { '/tmp/foo1': ensure => $foo ? { default => absent }, mode => 644; '/tmp/foo2': mode => 644; '/tmp/foo3': mode => 644; } END end let(:fixed) do <<-END file { '/tmp/foo1': ensure => $foo ? { default => absent }, mode => '0644'; '/tmp/foo2': mode => '0644'; '/tmp/foo3': mode => '0644'; } END end it 'should detect 3 problems' do expect(problems).to have(3).problems end it 'should fix 3 problems' do expect(problems).to contain_fixed(msg).on_line(4).in_column(23) expect(problems).to contain_fixed(msg).on_line(6).in_column(23) expect(problems).to contain_fixed(msg).on_line(8).in_column(23) end it 'should zero pad the file modes and change them to strings' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb0000644000004100000410000001272613611752231031333 0ustar www-datawww-datarequire 'spec_helper' describe 'ensure_first_param' do let(:msg) { "ensure found on line but it's not the first attribute" } context 'with fix disabled' do context 'ensure as only attr in a single line resource' do let(:code) { "file { 'foo': ensure => present }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure as only attr in a multi line resource' do let(:code) do <<-END file { 'foo': ensure => present, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure as second attr in a multi line resource' do let(:code) do <<-END file { 'foo': mode => '0000', ensure => present, } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(3).in_column(13) end end context 'ensure as first attr in a multi line resource' do let(:code) do <<-END file { 'foo': ensure => present, mode => '0000', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure as a hash key in classes does not need to be first' do let(:code) do <<-END class thing { class { 'thang': stuff => { 'stuffing' => { ensure => 'present', blah => 'bleah', } }, } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure in nested hash' do let(:code) do <<-END foo::bar { 'bar': opts => { ensure => present, }, }, END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'ensure as only attr in a single line resource' do let(:code) { "file { 'foo': ensure => present }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure as only attr in a multi line resource' do let(:code) do <<-END file { 'foo': ensure => present, } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure as second attr in a multi line resource' do let(:code) do <<-END file { 'foo': mode => '0000', ensure => present, } END end let(:fixed) do <<-END file { 'foo': ensure => present, mode => '0000', } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_fixed(msg).on_line(3).in_column(13) end it 'should make ensure the first attr' do expect(manifest).to eq(fixed) end end context 'ensure as first attr in a multi line resource' do let(:code) do <<-END file { 'foo': ensure => present, mode => '0000', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure as a hash key in classes does not need to be first' do let(:code) do <<-END class thing { class { 'thang': stuff => { 'stuffing' => { ensure => 'present', blah => 'bleah', } }, } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'ensure is a selector' do let(:code) do <<-END file { 'foo': mode => '0640', ensure => $::operatingsystem ? { 'redhat' => absent, default => $::phase_of_the_moon ? { 'full' => absent, default => present, }, }, } END end let(:fixed) do <<-END file { 'foo': ensure => $::operatingsystem ? { 'redhat' => absent, default => $::phase_of_the_moon ? { 'full' => absent, default => present, }, }, mode => '0640', } END end it 'should detect a problem' do expect(problems).to have(1).problem end it 'should fix the problem' do expect(problems).to contain_fixed(msg).on_line(3).in_column(13) end it 'should move the whole ensure parameter to the top' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb0000644000004100000410000001247113611752231032414 0ustar www-datawww-datarequire 'spec_helper' describe 'unquoted_resource_title' do let(:msg) { 'unquoted resource title' } context 'with fix disabled' do context 'quoted resource title on single line resource' do let(:code) { "file { 'foo': }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'unquoted resource title on single line resource' do let(:code) { 'file { foo: }' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(8) end end context 'quoted resource title on multi line resource' do let(:code) do <<-END file { 'foo': } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'unquoted resource title on multi line resource' do let(:code) do <<-END file { foo: } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(18) end end context 'condensed resources with quoted titles' do let(:code) do <<-END file { 'foo': ; 'bar': ; } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'condensed resources with an unquoted title' do let(:code) do <<-END file { 'foo': ; bar: ; } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(3).in_column(13) end end context 'single line resource with an array of titles (all quoted)' do let(:code) { "file { ['foo', 'bar']: }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'resource inside a case statement' do let(:code) do <<-END case $ensure { 'absent': { file { "some_file_${name}": ensure => absent, } } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'issue #116' do let(:code) do <<-END $config_file_init = $::operatingsystem ? { /(?i:Debian|Ubuntu|Mint)/ => '/etc/default/foo', default => '/etc/sysconfig/foo', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'case statement' do let(:code) do <<-END case $operatingsystem { centos: { $version = '1.2.3' } solaris: { $version = '3.2.1' } default: { fail("Module ${module_name} is not supported on ${operatingsystem}") } } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'unquoted resource title on single line resource' do let(:code) { 'file { foo: }' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(8) end it 'should single quote the resource title' do expect(manifest).to eq("file { 'foo': }") end end context 'unquoted resource title on multi line resource' do let(:code) do <<-END file { foo: } END end let(:fixed) do <<-END file { 'foo': } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(18) end it 'should single quote the resource title' do expect(manifest).to eq(fixed) end end context 'condensed resources with an unquoted title' do let(:code) do <<-END file { 'foo': ; bar: ; } END end let(:fixed) do <<-END file { 'foo': ; 'bar': ; } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(3).in_column(13) end it 'should single quote the resource title' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb0000644000004100000410000001031413611752231031301 0ustar www-datawww-datarequire 'spec_helper' describe 'unquoted_file_mode' do let(:msg) { 'unquoted file mode' } context 'with fix disabled' do context '4 digit unquoted file mode' do let(:code) { "file { 'foo': mode => 0777 }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(23) end end context '4 digit unquoted file mode' do let(:code) { "concat { 'foo': mode => 0777 }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(25) end end context 'file mode from a function rvalue' do let(:code) { "file { 'foo': mode => lookup('bar'), }" } it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'multi body file bad modes selector' do let(:code) do <<-END file { '/tmp/foo1': ensure => $foo ? { default => absent }, mode => 644; '/tmp/foo2': mode => 644; '/tmp/foo3': mode => 644; } END end it 'should detect 3 problems' do expect(problems).to have(3).problems end it 'should create three warnings' do expect(problems).to contain_warning(sprintf(msg)).on_line(4).in_column(23) expect(problems).to contain_warning(sprintf(msg)).on_line(6).in_column(23) expect(problems).to contain_warning(sprintf(msg)).on_line(8).in_column(23) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context '4 digit unquoted file mode w/fix' do let(:code) { "file { 'foo': mode => 0777 }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(23) end it 'should single quote the file mode' do expect(manifest).to eq("file { 'foo': mode => '0777' }") end end context '4 digit unquoted file mode w/fix' do let(:code) { "concat { 'foo': mode => 0777 }" } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the manifest' do expect(problems).to contain_fixed(msg).on_line(1).in_column(25) end it 'should single quote the file mode' do expect(manifest).to eq("concat { 'foo': mode => '0777' }") end end context 'file mode from a function rvalue' do let(:code) { "file { 'foo': mode => lookup('bar'), }" } it 'should not detect any problems' do expect(problems).to have(0).problems end it 'should not change the manifest' do expect(manifest).to eq(code) end end context 'multi body file bad modes selector' do let(:code) do <<-END file { '/tmp/foo1': ensure => $foo ? { default => absent }, mode => 644; '/tmp/foo2': mode => 644; '/tmp/foo3': mode => 644; } END end let(:fixed) do <<-END file { '/tmp/foo1': ensure => $foo ? { default => absent }, mode => '644'; '/tmp/foo2': mode => '644'; '/tmp/foo3': mode => '644'; } END end it 'should detect 3 problems' do expect(problems).to have(3).problems end it 'should fix 3 problems' do expect(problems).to contain_fixed(msg).on_line(4).in_column(23) expect(problems).to contain_fixed(msg).on_line(6).in_column(23) expect(problems).to contain_fixed(msg).on_line(8).in_column(23) end it 'should quote the file modes' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb0000644000004100000410000000431413611752231032732 0ustar www-datawww-datarequire 'spec_helper' describe 'ensure_not_symlink_target' do let(:msg) { 'symlink target specified in ensure attr' } context 'with fix disabled' do context 'file resource creating a symlink with seperate target attr' do let(:code) do <<-END file { 'foo': ensure => link, target => '/foo/bar', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end end context 'file resource creating a symlink with target specified in ensure' do let(:code) do <<-END file { 'foo': ensure => '/foo/bar', } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(msg).on_line(2).in_column(23) end end end context 'with fix enabled' do before do PuppetLint.configuration.fix = true end after do PuppetLint.configuration.fix = false end context 'file resource creating a symlink with seperate target attr' do let(:code) do <<-END file { 'foo': ensure => link, target => '/foo/bar', } END end it 'should not detect any problems' do expect(problems).to have(0).problems end it 'should not modify the manifest' do expect(manifest).to eq(code) end end context 'file resource creating a symlink with target specified in ensure' do let(:code) do <<-END file { 'foo': ensure => '/foo/bar', } END end let(:fixed) do <<-END file { 'foo': ensure => symlink, target => '/foo/bar', } END end it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should fix the problem' do expect(problems).to contain_fixed(msg).on_line(2).in_column(23) end it 'should create a new target param' do expect(manifest).to eq(fixed) end end end end puppet-lint-2.4.2/spec/puppet-lint/plugins/check_documentation/0000755000004100000410000000000013611752231024733 5ustar www-datawww-datapuppet-lint-2.4.2/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb0000644000004100000410000000226613611752231031151 0ustar www-datawww-datarequire 'spec_helper' describe 'documentation' do let(:class_msg) { 'class not documented' } let(:define_msg) { 'defined type not documented' } describe 'undocumented class' do let(:code) { 'class test {}' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(class_msg).on_line(1).in_column(1) end end describe 'documented class' do let(:code) do <<-END # foo class test {} END end it 'should not detect any problems' do expect(problems).to have(0).problems end end describe 'undocumented defined type' do let(:code) { 'define test {}' } it 'should only detect a single problem' do expect(problems).to have(1).problem end it 'should create a warning' do expect(problems).to contain_warning(define_msg).on_line(1).in_column(1) end end describe 'documented defined type' do let(:code) do <<-END # foo define test {} END end it 'should not detect any problems' do expect(problems).to have(0).problems end end end puppet-lint-2.4.2/spec/puppet-lint_spec.rb0000644000004100000410000000055313611752231020606 0ustar www-datawww-datarequire 'spec_helper' describe PuppetLint do subject { PuppetLint.new } it 'should accept manifests as a string' do subject.code = 'class foo { }' expect(subject.code).to_not be_nil end it 'should return empty manifest when empty one given as the input' do subject.code = '' subject.run expect(subject.manifest).to eq('') end end puppet-lint-2.4.2/spec/spec_helper.rb0000644000004100000410000000710013611752231017577 0ustar www-datawww-datarequire 'simplecov' SimpleCov.start do add_filter('/spec/') add_filter('/vendor/') add_group('Checks', 'lib/puppet-lint/plugins') end require 'puppet-lint' require 'rspec/its' require 'rspec/collection_matchers' begin require 'rspec/json_expectations' rescue LoadError, SyntaxError puts 'rspec/json_expectations is not available' end module RSpec module LintExampleGroup class HaveProblem def initialize(method, message) @expected_problem = { :kind => method.to_s.gsub(%r{\Acontain_}, '').to_sym, :message => message, } @description = ["contain a #{@expected_problem[:kind]}"] end def on_line(line) @expected_problem[:line] = line @description << "on line #{line}" self end def in_column(column) @expected_problem[:column] = column @description << "starting in column #{column}" self end def with_reason(reason) @expected_problem[:reason] = reason @description << "with reason '#{reason}'" self end def matches?(problems) @problems = problems problems.any? do |problem| @expected_problem.all? do |key, value| problem.key?(key) && problem[key] == value end end end def description @description.join(' ') end def check_attr(attr, prefix) return if @expected_problem[attr] == @problems.first[attr] expected = @expected_problem[attr].inspect actual = @problems.first[attr].inspect "#{prefix} #{expected}, but it was #{actual}" end def failure_message case @problems.length when 0 'expected that the check would create a problem but it did not' when 1 messages = ['expected that the problem'] messages << check_attr(:kind, 'would be of kind') messages << check_attr(:message, 'would have the message') messages << check_attr(:line, 'would be on line') messages << check_attr(:column, 'would start on column') messages << check_attr(:reason, 'would have the reason') messages.compact.join("\n ") else [ 'expected that the check would create', PP.pp(@expected_problem, '').strip, 'but it instead created', PP.pp(@problems, ''), ].join("\n") end end def failure_message_when_negated 'expected that the check would not create the problem, but it did' end end def method_missing(method, *args, &block) return HaveProblem.new(method, args.first) if method.to_s.start_with?('contain_') super end def respond_to_missing?(method, *) method.to_s.start_with?('contain_') || super end def problems subject.problems end def manifest subject.manifest end def subject klass = PuppetLint::Checks.new filepath = respond_to?(:path) ? path : '' klass.load_data(filepath, code) check_name = self.class.top_level_description.to_sym check = PuppetLint.configuration.check_object[check_name].new klass.problems = check.run klass.problems = check.fix_problems if PuppetLint.configuration.fix klass end end end RSpec.configure do |config| config.mock_framework = :rspec config.include( RSpec::LintExampleGroup, :type => :lint, :file_path => Regexp.compile(%w[spec puppet-lint plugins].join('[\\\/]')) ) config.expect_with(:rspec) do |c| c.syntax = :expect end end puppet-lint-2.4.2/CHANGELOG.md0000644000004100000410000027503513611752231015656 0ustar www-datawww-data# Changelog ## [2.4.2](https://github.com/rodjek/puppet-lint/tree/2.4.2) (2019-10-31) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.4.1...2.4.2) **Fixed bugs:** - `ERROR: Syntax error \(unterminated string\)` with 2.4.1 [\#899](https://github.com/rodjek/puppet-lint/issues/899) - Double quoted string containing variable named "node" mis-tokenized [\#897](https://github.com/rodjek/puppet-lint/issues/897) - 2.4.1 says Syntax error, but code runs fine [\#891](https://github.com/rodjek/puppet-lint/issues/891) - Error with regex variable with multiple `|`s. [\#859](https://github.com/rodjek/puppet-lint/issues/859) **Closed issues:** - WARNING: double quoted string containing no variables [\#895](https://github.com/rodjek/puppet-lint/issues/895) **Merged pull requests:** - Fix regression in tokenization in double-quoted strings [\#898](https://github.com/rodjek/puppet-lint/pull/898) ([seanmil](https://github.com/seanmil)) - Speed up calculation of resource indexes [\#893](https://github.com/rodjek/puppet-lint/pull/893) ([usev6](https://github.com/usev6)) - Search end of string before assuming escaped quote [\#892](https://github.com/rodjek/puppet-lint/pull/892) ([usev6](https://github.com/usev6)) - Allow parsing of regexes as rvalues [\#882](https://github.com/rodjek/puppet-lint/pull/882) ([usev6](https://github.com/usev6)) ## [2.4.1](https://github.com/rodjek/puppet-lint/tree/2.4.1) (2019-10-09) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.4.0...2.4.1) **Fixed bugs:** - Puppet-lint 2.4.0 - ERROR: Syntax error on line x [\#887](https://github.com/rodjek/puppet-lint/issues/887) - Puppet-lint 2.4.0 throws misleading warning on double-quoted strings with escaped variables [\#886](https://github.com/rodjek/puppet-lint/issues/886) - Breaks after 2.4.0 upgrade [\#885](https://github.com/rodjek/puppet-lint/issues/885) **Merged pull requests:** - Fix escaped ${} enclosure handling when slurping double quoted strings [\#889](https://github.com/rodjek/puppet-lint/pull/889) ([rodjek](https://github.com/rodjek)) - Fix non-indented heredoc parsing [\#888](https://github.com/rodjek/puppet-lint/pull/888) ([rodjek](https://github.com/rodjek)) ## [2.4.0](https://github.com/rodjek/puppet-lint/tree/2.4.0) (2019-10-08) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.6...2.4.0) **Fixed bugs:** - Command line options do not override options from config files [\#879](https://github.com/rodjek/puppet-lint/issues/879) - Fix for variables\_not\_enclosed incorrectly handles variables followed by a dash [\#836](https://github.com/rodjek/puppet-lint/issues/836) - Syntax error on Pattern data type [\#833](https://github.com/rodjek/puppet-lint/issues/833) - Error with puppet-lint --fix: NoMethodError: undefined method `next\_token' for nil:NilClass [\#831](https://github.com/rodjek/puppet-lint/issues/831) - TypeError: no implicit conversion of nil into String [\#830](https://github.com/rodjek/puppet-lint/issues/830) - Selector with 'default' case disables check for missing default in outer case statement [\#829](https://github.com/rodjek/puppet-lint/issues/829) - undefined method `next\_token' for nil:NilClass [\#824](https://github.com/rodjek/puppet-lint/issues/824) - NoMethodError: undefined method `next\_token' for nil:NilClass [\#790](https://github.com/rodjek/puppet-lint/issues/790) - Puppet-lint --fix silently removes necessary $ inside double quoted strings [\#773](https://github.com/rodjek/puppet-lint/issues/773) - It looks like puppet-lint has encountered an error that it doesn't know how to handle [\#768](https://github.com/rodjek/puppet-lint/issues/768) - puppet-lint lexer string interpolation needs to be updated to match PUP-5887 changes [\#747](https://github.com/rodjek/puppet-lint/issues/747) - Syntax error causes 'Whoops!' [\#740](https://github.com/rodjek/puppet-lint/issues/740) - "quoted boolean value found" in hash value should not raise a warning. [\#474](https://github.com/rodjek/puppet-lint/issues/474) **Closed issues:** - Error when running puppet-lint [\#862](https://github.com/rodjek/puppet-lint/issues/862) - puppet-lint crashes with mispelled namespace seperators [\#853](https://github.com/rodjek/puppet-lint/issues/853) - NoMethodError: undefined method `prev\_token' for nil:NilClass [\#845](https://github.com/rodjek/puppet-lint/issues/845) - Lint incorrectly errors on quoted bool [\#844](https://github.com/rodjek/puppet-lint/issues/844) - Type\[\]\] raises NoMethodError [\#843](https://github.com/rodjek/puppet-lint/issues/843) - Whoops! It looks like puppet-lint has encountered an error that it doesn't know how to handle. [\#842](https://github.com/rodjek/puppet-lint/issues/842) - Whoops! It looks like puppet-lint has encountered an error that it doesn't [\#838](https://github.com/rodjek/puppet-lint/issues/838) - Incorrectly wrapped hash variable inside double quotes [\#826](https://github.com/rodjek/puppet-lint/issues/826) - Test puppet-lint against Ruby 2.5.x [\#818](https://github.com/rodjek/puppet-lint/issues/818) - nested ensure misdetected as not coming first. [\#410](https://github.com/rodjek/puppet-lint/issues/410) **Merged pull requests:** - Handle unenclosed variables followed by dashes when fixing [\#881](https://github.com/rodjek/puppet-lint/pull/881) ([rodjek](https://github.com/rodjek)) - Let command line args override config from files [\#880](https://github.com/rodjek/puppet-lint/pull/880) ([usev6](https://github.com/usev6)) - Ignore hash keys when checking resource parameter order [\#877](https://github.com/rodjek/puppet-lint/pull/877) ([rodjek](https://github.com/rodjek)) - Only look for 'default' at first level of 'case' statement [\#876](https://github.com/rodjek/puppet-lint/pull/876) ([usev6](https://github.com/usev6)) - Report syntax error on unbalanced braces [\#875](https://github.com/rodjek/puppet-lint/pull/875) ([rodjek](https://github.com/rodjek)) - Include hash/array references when enclosing variables [\#874](https://github.com/rodjek/puppet-lint/pull/874) ([rodjek](https://github.com/rodjek)) - Disable quoted\_booleans check by default [\#873](https://github.com/rodjek/puppet-lint/pull/873) ([rodjek](https://github.com/rodjek)) - Test against Ruby 2.5 & 2.6 [\#872](https://github.com/rodjek/puppet-lint/pull/872) ([rodjek](https://github.com/rodjek)) - README - Add GitHub Actions action [\#868](https://github.com/rodjek/puppet-lint/pull/868) ([ScottBrenner](https://github.com/ScottBrenner)) - Update TravisCI config to use trusty image [\#867](https://github.com/rodjek/puppet-lint/pull/867) ([rodjek](https://github.com/rodjek)) - Use the default travis rubygems & bundler [\#860](https://github.com/rodjek/puppet-lint/pull/860) ([rodjek](https://github.com/rodjek)) - Add `Sensitive` to the list of KNOWN\_TOKEN TYPES [\#858](https://github.com/rodjek/puppet-lint/pull/858) ([alexjfisher](https://github.com/alexjfisher)) - Avoid internal error for typoed namespace [\#855](https://github.com/rodjek/puppet-lint/pull/855) ([usev6](https://github.com/usev6)) - Use lookahead assertion for matching function name [\#854](https://github.com/rodjek/puppet-lint/pull/854) ([usev6](https://github.com/usev6)) - Resource: fix nested ensure error. [\#848](https://github.com/rodjek/puppet-lint/pull/848) ([keur](https://github.com/keur)) - Rewrite double quoted string handling for nested interpolation [\#846](https://github.com/rodjek/puppet-lint/pull/846) ([rodjek](https://github.com/rodjek)) - Allow for spaces in the heredoc tag [\#841](https://github.com/rodjek/puppet-lint/pull/841) ([jarretlavallee](https://github.com/jarretlavallee)) - Recognizes multiline regexes [\#835](https://github.com/rodjek/puppet-lint/pull/835) ([jcbollinger](https://github.com/jcbollinger)) ## [2.3.6](https://github.com/rodjek/puppet-lint/tree/2.3.6) (2018-07-09) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.5...2.3.6) **Fixed bugs:** - --fix does not work with require arrows in certain situations [\#799](https://github.com/rodjek/puppet-lint/issues/799) - Error with --fix when no whitespace before hashrocket in resource attribute list [\#798](https://github.com/rodjek/puppet-lint/issues/798) - puppet-lint --fix strips comments when fixing arrow\_on\_right\_operand\_line [\#792](https://github.com/rodjek/puppet-lint/issues/792) - Crash report, reason unclear [\#781](https://github.com/rodjek/puppet-lint/issues/781) - crash in fix mode with multiple trailing arrows [\#776](https://github.com/rodjek/puppet-lint/issues/776) - Error negative argument if opening brace on the same line and following element longer [\#771](https://github.com/rodjek/puppet-lint/issues/771) - ArgumentError: negative argument [\#723](https://github.com/rodjek/puppet-lint/issues/723) **Merged pull requests:** - \(\#771\) Handle arrow alignment when arrow column \< opening brace column... [\#819](https://github.com/rodjek/puppet-lint/pull/819) ([rodjek](https://github.com/rodjek)) - Less aggressive fix method for arrow\_on\_right\_operand\_line [\#817](https://github.com/rodjek/puppet-lint/pull/817) ([rodjek](https://github.com/rodjek)) - Check if token still exists before fixing trailing\_whitespace [\#816](https://github.com/rodjek/puppet-lint/pull/816) ([rodjek](https://github.com/rodjek)) - Run all the checks before fixing problems [\#815](https://github.com/rodjek/puppet-lint/pull/815) ([rodjek](https://github.com/rodjek)) ## [2.3.5](https://github.com/rodjek/puppet-lint/tree/2.3.5) (2018-03-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.4...2.3.5) **Fixed bugs:** - v2.3.4 breakage - 'wrong number of arguments' when using Rake task [\#812](https://github.com/rodjek/puppet-lint/issues/812) **Merged pull requests:** - Make PuppetLint::OptParser.build argument optional [\#813](https://github.com/rodjek/puppet-lint/pull/813) ([rodjek](https://github.com/rodjek)) ## [2.3.4](https://github.com/rodjek/puppet-lint/tree/2.3.4) (2018-03-26) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.3...2.3.4) **Implemented enhancements:** - Allow ignoring default configurations files on the command line [\#787](https://github.com/rodjek/puppet-lint/issues/787) - Implement --list-checks feature, to list the names of all available checks from the cli. [\#804](https://github.com/rodjek/puppet-lint/pull/804) ([xraystyle](https://github.com/xraystyle)) - Option to disable loading default configurations files [\#789](https://github.com/rodjek/puppet-lint/pull/789) ([dioni21](https://github.com/dioni21)) - Allow passing ignore\_paths from cli [\#783](https://github.com/rodjek/puppet-lint/pull/783) ([keymone](https://github.com/keymone)) **Fixed bugs:** - Bad value for range [\#801](https://github.com/rodjek/puppet-lint/issues/801) - puppet-lint doesn't handle CRLFs very well [\#778](https://github.com/rodjek/puppet-lint/issues/778) - Configuration's ignore\_paths is not respected [\#774](https://github.com/rodjek/puppet-lint/issues/774) - Error when including class and missing a colon [\#507](https://github.com/rodjek/puppet-lint/issues/507) **Merged pull requests:** - Handle single colon in resource name syntax error [\#809](https://github.com/rodjek/puppet-lint/pull/809) ([rodjek](https://github.com/rodjek)) - \(\#778\) Don't include line ending in single line comment token values [\#782](https://github.com/rodjek/puppet-lint/pull/782) ([rodjek](https://github.com/rodjek)) - Fix setting ignore\_paths in Rake task [\#777](https://github.com/rodjek/puppet-lint/pull/777) ([alzabo](https://github.com/alzabo)) - Add support for passing backslash separated paths to puppet-lint [\#769](https://github.com/rodjek/puppet-lint/pull/769) ([rodjek](https://github.com/rodjek)) ## [2.3.3](https://github.com/rodjek/puppet-lint/tree/2.3.3) (2017-09-28) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.2...2.3.3) **Closed issues:** - 2.3.2 - Rakefile's ignore\_paths not respected [\#760](https://github.com/rodjek/puppet-lint/issues/760) - 2.3.1 - Puppet lint fails with 1.8.7-p371 and Puppet 3.8.0 [\#759](https://github.com/rodjek/puppet-lint/issues/759) - 2.3.1: puppet-lint does not show errors/warnings --error-level option. [\#756](https://github.com/rodjek/puppet-lint/issues/756) **Merged pull requests:** - Add some basic acceptance tests [\#764](https://github.com/rodjek/puppet-lint/pull/764) ([rodjek](https://github.com/rodjek)) - Restore Ruby 1.8.7 support [\#763](https://github.com/rodjek/puppet-lint/pull/763) ([rodjek](https://github.com/rodjek)) - Don't override ignore\_paths set in rake task with default value [\#762](https://github.com/rodjek/puppet-lint/pull/762) ([rodjek](https://github.com/rodjek)) - Add spec for issue raised in \#754 \#756 [\#761](https://github.com/rodjek/puppet-lint/pull/761) ([rodjek](https://github.com/rodjek)) - Fix setup of default log\_format in PuppetLink.configuration when it is empty. [\#757](https://github.com/rodjek/puppet-lint/pull/757) ([zekefast](https://github.com/zekefast)) ## [2.3.2](https://github.com/rodjek/puppet-lint/tree/2.3.2) (2017-09-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.1...2.3.2) **Fixed bugs:** - configuration, method_missing had faulty logic [\#754](https://github.com/rodjek/puppet-lint/issues/754) ## [2.3.1](https://github.com/rodjek/puppet-lint/tree/2.3.1) (2017-09-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.0...2.3.1) **Fixed bugs:** - NoMethodError: undefined method `type' for nil:NilClass [\#732](https://github.com/rodjek/puppet-lint/issues/732) - NoMethodError: undefined method `end\_with?' for nil:NilClass [\#727](https://github.com/rodjek/puppet-lint/issues/727) - puppet-lint not applying some lint:ignore statements when there are more then 2 on the same line [\#726](https://github.com/rodjek/puppet-lint/issues/726) - optional paramter warning false positve when inheriting params [\#716](https://github.com/rodjek/puppet-lint/issues/716) - invalid byte sequence in UTF-8 in selmodule-example.pp [\#714](https://github.com/rodjek/puppet-lint/issues/714) - puppet-lint --fix encountered an error that it doesn't know how to handle [\#706](https://github.com/rodjek/puppet-lint/issues/706) - Mangled file after running puppet-lint due to chained function call [\#703](https://github.com/rodjek/puppet-lint/issues/703) - `incompatible encoding regexp match` for non-printing characters in place of space [\#693](https://github.com/rodjek/puppet-lint/issues/693) - Unhandled error case [\#691](https://github.com/rodjek/puppet-lint/issues/691) **Closed issues:** - puppet-lint has encountered an error that it doesn't know how to handle [\#750](https://github.com/rodjek/puppet-lint/issues/750) - Variable use like "a+1 = ${$a + 1}" isn't reported but silently changed by --fix to "a+1 = ${a} + 1" [\#749](https://github.com/rodjek/puppet-lint/issues/749) - using --fix changes line endings [\#748](https://github.com/rodjek/puppet-lint/issues/748) - Puppet lint syntax error - puppet parser validate no issues [\#746](https://github.com/rodjek/puppet-lint/issues/746) - Error not handled [\#745](https://github.com/rodjek/puppet-lint/issues/745) - Whoops, not sure why. ArgumentError: bad value for range [\#742](https://github.com/rodjek/puppet-lint/issues/742) - ArgumentError: bad value for range [\#741](https://github.com/rodjek/puppet-lint/issues/741) - Line numbers off after multi-line strings with variables [\#736](https://github.com/rodjek/puppet-lint/issues/736) - Whoops! It looks like puppet-lint has encountered an error [\#729](https://github.com/rodjek/puppet-lint/issues/729) - puppet lint config log\_format not working [\#725](https://github.com/rodjek/puppet-lint/issues/725) - Quoted booleans in Puppet5 for Enum type declarations. [\#720](https://github.com/rodjek/puppet-lint/issues/720) - Chaining arrow syntax fix introduces trailing whitespaces [\#695](https://github.com/rodjek/puppet-lint/issues/695) - Refactor check\_comments.rb [\#587](https://github.com/rodjek/puppet-lint/issues/587) - Puppethack 12/2016 Issues [\#583](https://github.com/rodjek/puppet-lint/issues/583) - Allow multiple block-level ignore comments [\#498](https://github.com/rodjek/puppet-lint/issues/498) - puppet-lint crashes with "invalid byte sequence in UTF-8 \(ArgumentError\)" [\#458](https://github.com/rodjek/puppet-lint/issues/458) **Merged pull requests:** - Render the ${} enclosures as part of the string tokens [\#752](https://github.com/rodjek/puppet-lint/pull/752) ([rodjek](https://github.com/rodjek)) - Open manifest as binary when writing fixed manifest [\#751](https://github.com/rodjek/puppet-lint/pull/751) ([rodjek](https://github.com/rodjek)) - Remove monkeypatches to implement String\#% [\#744](https://github.com/rodjek/puppet-lint/pull/744) ([rodjek](https://github.com/rodjek)) - Add unit tests for PuppetLint::Checks [\#743](https://github.com/rodjek/puppet-lint/pull/743) ([rodjek](https://github.com/rodjek)) - Update CI configuration [\#739](https://github.com/rodjek/puppet-lint/pull/739) ([rodjek](https://github.com/rodjek)) - Rubocop compliance [\#738](https://github.com/rodjek/puppet-lint/pull/738) ([rodjek](https://github.com/rodjek)) - Fix line numbers being off with multi-line strings containing variables [\#737](https://github.com/rodjek/puppet-lint/pull/737) ([cbowman0](https://github.com/cbowman0)) - Split control comments into words before parsing [\#735](https://github.com/rodjek/puppet-lint/pull/735) ([rodjek](https://github.com/rodjek)) - Handle unicode spaces in the tokeniser [\#734](https://github.com/rodjek/puppet-lint/pull/734) ([rodjek](https://github.com/rodjek)) - Handle SE Linux policy package files [\#733](https://github.com/rodjek/puppet-lint/pull/733) ([rodjek](https://github.com/rodjek)) - Take into account Optional data type when checking parameter order [\#731](https://github.com/rodjek/puppet-lint/pull/731) ([rodjek](https://github.com/rodjek)) - Read the manifest files as UTF-8 [\#730](https://github.com/rodjek/puppet-lint/pull/730) ([rodjek](https://github.com/rodjek)) - Improve handling of unterminated double quoted strings [\#728](https://github.com/rodjek/puppet-lint/pull/728) ([rodjek](https://github.com/rodjek)) - Chaining arrow syntax fix introduces trailing whitespaces [\#708](https://github.com/rodjek/puppet-lint/pull/708) ([rnelson0](https://github.com/rnelson0)) - Add helper methods to add and remove tokens while maintaining the token links [\#694](https://github.com/rodjek/puppet-lint/pull/694) ([Darhazer](https://github.com/Darhazer)) - Code style improvements [\#661](https://github.com/rodjek/puppet-lint/pull/661) ([Darhazer](https://github.com/Darhazer)) - Plugins: Improve code readability [\#658](https://github.com/rodjek/puppet-lint/pull/658) ([Darhazer](https://github.com/Darhazer)) ## [2.3.0](https://github.com/rodjek/puppet-lint/tree/2.3.0) (2017-07-12) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.2.1...2.3.0) **Closed issues:** - Inappropriate =\> Indentation Warning in Hash [\#698](https://github.com/rodjek/puppet-lint/issues/698) - Regression: arrow\_alignment check broken between 2.1.1 and 2.2.x releases when left side contains text after variable interpolation [\#697](https://github.com/rodjek/puppet-lint/issues/697) - Check `arrow\_on\_right\_operand\_line` is undocumented. [\#688](https://github.com/rodjek/puppet-lint/issues/688) **Merged pull requests:** - \(maint\) Fixes puppet-lint json formatting to output valid json to stdout [\#719](https://github.com/rodjek/puppet-lint/pull/719) ([bmjen](https://github.com/bmjen)) - Permit puppet-lint to load "prerelease" gems [\#718](https://github.com/rodjek/puppet-lint/pull/718) ([kpaulisse](https://github.com/kpaulisse)) - Document the configuration file better [\#713](https://github.com/rodjek/puppet-lint/pull/713) ([binford2k](https://github.com/binford2k)) - Replace deprecated plugin with an improved alternative. [\#712](https://github.com/rodjek/puppet-lint/pull/712) ([deanwilson](https://github.com/deanwilson)) - Readme formatting fixes [\#709](https://github.com/rodjek/puppet-lint/pull/709) ([dbeckham](https://github.com/dbeckham)) - Readme edit [\#707](https://github.com/rodjek/puppet-lint/pull/707) ([jbondpdx](https://github.com/jbondpdx)) - Take into account length of DQPOST token when updating column number [\#701](https://github.com/rodjek/puppet-lint/pull/701) ([dbeckham](https://github.com/dbeckham)) - Add pattern support to rake task [\#700](https://github.com/rodjek/puppet-lint/pull/700) ([dbeckham](https://github.com/dbeckham)) - Note arrow\_on\_right\_operand\_line in the README [\#690](https://github.com/rodjek/puppet-lint/pull/690) ([rodjek](https://github.com/rodjek)) - Document the arrow\_on\_right\_operand\_line check on the website [\#689](https://github.com/rodjek/puppet-lint/pull/689) ([rodjek](https://github.com/rodjek)) - One file per plugin. Fixes \#657 [\#671](https://github.com/rodjek/puppet-lint/pull/671) ([Darhazer](https://github.com/Darhazer)) ## [2.2.1](https://github.com/rodjek/puppet-lint/tree/2.2.1) (2017-03-29) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.2.0...2.2.1) **Closed issues:** - Error on whitespace with 2.2.0 [\#683](https://github.com/rodjek/puppet-lint/issues/683) - "undefined method `map' for nil:NilClass" when running check\_whitespace [\#681](https://github.com/rodjek/puppet-lint/issues/681) - "undefined method `next\_token='" when fixing with check\_whitespace [\#680](https://github.com/rodjek/puppet-lint/issues/680) - Release 2.2.0 planning and discussion [\#668](https://github.com/rodjek/puppet-lint/issues/668) **Merged pull requests:** - restore the links between tokens after arrow\_on\_right\_operand\_line\#fix [\#684](https://github.com/rodjek/puppet-lint/pull/684) ([rodjek](https://github.com/rodjek)) - level\_tokens\[0\] can be nil if there is no params in the top level block [\#682](https://github.com/rodjek/puppet-lint/pull/682) ([rodjek](https://github.com/rodjek)) ## [2.2.0](https://github.com/rodjek/puppet-lint/tree/2.2.0) (2017-03-29) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.1.1...2.2.0) **Closed issues:** - Plugins reorganization: One file per check [\#657](https://github.com/rodjek/puppet-lint/issues/657) - 2.1.1 git tag [\#652](https://github.com/rodjek/puppet-lint/issues/652) - Quoted boolean triggers on the command 'true' [\#646](https://github.com/rodjek/puppet-lint/issues/646) - Namevars detected as optional parameters [\#633](https://github.com/rodjek/puppet-lint/issues/633) - 'Duplicate Parameter' warning on dynamic class parameter [\#627](https://github.com/rodjek/puppet-lint/issues/627) - arrow\_alignment should only check the alignment of the first arrow on each line [\#609](https://github.com/rodjek/puppet-lint/issues/609) - Top-scope variable warning on inline lambda [\#549](https://github.com/rodjek/puppet-lint/issues/549) - Puppet-lint crash with new puppet 4 syntax [\#516](https://github.com/rodjek/puppet-lint/issues/516) - Top-scope warning when looping though an array of hashes [\#464](https://github.com/rodjek/puppet-lint/issues/464) - Array of hashes one-liner throws a "Indentation of =\> is not properly aligned" [\#446](https://github.com/rodjek/puppet-lint/issues/446) - Missed bad file modes in file with multiple resource bodies [\#663](https://github.com/rodjek/puppet-lint/issues/663) - Provide helper methods to search for specific tokens [\#660](https://github.com/rodjek/puppet-lint/issues/660) - ensure\_first\_param fix can create invalid syntax [\#659](https://github.com/rodjek/puppet-lint/issues/659) - puppet-lint dies with inline\_template syntax [\#656](https://github.com/rodjek/puppet-lint/issues/656) - Variable use like "${$a}" isn't reported as an error and is changed with no message when run with --fix [\#655](https://github.com/rodjek/puppet-lint/issues/655) - Linter gets confused with arrays of hashes [\#654](https://github.com/rodjek/puppet-lint/issues/654) - heredoc throws unhandled exception [\#649](https://github.com/rodjek/puppet-lint/issues/649) - Match function breaks puppet-lint [\#645](https://github.com/rodjek/puppet-lint/issues/645) - top-scope variable being used without an explicit namespace in a string with a lookup [\#635](https://github.com/rodjek/puppet-lint/issues/635) - unquoted file mode & mode should be represented as a 4 digit when file mode is done by a lookup [\#634](https://github.com/rodjek/puppet-lint/issues/634) - double\_quoted\_strings-check issue with escaped character in the string [\#625](https://github.com/rodjek/puppet-lint/issues/625) - unable to disable 140chars check with control comments "block" [\#622](https://github.com/rodjek/puppet-lint/issues/622) - unquoted\_node\_name crash when curly braces missing [\#582](https://github.com/rodjek/puppet-lint/issues/582) - Heredoc triggers exception in arrow\_alignment check [\#578](https://github.com/rodjek/puppet-lint/issues/578) - Each + With = Fake positive top-scope variable detection [\#576](https://github.com/rodjek/puppet-lint/issues/576) - Top-scope variable warning on nested each loops [\#548](https://github.com/rodjek/puppet-lint/issues/548) - `arrow\_alignment --fix` doesn't indent keys when introducing line breaks; erroneously reports success [\#506](https://github.com/rodjek/puppet-lint/issues/506) - heredoc escape gives syntax error [\#430](https://github.com/rodjek/puppet-lint/issues/430) - NoMethodError when multiple heredocs are used [\#395](https://github.com/rodjek/puppet-lint/issues/395) **Merged pull requests:** - Support double quoted strings inside interpolated values in double quoted strings [\#676](https://github.com/rodjek/puppet-lint/pull/676) ([rodjek](https://github.com/rodjek)) - Check that arrow is on the line of right operand [\#672](https://github.com/rodjek/puppet-lint/pull/672) ([Darhazer](https://github.com/Darhazer)) - Deal with ruby 1.8.7 gem issues [\#630](https://github.com/rodjek/puppet-lint/pull/630) ([mterzo](https://github.com/mterzo)) - Plugin review; disable unnecessary plugins [\#567](https://github.com/rodjek/puppet-lint/pull/567) ([rnelson0](https://github.com/rnelson0)) - Ignore selectors when finding resource type [\#678](https://github.com/rodjek/puppet-lint/pull/678) ([rodjek](https://github.com/rodjek)) - Fix for arrow\_alignment bugs in \#506 [\#677](https://github.com/rodjek/puppet-lint/pull/677) ([rodjek](https://github.com/rodjek)) - Don't silently remove unnecessary $ from enclosed variables [\#674](https://github.com/rodjek/puppet-lint/pull/674) ([rodjek](https://github.com/rodjek)) - Fix ensure\_first\_param fix method to retrieve the full value of the ensure parameter [\#673](https://github.com/rodjek/puppet-lint/pull/673) ([rodjek](https://github.com/rodjek)) - Restrict appveyor testing to Ruby versions that appveyor supports [\#670](https://github.com/rodjek/puppet-lint/pull/670) ([james-stocks](https://github.com/james-stocks)) - Clear expected parameter column after processing each block when checking arrow alignment [\#669](https://github.com/rodjek/puppet-lint/pull/669) ([rodjek](https://github.com/rodjek)) - Allow regexps to used as function arguments [\#665](https://github.com/rodjek/puppet-lint/pull/665) ([rodjek](https://github.com/rodjek)) - Catch unhandled exception and provide debug info for issue [\#664](https://github.com/rodjek/puppet-lint/pull/664) ([rodjek](https://github.com/rodjek)) - Fix showing of a failure [\#662](https://github.com/rodjek/puppet-lint/pull/662) ([Darhazer](https://github.com/Darhazer)) - \(SDK-115\) Enable appveyor testing [\#653](https://github.com/rodjek/puppet-lint/pull/653) ([james-stocks](https://github.com/james-stocks)) - Heredoc support [\#650](https://github.com/rodjek/puppet-lint/pull/650) ([rodjek](https://github.com/rodjek)) - Warn when control comment blocks are not properly terminated [\#648](https://github.com/rodjek/puppet-lint/pull/648) ([rodjek](https://github.com/rodjek)) - Prevent incomplete node blocks from crashing puppet-lint [\#642](https://github.com/rodjek/puppet-lint/pull/642) ([rodjek](https://github.com/rodjek)) - Update the tokeniser to differentiate between unquoted strings and function names [\#640](https://github.com/rodjek/puppet-lint/pull/640) ([rodjek](https://github.com/rodjek)) - Check for escaped backslashes too [\#639](https://github.com/rodjek/puppet-lint/pull/639) ([binford2k](https://github.com/binford2k)) - Correctly handle function calls inside string interpolation [\#638](https://github.com/rodjek/puppet-lint/pull/638) ([hanazuki](https://github.com/hanazuki)) - Correctly handle nested lambdas [\#637](https://github.com/rodjek/puppet-lint/pull/637) ([hanazuki](https://github.com/hanazuki)) - Support for nested multiple-variable assignments [\#636](https://github.com/rodjek/puppet-lint/pull/636) ([hanazuki](https://github.com/hanazuki)) - Add LoadError to fix broken tests [\#631](https://github.com/rodjek/puppet-lint/pull/631) ([davidmogar](https://github.com/davidmogar)) ## [2.1.1](https://github.com/rodjek/puppet-lint/tree/2.1.1) (2017-02-15) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.1.0...2.1.1) **Closed issues:** - False positive detection in double quoted string containing no variables [\#618](https://github.com/rodjek/puppet-lint/issues/618) - Warning and error classification [\#614](https://github.com/rodjek/puppet-lint/issues/614) - Top-scope with multiple assignment using split [\#550](https://github.com/rodjek/puppet-lint/issues/550) - Strange error about indent with comments [\#475](https://github.com/rodjek/puppet-lint/issues/475) - Hash of hashes with long keys causes irrational warnings and crashes --fix [\#424](https://github.com/rodjek/puppet-lint/issues/424) - Wrong arrow alignment when key has interpolated variable [\#416](https://github.com/rodjek/puppet-lint/issues/416) - indentation of =\> is not properly aligned in hash within array [\#333](https://github.com/rodjek/puppet-lint/issues/333) **Merged pull requests:** - Correctly handle strings-with-variables as hash keys in arrow\_alignment check [\#621](https://github.com/rodjek/puppet-lint/pull/621) ([rodjek](https://github.com/rodjek)) - Support array of variables on left side of an assign operation [\#617](https://github.com/rodjek/puppet-lint/pull/617) ([rodjek](https://github.com/rodjek)) - Test against Ruby 2.4.0 [\#616](https://github.com/rodjek/puppet-lint/pull/616) ([rodjek](https://github.com/rodjek)) - Calculate arrow column from first parameter position, not the start of the line [\#615](https://github.com/rodjek/puppet-lint/pull/615) ([rodjek](https://github.com/rodjek)) - Do not test against Ruby 2.2 [\#613](https://github.com/rodjek/puppet-lint/pull/613) ([ghoneycutt](https://github.com/ghoneycutt)) ## [2.1.0](https://github.com/rodjek/puppet-lint/tree/2.1.0) (2016-12-30) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.0.2...2.1.0) **Closed issues:** - Excessive number of warnings from code\_on\_top\_scope [\#579](https://github.com/rodjek/puppet-lint/issues/579) - Syntax error for references starting with Regexp [\#566](https://github.com/rodjek/puppet-lint/issues/566) - --fix flag discoverability is low [\#556](https://github.com/rodjek/puppet-lint/issues/556) - Module names must only contain lowercase letters [\#554](https://github.com/rodjek/puppet-lint/issues/554) - Remove formatting with `linenumber` [\#539](https://github.com/rodjek/puppet-lint/issues/539) - names\_containing\_dash is broken and unignorable [\#534](https://github.com/rodjek/puppet-lint/issues/534) - Puppet-lint 2.0 fails on unquoted string starting with underscore. [\#531](https://github.com/rodjek/puppet-lint/issues/531) - puppet-lint reports incorrect line numbers [\#403](https://github.com/rodjek/puppet-lint/issues/403) - Release version 2.1.0 [\#610](https://github.com/rodjek/puppet-lint/issues/610) - No documentation on how to use plugins [\#602](https://github.com/rodjek/puppet-lint/issues/602) - incorrect error on inline template [\#545](https://github.com/rodjek/puppet-lint/issues/545) - parameter\_order check does not work default hash is added in parameter [\#544](https://github.com/rodjek/puppet-lint/issues/544) - Incorrect warning of required parameter when using array that includes variable. [\#537](https://github.com/rodjek/puppet-lint/issues/537) - syntax error on valid file when: if /regex/ in array [\#517](https://github.com/rodjek/puppet-lint/issues/517) - crashes if there is a \# line:endignore with no begining. [\#509](https://github.com/rodjek/puppet-lint/issues/509) - Wrong behaviour of variable\_contains\_dash [\#504](https://github.com/rodjek/puppet-lint/issues/504) - Start a CHANGELOG, make updates part of the build workflow [\#479](https://github.com/rodjek/puppet-lint/issues/479) - Nested future scope blocks lose local variables from parent scopes. [\#456](https://github.com/rodjek/puppet-lint/issues/456) - block-local variables \(|$x|\) don't properly get recognized when used as arrays or hashes [\#450](https://github.com/rodjek/puppet-lint/issues/450) - lint ignore comments feature not documented [\#369](https://github.com/rodjek/puppet-lint/issues/369) **Merged pull requests:** - Ignore \*.pp files at the top level [\#597](https://github.com/rodjek/puppet-lint/pull/597) ([rnelson0](https://github.com/rnelson0)) - Show logs in rspec tests [\#596](https://github.com/rodjek/puppet-lint/pull/596) ([ghoneycutt](https://github.com/ghoneycutt)) - Count lines in comments and double quoted strings [\#577](https://github.com/rodjek/puppet-lint/pull/577) ([paran1](https://github.com/paran1)) - Handle mismatched control comments gracefully [\#573](https://github.com/rodjek/puppet-lint/pull/573) ([rodjek](https://github.com/rodjek)) - Reimplementation of --fix support for unenclosed variables delimited by dashes [\#572](https://github.com/rodjek/puppet-lint/pull/572) ([rodjek](https://github.com/rodjek)) - Anchor the end of the :TYPE token regexp [\#571](https://github.com/rodjek/puppet-lint/pull/571) ([rodjek](https://github.com/rodjek)) - Multi line strings [\#570](https://github.com/rodjek/puppet-lint/pull/570) ([jiuka](https://github.com/jiuka)) - @node\_indexes should be reset too. [\#569](https://github.com/rodjek/puppet-lint/pull/569) ([jiuka](https://github.com/jiuka)) - True up reserved keywords [\#564](https://github.com/rodjek/puppet-lint/pull/564) ([rnelson0](https://github.com/rnelson0)) - \[561\] Provide style guide references for each check [\#562](https://github.com/rodjek/puppet-lint/pull/562) ([rnelson0](https://github.com/rnelson0)) - Add names\_containing\_uppercase docs [\#559](https://github.com/rodjek/puppet-lint/pull/559) ([arrdem](https://github.com/arrdem)) - Implement a linter for uppercase class names [\#558](https://github.com/rodjek/puppet-lint/pull/558) ([arrdem](https://github.com/arrdem)) - Include --fix usage instructions [\#557](https://github.com/rodjek/puppet-lint/pull/557) ([QuinnyPig](https://github.com/QuinnyPig)) - Add puppet-lint plugins from deanwilson to plugins page [\#553](https://github.com/rodjek/puppet-lint/pull/553) ([deanwilson](https://github.com/deanwilson)) - Updates PR for \#223 [\#552](https://github.com/rodjek/puppet-lint/pull/552) ([binford2k](https://github.com/binford2k)) - add legacy\_facts [\#543](https://github.com/rodjek/puppet-lint/pull/543) ([mmckinst](https://github.com/mmckinst)) - Remove formatting with `linenumber` [\#540](https://github.com/rodjek/puppet-lint/pull/540) ([rski](https://github.com/rski)) - Potential README changes [\#420](https://github.com/rodjek/puppet-lint/pull/420) ([rothsa](https://github.com/rothsa)) - Add fix to "ensure found on line but it's not the first attribute" [\#375](https://github.com/rodjek/puppet-lint/pull/375) ([sathieu](https://github.com/sathieu)) - Documentation on plugin usage. [\#611](https://github.com/rodjek/puppet-lint/pull/611) ([rnelson0](https://github.com/rnelson0)) - \(\#369\) Document existence of control comments [\#600](https://github.com/rodjek/puppet-lint/pull/600) ([rnelson0](https://github.com/rnelson0)) - \(\#517\) Update the allowed tokens prior to a regex [\#594](https://github.com/rodjek/puppet-lint/pull/594) ([rnelson0](https://github.com/rnelson0)) - \(\#531\) Treat barewords beginning with an underscore as :NAME tokens [\#593](https://github.com/rodjek/puppet-lint/pull/593) ([rnelson0](https://github.com/rnelson0)) - \(\#544, \#537\) Skip hash contents when checking optional parameters [\#592](https://github.com/rodjek/puppet-lint/pull/592) ([rnelson0](https://github.com/rnelson0)) - \(\#545\) Exempt inline\_epp and inline\_template from single quoted strin… [\#591](https://github.com/rodjek/puppet-lint/pull/591) ([rnelson0](https://github.com/rnelson0)) - Disable code\_on\_top\_scope by default until the noise can be reduced \(… [\#590](https://github.com/rodjek/puppet-lint/pull/590) ([rnelson0](https://github.com/rnelson0)) - Changelog generator task [\#589](https://github.com/rodjek/puppet-lint/pull/589) ([rnelson0](https://github.com/rnelson0)) - Adding support for logging to STDOUT as JSON [\#487](https://github.com/rodjek/puppet-lint/pull/487) ([binford2k](https://github.com/binford2k)) ## [2.0.2](https://github.com/rodjek/puppet-lint/tree/2.0.2) (2016-08-19) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.0.1...2.0.2) **Closed issues:** - Option to choose version of the puppet style guide [\#190](https://github.com/rodjek/puppet-lint/issues/190) **Merged pull requests:** - Revert "Bugfix: properly handling $gronk-$grouik with --fix \(fix \#442\)" [\#535](https://github.com/rodjek/puppet-lint/pull/535) ([rnelson0](https://github.com/rnelson0)) ## [2.0.1](https://github.com/rodjek/puppet-lint/tree/2.0.1) (2016-08-18) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.0.0...2.0.1) **Closed issues:** - Changelog on Github pages is out of date [\#520](https://github.com/rodjek/puppet-lint/issues/520) - 80char --\> 140char transition incomplete [\#514](https://github.com/rodjek/puppet-lint/issues/514) - ensure\_first\_param-check should not consider hashes [\#512](https://github.com/rodjek/puppet-lint/issues/512) - RFE: Provide a way to selectively disable checks in puppet source [\#508](https://github.com/rodjek/puppet-lint/issues/508) - question: 1.1.0 --\> 2.0.0 new checks [\#499](https://github.com/rodjek/puppet-lint/issues/499) - \[\#puppethack\] disable\_char\_check doesn't work [\#493](https://github.com/rodjek/puppet-lint/issues/493) - Error fixing indent in possion 0 [\#489](https://github.com/rodjek/puppet-lint/issues/489) - Allow specifying the default enable status of a check [\#484](https://github.com/rodjek/puppet-lint/issues/484) - Empty lines with trailing whitespace triggers redundant soft tabs error. [\#478](https://github.com/rodjek/puppet-lint/issues/478) - Little problem with =\> when variables are used as key [\#472](https://github.com/rodjek/puppet-lint/issues/472) - Question: using config file, with custom path [\#466](https://github.com/rodjek/puppet-lint/issues/466) - Error: "Variable in single quoted string" or "Double quoted string without variable" - syntax? [\#463](https://github.com/rodjek/puppet-lint/issues/463) - Critical error on Atom initialization [\#460](https://github.com/rodjek/puppet-lint/issues/460) - print warning for code that will result in logging or backups of secrets [\#455](https://github.com/rodjek/puppet-lint/issues/455) - Linter gets upset with Regexp in type [\#452](https://github.com/rodjek/puppet-lint/issues/452) - Single whitespace in file replaced with \[\] [\#444](https://github.com/rodjek/puppet-lint/issues/444) - Time for a new release! [\#443](https://github.com/rodjek/puppet-lint/issues/443) - Bug with --fix and warning "variable not enclosed in {}" [\#442](https://github.com/rodjek/puppet-lint/issues/442) - Linter should not warn about inheriting from params class [\#441](https://github.com/rodjek/puppet-lint/issues/441) - Variable not enclosed in {} AND single quoted string containing a variable [\#434](https://github.com/rodjek/puppet-lint/issues/434) - Quoted string issue due to structured data [\#433](https://github.com/rodjek/puppet-lint/issues/433) - allow for arrow alignment with more than one space before [\#432](https://github.com/rodjek/puppet-lint/issues/432) - 3 digit modes are incorrectly flagged [\#431](https://github.com/rodjek/puppet-lint/issues/431) - url\_without\_modules adding paths? [\#428](https://github.com/rodjek/puppet-lint/issues/428) - Check for unbalanced parenthesis [\#427](https://github.com/rodjek/puppet-lint/issues/427) - puppet-lint crash [\#422](https://github.com/rodjek/puppet-lint/issues/422) - PuppetLint.configuration.ignore\_paths ignored by puppet-lint [\#417](https://github.com/rodjek/puppet-lint/issues/417) - Quoted boolean check should only check values [\#415](https://github.com/rodjek/puppet-lint/issues/415) - nested ensure misdetected as not coming first. [\#410](https://github.com/rodjek/puppet-lint/issues/410) - tabs before code issue [\#402](https://github.com/rodjek/puppet-lint/issues/402) - Disabled checks aren't actually disabled, output is merely ignored. [\#400](https://github.com/rodjek/puppet-lint/issues/400) - file modes doesn't have to be 4 digit octal [\#394](https://github.com/rodjek/puppet-lint/issues/394) - Option to disable top-scope variable warning for $facts and $trusted hashes [\#382](https://github.com/rodjek/puppet-lint/issues/382) - top-scope variable check incorrectly warning on second parameter in block [\#380](https://github.com/rodjek/puppet-lint/issues/380) - Looking for a tool that shows the output of puppet-lint and rspec-puppet on a screen like jenkins [\#374](https://github.com/rodjek/puppet-lint/issues/374) - Puppet lint should warn on semi colon usage when used without compression [\#367](https://github.com/rodjek/puppet-lint/issues/367) - "indentation of =\> is not properly aligned" and "ensure found on line but it's not the first attribute" weirdness [\#365](https://github.com/rodjek/puppet-lint/issues/365) - Run via jenkins complains about autoload module layout [\#361](https://github.com/rodjek/puppet-lint/issues/361) - Installing gems / puppet-lint may break puppet-enterprise [\#358](https://github.com/rodjek/puppet-lint/issues/358) - Double arrow after "symlink target specified in ensure attr" fix [\#341](https://github.com/rodjek/puppet-lint/issues/341) - "puppet:// URL without modules/" - in the style guide? Custom mount points? [\#307](https://github.com/rodjek/puppet-lint/issues/307) - Autoloader layout test fails inside a \(custom named\) module directory [\#265](https://github.com/rodjek/puppet-lint/issues/265) - Check for trailing comma in last line of a attribute/value list [\#237](https://github.com/rodjek/puppet-lint/issues/237) - Catch code outside of class or define block. [\#220](https://github.com/rodjek/puppet-lint/issues/220) - Catch global code outside of node blocks [\#160](https://github.com/rodjek/puppet-lint/issues/160) - Add a warning for resources outside of a class [\#69](https://github.com/rodjek/puppet-lint/issues/69) - Release a new build, 2.0.1 [\#519](https://github.com/rodjek/puppet-lint/issues/519) - Puppet-Lint 1.1.0 unhandled issue causing exit during -f [\#366](https://github.com/rodjek/puppet-lint/issues/366) **Merged pull requests:** - Continue supporting Ruby \< 2 [\#529](https://github.com/rodjek/puppet-lint/pull/529) ([ghoneycutt](https://github.com/ghoneycutt)) - Use underscores instead of CamelCase in example [\#527](https://github.com/rodjek/puppet-lint/pull/527) ([ghoneycutt](https://github.com/ghoneycutt)) - new linter for top\_scope\_facts [\#526](https://github.com/rodjek/puppet-lint/pull/526) ([mmckinst](https://github.com/mmckinst)) - \(GH462\) Multi-line comments can now be fixed. [\#525](https://github.com/rodjek/puppet-lint/pull/525) ([rnelson0](https://github.com/rnelson0)) - New additions of protected variables [\#524](https://github.com/rodjek/puppet-lint/pull/524) ([rnelson0](https://github.com/rnelson0)) - Document new checks in puppet-lint 2.0.0+ [\#523](https://github.com/rodjek/puppet-lint/pull/523) ([rnelson0](https://github.com/rnelson0)) - Remove github pages changelog [\#522](https://github.com/rodjek/puppet-lint/pull/522) ([3flex](https://github.com/3flex)) - \(GH366\) Arrow Alignment fix crashes with tabs [\#515](https://github.com/rodjek/puppet-lint/pull/515) ([rnelson0](https://github.com/rnelson0)) - Make params disabled [\#511](https://github.com/rodjek/puppet-lint/pull/511) ([binford2k](https://github.com/binford2k)) - Removing params class check [\#510](https://github.com/rodjek/puppet-lint/pull/510) ([cvquesty](https://github.com/cvquesty)) - Tweak travis a bit for better patterns. [\#505](https://github.com/rodjek/puppet-lint/pull/505) ([rnelson0](https://github.com/rnelson0)) - Bugfix: properly handling $gronk-$grouik with --fix \(fix \#442\) [\#500](https://github.com/rodjek/puppet-lint/pull/500) ([Lucas-C](https://github.com/Lucas-C)) - Improve look of rspec [\#496](https://github.com/rodjek/puppet-lint/pull/496) ([rnelson0](https://github.com/rnelson0)) - This adds a disabled-by-default 80chars check [\#495](https://github.com/rodjek/puppet-lint/pull/495) ([binford2k](https://github.com/binford2k)) - Add better description of the problem in arrow\_alignment check [\#492](https://github.com/rodjek/puppet-lint/pull/492) ([rnelson0](https://github.com/rnelson0)) - \(GH410\) Limit ensure\_first\_param check to certain resources [\#490](https://github.com/rodjek/puppet-lint/pull/490) ([rnelson0](https://github.com/rnelson0)) - add lint test for resource references [\#486](https://github.com/rodjek/puppet-lint/pull/486) ([tuxmea](https://github.com/tuxmea)) - Regression from 418: duplicate constant [\#483](https://github.com/rodjek/puppet-lint/pull/483) ([rnelson0](https://github.com/rnelson0)) - Add fully-detailed CHANGELOG [\#481](https://github.com/rodjek/puppet-lint/pull/481) ([petems](https://github.com/petems)) - Add a CHANGELOG [\#480](https://github.com/rodjek/puppet-lint/pull/480) ([rnelson0](https://github.com/rnelson0)) - Add file mode checks for concat module [\#473](https://github.com/rodjek/puppet-lint/pull/473) ([danieljamesscott](https://github.com/danieljamesscott)) - Fix handling of empty code [\#469](https://github.com/rodjek/puppet-lint/pull/469) ([hanazuki](https://github.com/hanazuki)) - Allow regex params for puppet data types [\#468](https://github.com/rodjek/puppet-lint/pull/468) ([thejandroman](https://github.com/thejandroman)) - Support automatic fixing in Rake task as described in README [\#465](https://github.com/rodjek/puppet-lint/pull/465) ([hanazuki](https://github.com/hanazuki)) - Fix double arrow issue when adding target to ensure symlink [\#454](https://github.com/rodjek/puppet-lint/pull/454) ([mterzo](https://github.com/mterzo)) - Add future parser's Puppet Types token type [\#435](https://github.com/rodjek/puppet-lint/pull/435) ([mcanevet](https://github.com/mcanevet)) - Parameters ordering was only checked on defined types [\#429](https://github.com/rodjek/puppet-lint/pull/429) ([ctoa](https://github.com/ctoa)) - Check that variables are lowercase [\#418](https://github.com/rodjek/puppet-lint/pull/418) ([rothsa](https://github.com/rothsa)) ## [2.0.0](https://github.com/rodjek/puppet-lint/tree/2.0.0) (2016-06-22) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/1.1.0...2.0.0) puppet-lint 2.0.0 is a breaking change. Specifically, the renaming of the line length test was changed from `80chars` to `140chars`. You may need to adjust your configuration and lint checks. For example: ```ruby # Line length test is 80 chars in puppet-lint 1.1.0 PuppetLint.configuration.send('disable_80chars') # Line length test is 140 chars in puppet-lint 2.x PuppetLint.configuration.send('disable_140chars') ``` You may also need to adjust your Gemfile if you are pointing directly at git: ```ruby # old gem 'puppet-lint', :require => false, :git => 'https://github.com/rodjek/puppet-lint.git' # new gem 'puppet-lint', '~> 2.0' ``` If the additional gems you use for checks are pinned to 1.x, you should pin puppet-lint to `'~> 1.0'` or `'>= 1.0', '< 3.0'` until updated check gems are released. **Closed issues:** - Current package [\#471](https://github.com/rodjek/puppet-lint/issues/471) - Arrow alignment check not working with semicolons in a \(potential\) multiple resources declaration [\#470](https://github.com/rodjek/puppet-lint/issues/470) - puppet-lint --fix ".../puppet-lint/plugins/check\_comments.rb:55:in `block in fix': undefined method `value' for nil:NilClass \(NoMethodError\)" [\#461](https://github.com/rodjek/puppet-lint/issues/461) - WARNING: indentation of =\> is not properly aligned [\#447](https://github.com/rodjek/puppet-lint/issues/447) - Inheritance check [\#436](https://github.com/rodjek/puppet-lint/issues/436) - puppet-lint still checks for lines with more than 80 character [\#425](https://github.com/rodjek/puppet-lint/issues/425) - puppet-lint --help does not work [\#423](https://github.com/rodjek/puppet-lint/issues/423) - Test that "ensure" non-filename attributes are barewords [\#412](https://github.com/rodjek/puppet-lint/issues/412) - crashing puppet-lint 1.1.0 [\#409](https://github.com/rodjek/puppet-lint/issues/409) - Small Documentation Typo [\#408](https://github.com/rodjek/puppet-lint/issues/408) - Create v1.1.1 [\#401](https://github.com/rodjek/puppet-lint/issues/401) - TypeError running on seemingly-sane puppet file [\#399](https://github.com/rodjek/puppet-lint/issues/399) - Warning for line-length should be at 140 chars [\#396](https://github.com/rodjek/puppet-lint/issues/396) - Add fix for puppet\_url\_without\_modules check [\#390](https://github.com/rodjek/puppet-lint/issues/390) - How to disable some fix ? [\#383](https://github.com/rodjek/puppet-lint/issues/383) - indentation of =\> is not properly aligned [\#381](https://github.com/rodjek/puppet-lint/issues/381) - parser error on modulo operator [\#379](https://github.com/rodjek/puppet-lint/issues/379) - Trailing blank lines discarded in PuppetLinter::Data.manifest\_lines [\#378](https://github.com/rodjek/puppet-lint/issues/378) - nasty bug leading to --no-star\_comments-check to not being honored with --fix [\#373](https://github.com/rodjek/puppet-lint/issues/373) - Puppet-lint for EPEL7 [\#372](https://github.com/rodjek/puppet-lint/issues/372) - puppet-lint failure for resource declarations with colons followed by non-whitespaces [\#370](https://github.com/rodjek/puppet-lint/issues/370) - Issue with puppet-lint 1.1.0 binary on lucid [\#364](https://github.com/rodjek/puppet-lint/issues/364) - Immediate action required: custom Pages domain pointed to a legacy IP address [\#363](https://github.com/rodjek/puppet-lint/issues/363) - 1.1.0 ignores trailing white spaces on lines without text [\#359](https://github.com/rodjek/puppet-lint/issues/359) - alignment warning on commented code [\#357](https://github.com/rodjek/puppet-lint/issues/357) - gem missing when installing with Puppet [\#356](https://github.com/rodjek/puppet-lint/issues/356) - --fix ignores control comment\(s\) and fixes anyway [\#347](https://github.com/rodjek/puppet-lint/issues/347) - colon after closing of class causing puppet-lint to crash. [\#344](https://github.com/rodjek/puppet-lint/issues/344) - New problem in unqouted\_node\_name check in 1.1.0 [\#343](https://github.com/rodjek/puppet-lint/issues/343) - whitespace check bug [\#339](https://github.com/rodjek/puppet-lint/issues/339) - 57fd065d0c2c116471cb16afec99631803496659 breaks indentation of =\> check [\#338](https://github.com/rodjek/puppet-lint/issues/338) - Error in Jenkins [\#337](https://github.com/rodjek/puppet-lint/issues/337) - Line numbers in developer tutorial documentation. [\#336](https://github.com/rodjek/puppet-lint/issues/336) - '--relative' option doesn't work with new RakeTask format introduced in 1.1.0 [\#335](https://github.com/rodjek/puppet-lint/issues/335) - Configuring RakeTask does not work anymore [\#331](https://github.com/rodjek/puppet-lint/issues/331) - "indentation of =\> is not properly aligned" for hash inside resource definition [\#327](https://github.com/rodjek/puppet-lint/issues/327) - --fix doesn't change "\$var" to single-quotes [\#313](https://github.com/rodjek/puppet-lint/issues/313) **Merged pull requests:** - \(GH443\) Release 2.0.0 PR [\#477](https://github.com/rodjek/puppet-lint/pull/477) ([rnelson0](https://github.com/rnelson0)) - Fix arrow aligment check in multiple resources declaration [\#476](https://github.com/rodjek/puppet-lint/pull/476) ([wybczu](https://github.com/wybczu)) - Fix issue \#450: block-local variables aren't recognized with subscripts [\#453](https://github.com/rodjek/puppet-lint/pull/453) ([jearls](https://github.com/jearls)) - Adding package\_ensure plugin [\#448](https://github.com/rodjek/puppet-lint/pull/448) ([danzilio](https://github.com/danzilio)) - Update documentation for 140chars [\#440](https://github.com/rodjek/puppet-lint/pull/440) ([keeleysam](https://github.com/keeleysam)) - Changed character width to 140. [\#419](https://github.com/rodjek/puppet-lint/pull/419) ([potto007](https://github.com/potto007)) - Fix arrow\_alignment check to not raise exception when line isn't indented [\#413](https://github.com/rodjek/puppet-lint/pull/413) ([rodjek](https://github.com/rodjek)) - Fix puppet:// url check to catch double quoted strings [\#407](https://github.com/rodjek/puppet-lint/pull/407) ([paulgeringer](https://github.com/paulgeringer)) - Load puppet-lint plugins from Puppet modules [\#404](https://github.com/rodjek/puppet-lint/pull/404) ([raphink](https://github.com/raphink)) - Get ignore\_paths from the configuration [\#397](https://github.com/rodjek/puppet-lint/pull/397) ([lazyfrosch](https://github.com/lazyfrosch)) - Skip checks on empty files [\#393](https://github.com/rodjek/puppet-lint/pull/393) ([vStone](https://github.com/vStone)) - Add the fix functionality to puppet\_url\_without\_modules [\#391](https://github.com/rodjek/puppet-lint/pull/391) ([someword](https://github.com/someword)) - Add various helper functions [\#389](https://github.com/rodjek/puppet-lint/pull/389) ([raphink](https://github.com/raphink)) - Support older 1.8.7 patch numbers Kernel\#caller output [\#387](https://github.com/rodjek/puppet-lint/pull/387) ([rodjek](https://github.com/rodjek)) - Detect trailing whitespace on lines with no code [\#386](https://github.com/rodjek/puppet-lint/pull/386) ([rodjek](https://github.com/rodjek)) - Save the raw value of MLCOMMENT tokens to use when rendering back to a manifest [\#385](https://github.com/rodjek/puppet-lint/pull/385) ([rodjek](https://github.com/rodjek)) - Don't suppress nil values in manifest\_lines [\#384](https://github.com/rodjek/puppet-lint/pull/384) ([rodjek](https://github.com/rodjek)) - Update index.md [\#377](https://github.com/rodjek/puppet-lint/pull/377) ([mcanevet](https://github.com/mcanevet)) - Only clear task if it's already defined [\#376](https://github.com/rodjek/puppet-lint/pull/376) ([domcleal](https://github.com/domcleal)) - add strict\_indent check to community plugins [\#371](https://github.com/rodjek/puppet-lint/pull/371) ([relud](https://github.com/relud)) - Nested cases [\#368](https://github.com/rodjek/puppet-lint/pull/368) ([jonnangle](https://github.com/jonnangle)) - rpearce: Allow the use of facts\[\] and trusted\[\] as per Puppet 3.5+ [\#362](https://github.com/rodjek/puppet-lint/pull/362) ([rjpearce](https://github.com/rjpearce)) - plugins: Add absolute template path check [\#353](https://github.com/rodjek/puppet-lint/pull/353) ([3flex](https://github.com/3flex)) - Update index.md [\#352](https://github.com/rodjek/puppet-lint/pull/352) ([mcanevet](https://github.com/mcanevet)) - Add node\_indexes method [\#351](https://github.com/rodjek/puppet-lint/pull/351) ([mcanevet](https://github.com/mcanevet)) - Don't attempt to fix ignored problems [\#349](https://github.com/rodjek/puppet-lint/pull/349) ([rodjek](https://github.com/rodjek)) - Handle case where a colon is the last token in a file [\#346](https://github.com/rodjek/puppet-lint/pull/346) ([rodjek](https://github.com/rodjek)) - Fix bug in unquoted\_node\_name to support multiple node blocks [\#345](https://github.com/rodjek/puppet-lint/pull/345) ([rodjek](https://github.com/rodjek)) - Catch Errno::EACCES when reading a puppet-lint.rc out of HOME [\#342](https://github.com/rodjek/puppet-lint/pull/342) ([rodjek](https://github.com/rodjek)) - Generate line numbers for the plugin tutorial code examples [\#340](https://github.com/rodjek/puppet-lint/pull/340) ([rodjek](https://github.com/rodjek)) - Add support for '--relative' option in new Rake::Task format. [\#334](https://github.com/rodjek/puppet-lint/pull/334) ([fatmcgav](https://github.com/fatmcgav)) - fix \#331 - clear any pre-\(auto-\)existing tasks [\#332](https://github.com/rodjek/puppet-lint/pull/332) ([duritong](https://github.com/duritong)) - Don't warn for arrow alignment for single-element hashes [\#330](https://github.com/rodjek/puppet-lint/pull/330) ([domcleal](https://github.com/domcleal)) - Document multiple commands in a single control comment [\#329](https://github.com/rodjek/puppet-lint/pull/329) ([domcleal](https://github.com/domcleal)) - Add parameter\_documentation/param-docs plugin [\#328](https://github.com/rodjek/puppet-lint/pull/328) ([domcleal](https://github.com/domcleal)) - Alternative to \#289: :error on either class names and defines [\#290](https://github.com/rodjek/puppet-lint/pull/290) ([ppp0](https://github.com/ppp0)) ## [1.1.0](https://github.com/rodjek/puppet-lint/tree/1.1.0) (2014-09-23) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/1.0.1...1.1.0) **Closed issues:** - Allow overriding filename for autoloader\_layout [\#316](https://github.com/rodjek/puppet-lint/issues/316) - Alignment warning when =\> are all aligned. [\#309](https://github.com/rodjek/puppet-lint/issues/309) - Run with future parser? [\#306](https://github.com/rodjek/puppet-lint/issues/306) - Pull in variables defined from inherited classes for top\_scope\_variables check [\#304](https://github.com/rodjek/puppet-lint/issues/304) - puppet-lint unqouted\_node\_name only checks \(and fixes\) first entry [\#323](https://github.com/rodjek/puppet-lint/issues/323) - Class param\_tokens on unparameterised class returns function arguments [\#319](https://github.com/rodjek/puppet-lint/issues/319) - Performance on largeish files for 1.0.0 and 1.0.1 is much slower [\#315](https://github.com/rodjek/puppet-lint/issues/315) - Multiple ignores on one line [\#314](https://github.com/rodjek/puppet-lint/issues/314) - --fix doesn't handle multiple "=\>" on the same line properly [\#312](https://github.com/rodjek/puppet-lint/issues/312) - --fix converts "param=\>" to "=\>" [\#311](https://github.com/rodjek/puppet-lint/issues/311) - Make top scope variable check respect metaparameters for defined types [\#310](https://github.com/rodjek/puppet-lint/issues/310) - Installation instructions on front page should include how to install it with puppet [\#308](https://github.com/rodjek/puppet-lint/issues/308) - Make rake task accept optional list of files to check [\#305](https://github.com/rodjek/puppet-lint/issues/305) **Merged pull requests:** - Extend the rake task to support setting configuration options in the block [\#326](https://github.com/rodjek/puppet-lint/pull/326) ([rodjek](https://github.com/rodjek)) - Support multiple commands in a single control comment [\#325](https://github.com/rodjek/puppet-lint/pull/325) ([rodjek](https://github.com/rodjek)) - Support for multiple node names in unquoted\_node\_name [\#324](https://github.com/rodjek/puppet-lint/pull/324) ([rodjek](https://github.com/rodjek)) - Handle multiple parameters on a line when fixing arrow\_alignment problems [\#322](https://github.com/rodjek/puppet-lint/pull/322) ([rodjek](https://github.com/rodjek)) - Support of metaparameter variables in variable\_scope check [\#321](https://github.com/rodjek/puppet-lint/pull/321) ([rodjek](https://github.com/rodjek)) - Don't parse class body when searching for parameter tokens [\#320](https://github.com/rodjek/puppet-lint/pull/320) ([domcleal](https://github.com/domcleal)) - Insert :WHITESPACE token between :NAME and :FARROW if needed [\#318](https://github.com/rodjek/puppet-lint/pull/318) ([rodjek](https://github.com/rodjek)) - Cache parsing state in Lexer rather than recalculating [\#317](https://github.com/rodjek/puppet-lint/pull/317) ([rodjek](https://github.com/rodjek)) ## [1.0.1](https://github.com/rodjek/puppet-lint/tree/1.0.1) (2014-08-20) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/1.0.0...1.0.1) **Closed issues:** - Cut a new release. [\#259](https://github.com/rodjek/puppet-lint/issues/259) - Exception with PE 3.0 [\#231](https://github.com/rodjek/puppet-lint/issues/231) - Puppet-lint should warn on files that do not end with a trailing newline [\#188](https://github.com/rodjek/puppet-lint/issues/188) - Breaks if ressource collector is present [\#301](https://github.com/rodjek/puppet-lint/issues/301) - puppet-lint issues scope warnings for array/hash access [\#291](https://github.com/rodjek/puppet-lint/issues/291) **Merged pull requests:** - Handle empty blocks in arrow\_alignment [\#302](https://github.com/rodjek/puppet-lint/pull/302) ([rodjek](https://github.com/rodjek)) - fix typo in the links to 'trailing\_newline' plugin [\#300](https://github.com/rodjek/puppet-lint/pull/300) ([3flex](https://github.com/3flex)) - Comments on developer puppet-lint checks [\#299](https://github.com/rodjek/puppet-lint/pull/299) ([jfryman](https://github.com/jfryman)) - \[Fixes \#291\] Ignore index braces for scope variables [\#303](https://github.com/rodjek/puppet-lint/pull/303) ([dcarley](https://github.com/dcarley)) ## [1.0.0](https://github.com/rodjek/puppet-lint/tree/1.0.0) (2014-08-18) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.4.0.pre1...1.0.0) **Closed issues:** - Stop complaining about things unsupported versions of Puppet won't support. [\#281](https://github.com/rodjek/puppet-lint/issues/281) - some ERROR checks shouldn't fire inside comments [\#272](https://github.com/rodjek/puppet-lint/issues/272) - quoted boolean should not trigger off of a variable value in a conditional [\#268](https://github.com/rodjek/puppet-lint/issues/268) - Fails when parsing a Puppet file with Windows line endings on Linux. [\#262](https://github.com/rodjek/puppet-lint/issues/262) - Whitelist variables [\#260](https://github.com/rodjek/puppet-lint/issues/260) - Syntax error not detected [\#257](https://github.com/rodjek/puppet-lint/issues/257) - "\$ escape sequence" throws out puppet lint error [\#256](https://github.com/rodjek/puppet-lint/issues/256) - Incorrect ensure not first attribute warning [\#254](https://github.com/rodjek/puppet-lint/issues/254) - lint task breaks, command line works [\#253](https://github.com/rodjek/puppet-lint/issues/253) - Boolean quotation [\#251](https://github.com/rodjek/puppet-lint/issues/251) - Closing bracket from classes not "linting" [\#250](https://github.com/rodjek/puppet-lint/issues/250) - Node variables being detected as a top-scope variable [\#246](https://github.com/rodjek/puppet-lint/issues/246) - autoloader\_layout test overly dependant on the name of the current directory [\#245](https://github.com/rodjek/puppet-lint/issues/245) - Bamboo plugin published [\#242](https://github.com/rodjek/puppet-lint/issues/242) - puppet-lint says syntax error, puppet parser says ok [\#230](https://github.com/rodjek/puppet-lint/issues/230) - warn when variable or parameter is not used [\#225](https://github.com/rodjek/puppet-lint/issues/225) - Parser fails on arithmetic expressions [\#222](https://github.com/rodjek/puppet-lint/issues/222) - Linting errors should be sent to stderr [\#218](https://github.com/rodjek/puppet-lint/issues/218) - 2 space softabs does not always make sense when aligning array endings [\#213](https://github.com/rodjek/puppet-lint/issues/213) - Ignore cron commands over 80 characters long [\#198](https://github.com/rodjek/puppet-lint/issues/198) - facter fact selinux; WARNING: quoted boolean value found on line [\#197](https://github.com/rodjek/puppet-lint/issues/197) - Recursive check [\#196](https://github.com/rodjek/puppet-lint/issues/196) - emits ERROR when garbage outside the class definition. [\#193](https://github.com/rodjek/puppet-lint/issues/193) - variables\_not\_enclosed sometimes fires where it shouldn't. [\#191](https://github.com/rodjek/puppet-lint/issues/191) - Doesn't detect syntax error [\#187](https://github.com/rodjek/puppet-lint/issues/187) - Puppet-lint doesn't fail on unbalanced curly braces [\#185](https://github.com/rodjek/puppet-lint/issues/185) - Optionally fixing simple stuff instead of complaining [\#162](https://github.com/rodjek/puppet-lint/issues/162) - Feature: Print the name of the file being linted [\#283](https://github.com/rodjek/puppet-lint/issues/283) - Allow specifying a configuration file on the command line [\#267](https://github.com/rodjek/puppet-lint/issues/267) - Future parser loop should allow for inline variable declaration without scoping [\#264](https://github.com/rodjek/puppet-lint/issues/264) - Double Quoted Strings - should allow for strings containing single quotes [\#263](https://github.com/rodjek/puppet-lint/issues/263) - puppet-lint should not warn "string containing only a variable" when it's used to create a hash [\#261](https://github.com/rodjek/puppet-lint/issues/261) - ERROR: Syntax error \(try running `puppet parser validate \`\) on line 15 [\#258](https://github.com/rodjek/puppet-lint/issues/258) - Variables in each incorrectly idenentified as top scope. [\#249](https://github.com/rodjek/puppet-lint/issues/249) - puppet-lint -f makes a mess of double-quoted strings that contain single quotes [\#248](https://github.com/rodjek/puppet-lint/issues/248) - Need a way to ignore a lint check for a particular line [\#247](https://github.com/rodjek/puppet-lint/issues/247) - Puppetlint should ignore template lines \> 80 characters [\#233](https://github.com/rodjek/puppet-lint/issues/233) - Syntax error when parser future features used [\#232](https://github.com/rodjek/puppet-lint/issues/232) - Issue with puppet-lint -f and trailing whitespace [\#224](https://github.com/rodjek/puppet-lint/issues/224) - escape a variable interpolation to skip checking [\#219](https://github.com/rodjek/puppet-lint/issues/219) - Trailing line comment to disable check [\#214](https://github.com/rodjek/puppet-lint/issues/214) - wrong title for \>80char per line check site [\#209](https://github.com/rodjek/puppet-lint/issues/209) - `rake lint` should respect .puppet-lint.rc in root of module [\#202](https://github.com/rodjek/puppet-lint/issues/202) - lint analyzes inlined ruby code [\#201](https://github.com/rodjek/puppet-lint/issues/201) - --with-context causes error [\#200](https://github.com/rodjek/puppet-lint/issues/200) - Different results on Windows and Mac [\#195](https://github.com/rodjek/puppet-lint/issues/195) - Fixing of double quoted strings doesn't escape single quote inside [\#182](https://github.com/rodjek/puppet-lint/issues/182) - Fixing of string with array addressing wrong [\#181](https://github.com/rodjek/puppet-lint/issues/181) - Puppet lint seems to ignore --no-class\_parameter\_defaults-check when inheriting the params class [\#173](https://github.com/rodjek/puppet-lint/issues/173) - Quoting top level variable in class parameter cause false warning [\#170](https://github.com/rodjek/puppet-lint/issues/170) - exec and Bash vars, false-postive "single quoted string containing a variable found on line" [\#113](https://github.com/rodjek/puppet-lint/issues/113) - disable tests on arbitrary lines or over blocks of code [\#68](https://github.com/rodjek/puppet-lint/issues/68) **Merged pull requests:** - Checks for code outside class/define block [\#223](https://github.com/rodjek/puppet-lint/pull/223) ([dLobatog](https://github.com/dLobatog)) - explains in README that puppet-lint is not for checking syntax [\#186](https://github.com/rodjek/puppet-lint/pull/186) ([ghoneycutt](https://github.com/ghoneycutt)) - Use the current workdir as reference to calculate the expanded\_path of a filename [\#175](https://github.com/rodjek/puppet-lint/pull/175) ([vStone](https://github.com/vStone)) - Update code documentation [\#298](https://github.com/rodjek/puppet-lint/pull/298) ([rodjek](https://github.com/rodjek)) - Add option to load config from specified file [\#297](https://github.com/rodjek/puppet-lint/pull/297) ([rodjek](https://github.com/rodjek)) - Ensure check methods can't modify tokens array [\#296](https://github.com/rodjek/puppet-lint/pull/296) ([rodjek](https://github.com/rodjek)) - Allow single quoted strings in double quoted strings [\#295](https://github.com/rodjek/puppet-lint/pull/295) ([rodjek](https://github.com/rodjek)) - Move dependency info into gemspec [\#294](https://github.com/rodjek/puppet-lint/pull/294) ([rodjek](https://github.com/rodjek)) - Support future parser loop local scope variables [\#293](https://github.com/rodjek/puppet-lint/pull/293) ([rodjek](https://github.com/rodjek)) - Fix problems after all checks have finished [\#292](https://github.com/rodjek/puppet-lint/pull/292) ([rodjek](https://github.com/rodjek)) - Enable --with-filename by default if checking multiple files [\#287](https://github.com/rodjek/puppet-lint/pull/287) ([rodjek](https://github.com/rodjek)) - Automatically convert multiline comments into many single line comments [\#286](https://github.com/rodjek/puppet-lint/pull/286) ([rodjek](https://github.com/rodjek)) - Move to rspec3 [\#285](https://github.com/rodjek/puppet-lint/pull/285) ([rodjek](https://github.com/rodjek)) - Automatically fix ensure\_not\_symlink\_target problems [\#284](https://github.com/rodjek/puppet-lint/pull/284) ([rodjek](https://github.com/rodjek)) - Allow strings containing only a variable if they're used as hash keys [\#280](https://github.com/rodjek/puppet-lint/pull/280) ([rodjek](https://github.com/rodjek)) - Compressed arrow\_alignment [\#279](https://github.com/rodjek/puppet-lint/pull/279) ([rodjek](https://github.com/rodjek)) - Array ref variables [\#278](https://github.com/rodjek/puppet-lint/pull/278) ([rodjek](https://github.com/rodjek)) - Add docs badge to README [\#277](https://github.com/rodjek/puppet-lint/pull/277) ([rrrene](https://github.com/rrrene)) - Make array refs part of the variable name [\#276](https://github.com/rodjek/puppet-lint/pull/276) ([rodjek](https://github.com/rodjek)) - Don't automatically pad comment content with whitespace [\#275](https://github.com/rodjek/puppet-lint/pull/275) ([rodjek](https://github.com/rodjek)) - Use \#write instead of \#puts when writing fixed manifest [\#274](https://github.com/rodjek/puppet-lint/pull/274) ([rodjek](https://github.com/rodjek)) - Add --fix back to optionparser [\#273](https://github.com/rodjek/puppet-lint/pull/273) ([rodjek](https://github.com/rodjek)) - Initial spike of control comment logic [\#266](https://github.com/rodjek/puppet-lint/pull/266) ([rodjek](https://github.com/rodjek)) - Abort rake on lint error [\#255](https://github.com/rodjek/puppet-lint/pull/255) ([rodjek](https://github.com/rodjek)) - Add --relative command line argument for autoload structure testing [\#252](https://github.com/rodjek/puppet-lint/pull/252) ([ryanuber](https://github.com/ryanuber)) - DRY up the checks [\#244](https://github.com/rodjek/puppet-lint/pull/244) ([rodjek](https://github.com/rodjek)) - Refactor out linenumber in problems [\#243](https://github.com/rodjek/puppet-lint/pull/243) ([rodjek](https://github.com/rodjek)) - Ignore 80chars on lines that have long template\(\) paths [\#241](https://github.com/rodjek/puppet-lint/pull/241) ([rodjek](https://github.com/rodjek)) - Have the rake task read options from .puppet-lint.rc [\#240](https://github.com/rodjek/puppet-lint/pull/240) ([rodjek](https://github.com/rodjek)) - Support pipe char \(used in the "future" parser\) [\#239](https://github.com/rodjek/puppet-lint/pull/239) ([rodjek](https://github.com/rodjek)) - Rejig tests [\#238](https://github.com/rodjek/puppet-lint/pull/238) ([rodjek](https://github.com/rodjek)) - Allow double quotes for puppet supported escape sequences [\#234](https://github.com/rodjek/puppet-lint/pull/234) ([xarses](https://github.com/xarses)) - Allow specifying a list of checks that should run [\#228](https://github.com/rodjek/puppet-lint/pull/228) ([rodjek](https://github.com/rodjek)) - Split checking and reporting logic [\#227](https://github.com/rodjek/puppet-lint/pull/227) ([rodjek](https://github.com/rodjek)) - Refactor check plugins to have slightly less awful magic [\#226](https://github.com/rodjek/puppet-lint/pull/226) ([rodjek](https://github.com/rodjek)) - Add %{column} to help text of --log-format [\#221](https://github.com/rodjek/puppet-lint/pull/221) ([bdd](https://github.com/bdd)) - Bad hash indenting with --fix where members declared on a single line [\#217](https://github.com/rodjek/puppet-lint/pull/217) ([aelse](https://github.com/aelse)) - Handle variables with array & hash references [\#212](https://github.com/rodjek/puppet-lint/pull/212) ([rodjek](https://github.com/rodjek)) - Add Modulo token [\#207](https://github.com/rodjek/puppet-lint/pull/207) ([dalen](https://github.com/dalen)) - Fix class\_inherits\_from\_params\_class docs link [\#206](https://github.com/rodjek/puppet-lint/pull/206) ([dcarley](https://github.com/dcarley)) - incorrect top-scope variable warning for define [\#205](https://github.com/rodjek/puppet-lint/pull/205) ([blalor](https://github.com/blalor)) - --fix doesn't modify my file [\#203](https://github.com/rodjek/puppet-lint/pull/203) ([BillWeiss](https://github.com/BillWeiss)) - Don't warn about 'mode' format when it's an 'audit' value [\#199](https://github.com/rodjek/puppet-lint/pull/199) ([bitfield](https://github.com/bitfield)) - Doesn't recognize paramater containing default value if value is double quoted. [\#194](https://github.com/rodjek/puppet-lint/pull/194) ([jcray](https://github.com/jcray)) - Running with --fix deletes all code for files containing invalid syntax [\#184](https://github.com/rodjek/puppet-lint/pull/184) ([devicenull](https://github.com/devicenull)) - Puppet-lint fails to handle mac line endings [\#183](https://github.com/rodjek/puppet-lint/pull/183) ([devicenull](https://github.com/devicenull)) - Lone dollar sign should not be removed [\#180](https://github.com/rodjek/puppet-lint/pull/180) ([Seldaek](https://github.com/Seldaek)) - Fix illegal replacement of double quotes by single quotes [\#179](https://github.com/rodjek/puppet-lint/pull/179) ([Seldaek](https://github.com/Seldaek)) - Write files in binary mode to avoid writing CRLFs on windows [\#178](https://github.com/rodjek/puppet-lint/pull/178) ([Seldaek](https://github.com/Seldaek)) - Warn about unquoted node names [\#177](https://github.com/rodjek/puppet-lint/pull/177) ([bitfield](https://github.com/bitfield)) - Fix the check\_classes check for certain cases. [\#176](https://github.com/rodjek/puppet-lint/pull/176) ([vStone](https://github.com/vStone)) - Invalid warning about mandatory class parameters without defaults [\#167](https://github.com/rodjek/puppet-lint/pull/167) ([svend](https://github.com/svend)) - Add check for puppet:/// URIs without modules/ [\#166](https://github.com/rodjek/puppet-lint/pull/166) ([rodjek](https://github.com/rodjek)) ## [0.4.0.pre1](https://github.com/rodjek/puppet-lint/tree/0.4.0.pre1) (2013-01-28) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.3.2...0.4.0.pre1) **Closed issues:** - error installing puppet-lint [\#172](https://github.com/rodjek/puppet-lint/issues/172) - puppet-lint seems to miss obvious syntax error [\#171](https://github.com/rodjek/puppet-lint/issues/171) - ERROR with file containing DOS EOL character [\#165](https://github.com/rodjek/puppet-lint/issues/165) - ssh key parameter will always be longer than 80 chars [\#70](https://github.com/rodjek/puppet-lint/issues/70) **Merged pull requests:** - Fix where . is located in docs [\#169](https://github.com/rodjek/puppet-lint/pull/169) ([gmjosack](https://github.com/gmjosack)) - Update README.md [\#168](https://github.com/rodjek/puppet-lint/pull/168) ([levilovelock](https://github.com/levilovelock)) ## [0.3.2](https://github.com/rodjek/puppet-lint/tree/0.3.2) (2012-10-19) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.3.1...0.3.2) **Closed issues:** - Check "string containing only a variable" performs invalid suggestion. [\#164](https://github.com/rodjek/puppet-lint/issues/164) - puppet-lint/lexer.rb:184:in `tokenise': ' } \(PuppetLint::LexerError\) on Ruby 1.8.7 [\#161](https://github.com/rodjek/puppet-lint/issues/161) - Warning for 'more than 80 characters on line' is not catching all instances [\#159](https://github.com/rodjek/puppet-lint/issues/159) - captilised variables error on puppet not with lint [\#158](https://github.com/rodjek/puppet-lint/issues/158) - warning for 'class param without default' is not catching all instances in a file [\#157](https://github.com/rodjek/puppet-lint/issues/157) - puppet-lint crashes if HOME environment is not set [\#156](https://github.com/rodjek/puppet-lint/issues/156) - String monkeypatch breaks Facter under Ruby 1.8 [\#154](https://github.com/rodjek/puppet-lint/issues/154) - Crash on string with \\ and variable [\#152](https://github.com/rodjek/puppet-lint/issues/152) **Merged pull requests:** - \(\#152\) Fix crash on string with \\ and variable [\#163](https://github.com/rodjek/puppet-lint/pull/163) ([dalen](https://github.com/dalen)) - fixes \#154 string monkeypatch failure [\#155](https://github.com/rodjek/puppet-lint/pull/155) ([vStone](https://github.com/vStone)) ## [0.3.1](https://github.com/rodjek/puppet-lint/tree/0.3.1) (2012-09-26) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.3.0...0.3.1) **Closed issues:** - class\_inherits\_from\_params\_class throws exception in 0.3.0 [\#150](https://github.com/rodjek/puppet-lint/issues/150) **Merged pull requests:** - Fixes \#150 class inherits from params class exception [\#151](https://github.com/rodjek/puppet-lint/pull/151) ([vStone](https://github.com/vStone)) ## [0.3.0](https://github.com/rodjek/puppet-lint/tree/0.3.0) (2012-09-25) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.2.1...0.3.0) **Closed issues:** - False positive unquoted resource title for colons in resource parameters [\#146](https://github.com/rodjek/puppet-lint/issues/146) - should exit with non 0 exit code on error [\#140](https://github.com/rodjek/puppet-lint/issues/140) - using fully qualified class names in inheritance is wrongly reported as inheritance across namespaces [\#148](https://github.com/rodjek/puppet-lint/issues/148) - False positive on duplicate parameter checks [\#145](https://github.com/rodjek/puppet-lint/issues/145) - Crash on \\ at end of single quoted string [\#144](https://github.com/rodjek/puppet-lint/issues/144) - Strings ending in backslash cause exceptions [\#142](https://github.com/rodjek/puppet-lint/issues/142) - --no-class\_parameter\_defaults-check [\#139](https://github.com/rodjek/puppet-lint/issues/139) - Provide context for the problems [\#130](https://github.com/rodjek/puppet-lint/issues/130) **Merged pull requests:** - Fixes \#145: False positive on duplicate parameter. [\#147](https://github.com/rodjek/puppet-lint/pull/147) ([vStone](https://github.com/vStone)) - Pass exit value to the shell [\#141](https://github.com/rodjek/puppet-lint/pull/141) ([vStone](https://github.com/vStone)) - \(\#148\) Allow class inheritance within the same module [\#149](https://github.com/rodjek/puppet-lint/pull/149) ([dcarley](https://github.com/dcarley)) - use .puppet-lint.rc, as .puppet-lintrc is deprecated [\#143](https://github.com/rodjek/puppet-lint/pull/143) ([ghoneycutt](https://github.com/ghoneycutt)) ## [0.2.1](https://github.com/rodjek/puppet-lint/tree/0.2.1) (2012-08-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.2.0...0.2.1) **Closed issues:** - Rake task breaks in 0.2.0 [\#138](https://github.com/rodjek/puppet-lint/issues/138) - False warning : parameterised class parameter without a default value [\#137](https://github.com/rodjek/puppet-lint/issues/137) ## [0.2.0](https://github.com/rodjek/puppet-lint/tree/0.2.0) (2012-08-23) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.2.0.pre1...0.2.0) **Closed issues:** - `require': iconv will be deprecated in the future, use String\#encode instead. [\#133](https://github.com/rodjek/puppet-lint/issues/133) - False positive in "optional parameter listed before required parameter"? [\#126](https://github.com/rodjek/puppet-lint/issues/126) - There's a puppet-lint 0.13.1 gem on rubygems.org but no 0.13.1 tag here [\#99](https://github.com/rodjek/puppet-lint/issues/99) - Introduce a way to tweak warning/error level for checks [\#91](https://github.com/rodjek/puppet-lint/issues/91) - Didn't pick up $ipaddress\_bond0 as a fact [\#61](https://github.com/rodjek/puppet-lint/issues/61) - Variables standing by themselves should not be quoted [\#20](https://github.com/rodjek/puppet-lint/issues/20) - write class\_parameter\_defaults check [\#134](https://github.com/rodjek/puppet-lint/issues/134) - False positive when using function call for parameter default [\#132](https://github.com/rodjek/puppet-lint/issues/132) - Fix up the website [\#131](https://github.com/rodjek/puppet-lint/issues/131) - Linked list style functionality for tokens [\#129](https://github.com/rodjek/puppet-lint/issues/129) - False positive unquoted resource title in case statements [\#128](https://github.com/rodjek/puppet-lint/issues/128) - Crash on arrow alignment check [\#127](https://github.com/rodjek/puppet-lint/issues/127) - duplicate parameter detection [\#122](https://github.com/rodjek/puppet-lint/issues/122) - Does not work on ruby 1.9.3 [\#120](https://github.com/rodjek/puppet-lint/issues/120) - Bad class format causes exception [\#118](https://github.com/rodjek/puppet-lint/issues/118) - case statement in inline\_template false warning [\#117](https://github.com/rodjek/puppet-lint/issues/117) - False warning with puppet-lint-0.2 [\#116](https://github.com/rodjek/puppet-lint/issues/116) - :lint rake tasks should not print "Evaluating" lines [\#114](https://github.com/rodjek/puppet-lint/issues/114) - when content is specified directly, double quotes are needed to get newlines [\#109](https://github.com/rodjek/puppet-lint/issues/109) - Incorrect variable count in string parsing [\#104](https://github.com/rodjek/puppet-lint/issues/104) - misparses empty hash in defined resource prototype [\#101](https://github.com/rodjek/puppet-lint/issues/101) - Allow file modes to be 'undef' [\#100](https://github.com/rodjek/puppet-lint/issues/100) - Arrow alignment check shouldn't span over several resources [\#78](https://github.com/rodjek/puppet-lint/issues/78) - Ignore commented lines for arrow alignment [\#77](https://github.com/rodjek/puppet-lint/issues/77) - /etc/puppet-lint.rc please! [\#71](https://github.com/rodjek/puppet-lint/issues/71) - checking of correct docs format [\#59](https://github.com/rodjek/puppet-lint/issues/59) - Multiline string should not be checked for double quotes [\#51](https://github.com/rodjek/puppet-lint/issues/51) ## [0.2.0.pre1](https://github.com/rodjek/puppet-lint/tree/0.2.0.pre1) (2012-07-11) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.13...0.2.0.pre1) **Closed issues:** - Getting double quote warning with Augeas [\#111](https://github.com/rodjek/puppet-lint/issues/111) - NoMethodError with Ruby 1.9.2 [\#103](https://github.com/rodjek/puppet-lint/issues/103) - new to the lint [\#97](https://github.com/rodjek/puppet-lint/issues/97) - inline\_templates only evaluate in double quotes, yet lint warns of no vars. [\#94](https://github.com/rodjek/puppet-lint/issues/94) - Stop duplicate output [\#93](https://github.com/rodjek/puppet-lint/issues/93) - add noop to variables\_in\_scope list [\#92](https://github.com/rodjek/puppet-lint/issues/92) - Can't handle single quotes? \(slurpstring\) [\#90](https://github.com/rodjek/puppet-lint/issues/90) - Detect missing commas [\#89](https://github.com/rodjek/puppet-lint/issues/89) - Weird \(probably UTF-8\) problem gives false positives on 80char limit. [\#84](https://github.com/rodjek/puppet-lint/issues/84) - Autoload module check and JenkinsCI [\#83](https://github.com/rodjek/puppet-lint/issues/83) - "Should align arrows within blocks of attributes" check doesn't seem to work [\#75](https://github.com/rodjek/puppet-lint/issues/75) - puppet-lintrc is ignored when running "rake lint" [\#74](https://github.com/rodjek/puppet-lint/issues/74) - docs mention --disable-XXX, should be --no-XXX [\#73](https://github.com/rodjek/puppet-lint/issues/73) - Added support for detecting bad string interpolation [\#40](https://github.com/rodjek/puppet-lint/issues/40) **Merged pull requests:** - Make rake task respect PuppetLint.configuration.fail\_on\_warnings [\#115](https://github.com/rodjek/puppet-lint/pull/115) ([wfarr](https://github.com/wfarr)) - fixes spelling and typo errors in README [\#112](https://github.com/rodjek/puppet-lint/pull/112) ([ghoneycutt](https://github.com/ghoneycutt)) - This fixes the build on Travis CI for ruby1.9 [\#110](https://github.com/rodjek/puppet-lint/pull/110) ([vStone](https://github.com/vStone)) - Fix utf8 char issues: see bug \#84 [\#108](https://github.com/rodjek/puppet-lint/pull/108) ([vStone](https://github.com/vStone)) - Add support for ignoring certain globs in the rake task [\#106](https://github.com/rodjek/puppet-lint/pull/106) ([wfarr](https://github.com/wfarr)) - Fix bug introduced in \#81 [\#98](https://github.com/rodjek/puppet-lint/pull/98) ([deizel](https://github.com/deizel)) ## [0.1.13](https://github.com/rodjek/puppet-lint/tree/0.1.13) (2012-03-26) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.12...0.1.13) **Closed issues:** - Getting `warning: class variable access from toplevel` with bundler [\#85](https://github.com/rodjek/puppet-lint/issues/85) - Suppress "string containing only a variable" warnings on defines? [\#79](https://github.com/rodjek/puppet-lint/issues/79) - puppet-lint equivalent to rakefile's require 'puppet-lint/tasks/puppet-lint' [\#72](https://github.com/rodjek/puppet-lint/issues/72) - Support symbolic file modes for \>= 2.7.10 [\#60](https://github.com/rodjek/puppet-lint/issues/60) **Merged pull requests:** - Update readme to reflect the current names of the flags for disabling checks [\#88](https://github.com/rodjek/puppet-lint/pull/88) ([garethr](https://github.com/garethr)) - Add additional puppet variables. [\#82](https://github.com/rodjek/puppet-lint/pull/82) ([nanliu](https://github.com/nanliu)) - Add support run puppet-lint on directory. [\#81](https://github.com/rodjek/puppet-lint/pull/81) ([nanliu](https://github.com/nanliu)) - Update travis support for multiple puppet version. [\#80](https://github.com/rodjek/puppet-lint/pull/80) ([nanliu](https://github.com/nanliu)) - Find booleans in double quoted strings [\#67](https://github.com/rodjek/puppet-lint/pull/67) ([richardc](https://github.com/richardc)) - Fixup the variable not enclosed in {} test [\#66](https://github.com/rodjek/puppet-lint/pull/66) ([richardc](https://github.com/richardc)) - Feature/symbolic filemodes \(cfr ticket \#60\) [\#62](https://github.com/rodjek/puppet-lint/pull/62) ([vStone](https://github.com/vStone)) ## [0.1.12](https://github.com/rodjek/puppet-lint/tree/0.1.12) (2012-01-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.11...0.1.12) **Closed issues:** - ssh\_key can't be broken up by \ [\#58](https://github.com/rodjek/puppet-lint/issues/58) - Autoload module check doesn't seem to work [\#57](https://github.com/rodjek/puppet-lint/issues/57) - included parameterized classes check does not work [\#56](https://github.com/rodjek/puppet-lint/issues/56) - invalid quoted string warning on resource titles [\#44](https://github.com/rodjek/puppet-lint/issues/44) - turn off particular tests? .puppet-lintrc? [\#34](https://github.com/rodjek/puppet-lint/issues/34) ## [0.1.11](https://github.com/rodjek/puppet-lint/tree/0.1.11) (2012-01-11) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.10...0.1.11) ## [0.1.10](https://github.com/rodjek/puppet-lint/tree/0.1.10) (2012-01-11) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.9...0.1.10) **Closed issues:** - Alert when more than one class/define is present in a .pp file [\#54](https://github.com/rodjek/puppet-lint/issues/54) - Invalid top-scope variable warning in definitions. [\#50](https://github.com/rodjek/puppet-lint/issues/50) - Regex capture variables [\#49](https://github.com/rodjek/puppet-lint/issues/49) **Merged pull requests:** - Feature/unified problems [\#52](https://github.com/rodjek/puppet-lint/pull/52) ([vStone](https://github.com/vStone)) ## [0.1.9](https://github.com/rodjek/puppet-lint/tree/0.1.9) (2011-12-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.8...0.1.9) **Merged pull requests:** - Consolidated option checking logic [\#48](https://github.com/rodjek/puppet-lint/pull/48) ([jamtur01](https://github.com/jamtur01)) ## [0.1.8](https://github.com/rodjek/puppet-lint/tree/0.1.8) (2011-12-27) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.7...0.1.8) **Closed issues:** - Add option to control which error level is returned [\#45](https://github.com/rodjek/puppet-lint/issues/45) - "false" != false \(ditto for true\) [\#43](https://github.com/rodjek/puppet-lint/issues/43) - Facter variables are seen as unnamespaced top-level variables [\#42](https://github.com/rodjek/puppet-lint/issues/42) - WARNING: =\> on line 13 isn't aligned with the previous line [\#37](https://github.com/rodjek/puppet-lint/issues/37) - single quotes in a manifest causes an exception [\#36](https://github.com/rodjek/puppet-lint/issues/36) - Invalid "optional parameter listed before required parameter" warning. [\#35](https://github.com/rodjek/puppet-lint/issues/35) - Resource types containing only a variable [\#30](https://github.com/rodjek/puppet-lint/issues/30) **Merged pull requests:** - \[\#9\] add stack to allow nested hashes [\#47](https://github.com/rodjek/puppet-lint/pull/47) ([zsprackett](https://github.com/zsprackett)) - Fixed \#45 - Added selective error level reporting [\#46](https://github.com/rodjek/puppet-lint/pull/46) ([jamtur01](https://github.com/jamtur01)) - Added check for dashes in variables [\#41](https://github.com/rodjek/puppet-lint/pull/41) ([jamtur01](https://github.com/jamtur01)) - Add filename as first test\(\) argument so plugins can use that too [\#39](https://github.com/rodjek/puppet-lint/pull/39) ([vStone](https://github.com/vStone)) ## [0.1.7](https://github.com/rodjek/puppet-lint/tree/0.1.7) (2011-10-18) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.4...0.1.7) **Closed issues:** - missing dependency on "puppet" gem [\#33](https://github.com/rodjek/puppet-lint/issues/33) - "class defined inside a class" even when class is a resource \(parameterized Class\) [\#32](https://github.com/rodjek/puppet-lint/issues/32) - Classes inside classes should be allowed when order matters [\#31](https://github.com/rodjek/puppet-lint/issues/31) - doesn't work...at all [\#29](https://github.com/rodjek/puppet-lint/issues/29) - "mode should be represented as a 4 digit octal value" when variable [\#28](https://github.com/rodjek/puppet-lint/issues/28) ## [0.1.4](https://github.com/rodjek/puppet-lint/tree/0.1.4) (2011-09-09) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.3...0.1.4) **Closed issues:** - String containing escape char \(and no var\) incorrectly flagged [\#26](https://github.com/rodjek/puppet-lint/issues/26) - False alignment positives [\#21](https://github.com/rodjek/puppet-lint/issues/21) ## [0.1.3](https://github.com/rodjek/puppet-lint/tree/0.1.3) (2011-09-09) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.2...0.1.3) ## [0.1.2](https://github.com/rodjek/puppet-lint/tree/0.1.2) (2011-09-09) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.1...0.1.2) **Closed issues:** - double quote within single quote [\#24](https://github.com/rodjek/puppet-lint/issues/24) - False positive in commented line [\#22](https://github.com/rodjek/puppet-lint/issues/22) ## [0.1.1](https://github.com/rodjek/puppet-lint/tree/0.1.1) (2011-09-07) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.1.0...0.1.1) **Closed issues:** - $name is detected as a top-scope variable [\#23](https://github.com/rodjek/puppet-lint/issues/23) - Not detecting comma and semicolon being mixed up [\#13](https://github.com/rodjek/puppet-lint/issues/13) ## [0.1.0](https://github.com/rodjek/puppet-lint/tree/0.1.0) (2011-08-23) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.7...0.1.0) **Closed issues:** - display order of class/define parameters [\#19](https://github.com/rodjek/puppet-lint/issues/19) - class inheritance [\#18](https://github.com/rodjek/puppet-lint/issues/18) - classes and defined types within classes [\#17](https://github.com/rodjek/puppet-lint/issues/17) - relationship declarations [\#16](https://github.com/rodjek/puppet-lint/issues/16) - defaults for case statements and selectors [\#15](https://github.com/rodjek/puppet-lint/issues/15) - namespacing variables [\#14](https://github.com/rodjek/puppet-lint/issues/14) - =\> alignment warnings in selectors is broken [\#11](https://github.com/rodjek/puppet-lint/issues/11) ## [0.0.7](https://github.com/rodjek/puppet-lint/tree/0.0.7) (2011-08-21) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.6...0.0.7) ## [0.0.6](https://github.com/rodjek/puppet-lint/tree/0.0.6) (2011-08-19) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.5...0.0.6) **Closed issues:** - Please add logic to the \>80 chars check [\#12](https://github.com/rodjek/puppet-lint/issues/12) ## [0.0.5](https://github.com/rodjek/puppet-lint/tree/0.0.5) (2011-08-19) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.4...0.0.5) **Closed issues:** - When ensure is the only attribute it is the first one too. [\#10](https://github.com/rodjek/puppet-lint/issues/10) - Shell commands with curly brackets \(e.g. awk\) [\#9](https://github.com/rodjek/puppet-lint/issues/9) - "single quoted string containing a variable" should check for nested quotes [\#7](https://github.com/rodjek/puppet-lint/issues/7) ## [0.0.4](https://github.com/rodjek/puppet-lint/tree/0.0.4) (2011-08-18) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.3...0.0.4) **Closed issues:** - "ensure is not the first attribute" does not check for aggregated resources [\#8](https://github.com/rodjek/puppet-lint/issues/8) - Square brackets trigger "WARNING: unquoted resource title" [\#5](https://github.com/rodjek/puppet-lint/issues/5) - Nasty stacktrace when trying to run lint against a non existance file [\#4](https://github.com/rodjek/puppet-lint/issues/4) ## [0.0.3](https://github.com/rodjek/puppet-lint/tree/0.0.3) (2011-08-17) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.2...0.0.3) **Closed issues:** - Invalid "ensure is not the first attribute" [\#3](https://github.com/rodjek/puppet-lint/issues/3) - Empty variables break check\_strings plugin [\#2](https://github.com/rodjek/puppet-lint/issues/2) ## [0.0.2](https://github.com/rodjek/puppet-lint/tree/0.0.2) (2011-08-17) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/0.0.1...0.0.2) **Merged pull requests:** - Here, have some Rake support [\#1](https://github.com/rodjek/puppet-lint/pull/1) ([builddoctor](https://github.com/builddoctor)) ## [0.0.1](https://github.com/rodjek/puppet-lint/tree/0.0.1) (2011-08-15) [Full Changelog](https://github.com/rodjek/puppet-lint/compare/2dd42b803a4dfc3a2398a509d26f285c9427ba41...0.0.1) \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* puppet-lint-2.4.2/.rubocop.yml0000644000004100000410000000331013611752231016300 0ustar www-datawww-data--- inherit_from: './.rubocop_todo.yml' AllCops: TargetRubyVersion: 1.9 Style/HashSyntax: EnforcedStyle: hash_rockets Layout/FirstArrayElementLineBreak: Enabled: true Layout/FirstHashElementLineBreak: Enabled: true Layout/FirstMethodArgumentLineBreak: Enabled: true Layout/FirstMethodParameterLineBreak: Enabled: true Layout/IndentArray: EnforcedStyle: consistent Layout/MultilineArrayBraceLayout: EnforcedStyle: new_line Layout/MultilineAssignmentLayout: Enabled: true EnforcedStyle: same_line Layout/MultilineHashBraceLayout: EnforcedStyle: new_line Layout/MultilineMethodDefinitionBraceLayout: EnforcedStyle: new_line Style/AutoResourceCleanup: Enabled: true Style/BlockDelimiters: EnforcedStyle: braces_for_chaining Style/BracesAroundHashParameters: EnforcedStyle: context_dependent Style/Encoding: Enabled: false Style/MethodCallWithArgsParentheses: Enabled: true IgnoreMacros: true IgnoredMethods: - puts - require - include - it - context - describe - to - to_not - raise - desc - task - exit - should - gem - group - attr_reader - attr_accessor - attr_writer - source Style/MethodCalledOnDoEndBlock: Enabled: true Style/RegexpLiteral: EnforcedStyle: percent_r Style/TrailingCommaInArguments: EnforcedStyleForMultiline: no_comma Style/TrailingCommaInLiteral: EnforcedStyleForMultiline: comma Style/FormatStringToken: Enabled: false Style/FileName: Exclude: - 'lib/puppet-lint.rb' - 'lib/puppet-lint/tasks/puppet-lint.rb' - 'spec/puppet-lint_spec.rb' puppet-lint-2.4.2/.gitignore0000644000004100000410000000015313611752231016020 0ustar www-datawww-data*.gem .bundle/ .rbenv-version .ruby-version Gemfile.lock vendor/ coverage/ *.swp /_site/ .idea /*.pp /tmp/ puppet-lint-2.4.2/LICENSE0000644000004100000410000000203613611752231015037 0ustar www-datawww-dataCopyright (c) 2011 Tim Sharpe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. puppet-lint-2.4.2/.rubocop_todo.yml0000644000004100000410000000431013611752231017326 0ustar www-datawww-data# This configuration was generated by # `rubocop --auto-gen-config` # on 2017-08-28 12:57:58 +1000 using RuboCop version 0.49.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 3 # Configuration parameters: Include. # Include: **/Gemfile, **/gems.rb Bundler/DuplicatedGem: Exclude: - 'Gemfile' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: Include, TreatCommentsAsGroupSeparators. # Include: **/Gemfile, **/gems.rb Bundler/OrderedGems: Exclude: - 'Gemfile' # Offense count: 9 # Configuration parameters: AllowSafeAssignment. Lint/AssignmentInCondition: Exclude: - 'lib/puppet-lint/lexer.rb' - 'lib/puppet-lint/plugins/check_classes/variable_scope.rb' # Offense count: 52 Metrics/AbcSize: Max: 153 # Offense count: 121 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: Max: 1136 # Offense count: 8 # Configuration parameters: CountBlocks. Metrics/BlockNesting: Max: 5 # Offense count: 2 # Configuration parameters: CountComments. Metrics/ClassLength: Max: 385 # Offense count: 20 Metrics/CyclomaticComplexity: Max: 26 # Offense count: 238 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: Max: 223 # Offense count: 65 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 105 # Offense count: 18 Metrics/PerceivedComplexity: Max: 28 # Offense count: 1 # Cop supports --auto-correct. Performance/RedundantBlockCall: Exclude: - 'lib/puppet-lint/tasks/puppet-lint.rb' # Offense count: 7 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - 'lib/puppet-lint.rb' - 'lib/puppet-lint/bin.rb' - 'lib/puppet-lint/checkplugin.rb' - 'lib/puppet-lint/checks.rb' - 'lib/puppet-lint/data.rb' - 'lib/puppet-lint/optparser.rb' # Offense count: 20 Style/MultilineBlockChain: Enabled: false puppet-lint-2.4.2/Rakefile0000644000004100000410000000203313611752231015474 0ustar www-datawww-datarequire 'rake' require 'rspec/core/rake_task' require 'puppet-lint' require 'puppet-lint/tasks/release_test' task :default => :test RSpec::Core::RakeTask.new(:test) begin require 'github_changelog_generator/task' GitHubChangelogGenerator::RakeTask.new(:changelog) do |config| version = PuppetLint::VERSION config.user = 'rodjek' config.project = 'puppet-lint' config.future_release = version.to_s config.exclude_labels = %w[duplicate question invalid wontfix release-pr documentation] config.enhancement_labels = %w[feature] end rescue LoadError $stderr.puts 'Changelog generation requires Ruby 2.0 or higher' end begin require 'rubocop/rake_task' RuboCop::RakeTask.new(:rubocop) do |task| task.options = %w[-D -E] task.patterns = [ 'lib/**/*.rb', 'spec/**/*.rb', 'bin/*', '*.gemspec', 'Gemfile', 'Rakefile', ] end rescue LoadError $stderr.puts 'Rubocop is not available for this version of Ruby.' end task :ci => [:test, :release_test] # vim: syntax=ruby puppet-lint-2.4.2/lib/0000755000004100000410000000000013611752231014577 5ustar www-datawww-datapuppet-lint-2.4.2/lib/puppet-lint.rb0000644000004100000410000001632113611752231017410 0ustar www-datawww-data# encoding: utf-8 require 'set' require 'json' require 'puppet-lint/version' require 'puppet-lint/lexer' require 'puppet-lint/configuration' require 'puppet-lint/data' require 'puppet-lint/checks' require 'puppet-lint/bin' require 'puppet-lint/monkeypatches' class PuppetLint::NoCodeError < StandardError; end class PuppetLint::NoFix < StandardError; end # Parser Syntax Errors class PuppetLint::SyntaxError < StandardError attr_reader :token def initialize(token) @token = token end end # Public: The public interface to puppet-lint. class PuppetLint # Public: Gets/Sets the String manifest code to be checked. attr_accessor :code # Public: Gets the String manifest with the errors fixed. attr_reader :manifest # Public: Returns an Array of Hashes describing the problems found in the # manifest. # # Each Hash will contain *at least*: # :check - The Symbol name of the check that generated the problem. # :kind - The Symbol kind of the problem (:error, :warning, or # :fixed). # :line - The Integer line number of the location of the problem in # the manifest. # :column - The Integer column number of the location of the problem in # the manifest. # :message - The String message describing the problem that was found. attr_reader :problems # Public: Gets/Sets the String path to the manifest to be checked. attr_accessor :path # Public: Returns a Hash of linter statistics # # :error - An Integer count of errors found in the manifest. # :warning - An Integer count of warnings found in the manifest. # :fixed - An Integer count of problems found in the manifest that were # automatically fixed. attr_reader :statistics # Public: Initialise a new PuppetLint object. def initialize @code = nil @statistics = { :error => 0, :warning => 0, :fixed => 0, :ignored => 0 } @manifest = '' end # Public: Access PuppetLint's configuration from outside the class. # # Returns a PuppetLint::Configuration object. def self.configuration @configuration ||= PuppetLint::Configuration.new end # Public: Access PuppetLint's configuration from inside the class. # # Returns a PuppetLint::Configuration object. def configuration self.class.configuration end # Public: Set the path of the manifest file to be tested and read the # contents of the file. # # Returns nothing. def file=(path) return unless File.exist?(path) @path = path File.open(path, 'rb:UTF-8') do |f| @code = f.read end # Check if the input is an SE Linux policy package file (which also use # the .pp extension), which all have the first 4 bytes 0xf97cff8f. @code = '' if @code[0..3].unpack('V').first == 0xf97cff8f end # Internal: Retrieve the format string to be used when writing problems to # STDOUT. If the user has not specified a custom log format, build one for # them. # # Returns a format String to be used with String#%. def log_format if configuration.log_format.nil? || configuration.log_format.empty? ## recreate previous old log format as far as thats possible. format = '%{KIND}: %{message} on line %{line}' format.prepend('%{path} - ') if configuration.with_filename configuration.log_format = format end configuration.log_format end # Internal: Format a problem message and print it to STDOUT. # # message - A Hash containing all the information about a problem. # # Returns nothing. def format_message(message) format = log_format puts format % message puts " #{message[:reason]}" if message[:kind] == :ignored && !message[:reason].nil? end # Internal: Get the line of the manifest on which the problem was found # # message - A Hash containing all the information about a problem. # # Returns the problematic line as a string. def get_context(message) PuppetLint::Data.manifest_lines[message[:line] - 1].strip end # Internal: Print out the line of the manifest on which the problem was found # as well as a marker pointing to the location on the line. # # message - A Hash containing all the information about a problem. # # Returns nothing. def print_context(message) return if message[:check] == 'documentation' return if message[:kind] == :fixed line = get_context(message) offset = line.index(%r{\S}) || 1 puts "\n #{line.strip}" printf("%#{message[:column] + 2 - offset}s\n\n", '^') end # Internal: Print the reported problems with a manifest to stdout. # # problems - An Array of problem Hashes as returned by # PuppetLint::Checks#run. # # Returns nothing. def report(problems) json = [] problems.each do |message| next if message[:kind] == :ignored && !PuppetLint.configuration.show_ignored message[:KIND] = message[:kind].to_s.upcase if message[:kind] == :fixed || [message[:kind], :all].include?(configuration.error_level) if configuration.json message['context'] = get_context(message) if configuration.with_context json << message else format_message(message) print_context(message) if configuration.with_context end end end puts JSON.pretty_generate(json) if configuration.json $stderr.puts 'Try running `puppet parser validate `' if problems.any? { |p| p[:check] == :syntax } end # Public: Determine if PuppetLint found any errors in the manifest. # # Returns true if errors were found, otherwise returns false. def errors? @statistics[:error] != 0 end # Public: Determine if PuppetLint found any warnings in the manifest. # # Returns true if warnings were found, otherwise returns false. def warnings? @statistics[:warning] != 0 end # Public: Run the loaded manifest code through the lint checks and print the # results of the checks to stdout. # # Returns nothing. # Raises PuppetLint::NoCodeError if no manifest code has been loaded. def run raise PuppetLint::NoCodeError if @code.nil? if @code.empty? @problems = [] @manifest = '' return end linter = PuppetLint::Checks.new @problems = linter.run(@path, @code) @problems.each { |problem| @statistics[problem[:kind]] += 1 } @manifest = linter.manifest if PuppetLint.configuration.fix end # Public: Print any problems that were found out to stdout. # # Returns nothing. def print_problems report(@problems) end # Public: Define a new check. # # name - A unique name for the check as a Symbol. # block - The check logic. This must contain a `check` method and optionally # a `fix` method. # # Returns nothing. # # Examples # # PuppetLint.new_check(:foo) do # def check # end # end def self.new_check(name, &block) class_name = name.to_s.split('_').map(&:capitalize).join klass = PuppetLint.const_set("Check#{class_name}", Class.new(PuppetLint::CheckPlugin)) klass.const_set('NAME', name) klass.class_exec(&block) PuppetLint.configuration.add_check(name, klass) PuppetLint::Data.ignore_overrides[name] ||= {} end end # Default configuration options PuppetLint.configuration.defaults require 'puppet-lint/plugins' puppet-lint-2.4.2/lib/puppet-lint/0000755000004100000410000000000013611752231017060 5ustar www-datawww-datapuppet-lint-2.4.2/lib/puppet-lint/version.rb0000644000004100000410000000006013611752231021066 0ustar www-datawww-dataclass PuppetLint VERSION = '2.4.2'.freeze end puppet-lint-2.4.2/lib/puppet-lint/optparser.rb0000644000004100000410000001140213611752231021422 0ustar www-datawww-datarequire 'optparse' # Public: Contains the puppet-lint option parser so that it can be used easily # in multiple places. class PuppetLint::OptParser HELP_TEXT = <<-EOF.freeze puppet-lint Basic Command Line Usage: puppet-lint [OPTIONS] PATH PATH The path to the Puppet manifest. Option: EOF # Public: Initialise a new puppet-lint OptionParser. # # Returns an OptionParser object. def self.build(args = []) opt_parser = OptionParser.new do |opts| opts.banner = HELP_TEXT opts.on('--version', 'Display the current version.') do PuppetLint.configuration.display_version = true end opts.on('--no-config', 'Do not load default puppet-lint option files.') do # nothing to do, option is handled differently end opts.on('-c', '--config FILE', 'Load puppet-lint options from file.') do |file| opts.load(file) end opts.on('--with-context', 'Show where in the manifest the problem is.') do PuppetLint.configuration.with_context = true end opts.on('--with-filename', 'Display the filename before the warning.') do PuppetLint.configuration.with_filename = true end opts.on('--fail-on-warnings', 'Return a non-zero exit status for warnings') do PuppetLint.configuration.fail_on_warnings = true end opts.on( '--error-level LEVEL', [:all, :warning, :error], 'The level of error to return (warning, error or all).' ) do |el| PuppetLint.configuration.error_level = el end opts.on('--show-ignored', 'Show problems that have been ignored by control comments') do PuppetLint.configuration.show_ignored = true end opts.on('--relative', 'Compare module layout relative to the module root') do PuppetLint.configuration.relative = true end opts.on('-l', '--load FILE', 'Load a file containing custom puppet-lint checks.') do |f| load(f) end opts.on('--load-from-puppet MODULEPATH', 'Load plugins from the given Puppet module path.') do |path| path.split(':').each do |p| Dir["#{p}/*/lib/puppet-lint/plugins/*.rb"].each do |file| load(file) end end end opts.on('-f', '--fix', 'Attempt to automatically fix errors') do PuppetLint.configuration.fix = true end opts.on( '--log-format FORMAT', 'Change the log format.', 'Overrides --with-filename.', 'The following placeholders can be used:', '%{filename} - Filename without path.', '%{path} - Path as provided to puppet-lint.', '%{fullpath} - Expanded path to the file.', '%{line} - Line number.', '%{column} - Column number.', '%{kind} - The kind of message (warning, error).', '%{KIND} - Uppercase version of %{kind}.', '%{check} - The name of the check.', '%{message} - The message.' ) do |format| PuppetLint.configuration.log_format = format end opts.on('--json', 'Log output as JSON') do PuppetLint.configuration.json = true end opts.on('--list-checks', 'List available check names.') do PuppetLint.configuration.list_checks = true end opts.separator('') opts.separator(' Checks:') opts.on('--only-checks CHECKS', 'A comma separated list of checks that should be run') do |checks| enable_checks = checks.split(',').map(&:to_sym) PuppetLint.configuration.checks.each do |check| if enable_checks.include?(check) PuppetLint.configuration.send("enable_#{check}") else PuppetLint.configuration.send("disable_#{check}") end end end opts.on('--ignore-paths PATHS', 'A comma separated list of patterns to ignore') do |paths| PuppetLint.configuration.ignore_paths = paths.split(',') end PuppetLint.configuration.checks.each do |check| opts.on("--no-#{check}-check", "Skip the #{check} check.") do PuppetLint.configuration.send("disable_#{check}") end next if PuppetLint.configuration.send("#{check}_enabled?") opts.on("--#{check}-check", "Enable the #{check} check.") do PuppetLint.configuration.send("enable_#{check}") end end end unless args.include?('--no-config') opt_parser.load('/etc/puppet-lint.rc') if ENV.key?('HOME') && File.readable?(ENV['HOME']) home_dotfile_path = File.expand_path('~/.puppet-lint.rc') opt_parser.load(home_dotfile_path) if File.readable?(home_dotfile_path) end opt_parser.load('.puppet-lint.rc') end opt_parser.parse!(args) unless args.empty? opt_parser end end puppet-lint-2.4.2/lib/puppet-lint/lexer.rb0000644000004100000410000003637713611752231020544 0ustar www-datawww-data# encoding: utf-8 require 'pp' require 'strscan' require 'set' require 'puppet-lint/lexer/token' require 'puppet-lint/lexer/string_slurper' class PuppetLint # Internal: A generic error thrown by the lexer when it encounters something # it can't handle. class LexerError < StandardError # Internal: Get the Integer line number of the location of the error. attr_reader :line_no # Internal: Get the Integer column number of the location of the error. attr_reader :column # Internal: Get the String reason for the error (if known). attr_reader :reason # Internal: Initialise a new PuppetLint::LexerError object. # # line_no - The Integer line number of the location of the error. # column - The Integer column number of the location of the error. # reason - A String describing the cause of the error (if known). def initialize(line_no, column, reason = nil) @line_no = line_no @column = column @reason = reason end def to_s "PuppetLint::LexerError: Line:#{line_no} Column: #{column} Reason: #{reason}" end end # Internal: The puppet-lint lexer. Converts your manifest into its tokenised # form. class Lexer def initialize @line_no = 1 @column = 1 end def self.heredoc_queue @heredoc_queue ||= [] end def heredoc_queue self.class.heredoc_queue end # Internal: A Hash whose keys are Strings representing reserved keywords in # the Puppet DSL. # From https://github.com/puppetlabs/puppet/blob/master/lib/puppet/pops/parser/lexer2.rb#L116-L137 # or thereabouts KEYWORDS = { 'case' => true, 'class' => true, 'default' => true, 'define' => true, 'import' => true, 'if' => true, 'elsif' => true, 'else' => true, 'inherits' => true, 'node' => true, 'and' => true, 'or' => true, 'undef' => true, 'false' => true, 'true' => true, 'in' => true, 'unless' => true, 'function' => true, 'type' => true, 'attr' => true, 'private' => true, }.freeze # Internal: A Hash whose keys are Strings representing reserved keywords in # the Puppet DSL when Application Management is enabled # From https://github.com/puppetlabs/puppet/blob/master/lib/puppet/pops/parser/lexer2.rb#L142-L159 # or therabouts # Currently unused APP_MANAGEMENT_TOKENS = { 'application' => true, 'consumes' => true, 'produces' => true, 'site' => true, }.freeze # Internal: A Hash whose keys are Symbols representing token types which # a regular expression can follow. REGEX_PREV_TOKENS = { :NODE => true, :LBRACE => true, :RBRACE => true, :MATCH => true, :NOMATCH => true, :COMMA => true, :LBRACK => true, :IF => true, :ELSIF => true, :LPAREN => true, :EQUALS => true, }.freeze # Internal: some commonly used regular expressions # \t == tab # \v == vertical tab # \f == form feed # \p{Zs} == ASCII + Unicode non-linebreaking whitespace WHITESPACE_RE = RUBY_VERSION == '1.8.7' ? %r{[\t\v\f ]} : %r{[\t\v\f\p{Zs}]} LINE_END_RE = %r{(?:\r\n|\r|\n)} NAME_RE = %r{\A((?:(?:::)?[_a-z0-9][-\w]*)(?:::[a-z0-9][-\w]*)*)} # Internal: An Array of Arrays containing tokens that can be described by # a single regular expression. Each sub-Array contains 2 elements, the # name of the token as a Symbol and a regular expression describing the # value of the token. KNOWN_TOKENS = [ [:WHITESPACE, %r{\A(#{WHITESPACE_RE}+)}], [:TYPE, %r{\A(Integer|Float|Boolean|Regexp|String|Array|Hash|Resource|Class|Collection|Scalar|Numeric|CatalogEntry|Data|Tuple|Struct|Optional|NotUndef|Variant|Enum|Pattern|Any|Callable|Type|Runtime|Undef|Default|Sensitive)\b}], # rubocop:disable Metrics/LineLength [:CLASSREF, %r{\A(((::){0,1}[A-Z][-\w]*)+)}], [:NUMBER, %r{\A\b((?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?))\b}], [:FUNCTION_NAME, %r{#{NAME_RE}(?=\()}], [:NAME, NAME_RE], [:LBRACK, %r{\A(\[)}], [:RBRACK, %r{\A(\])}], [:LBRACE, %r{\A(\{)}], [:RBRACE, %r{\A(\})}], [:LPAREN, %r{\A(\()}], [:RPAREN, %r{\A(\))}], [:ISEQUAL, %r{\A(==)}], [:MATCH, %r{\A(=~)}], [:FARROW, %r{\A(=>)}], [:EQUALS, %r{\A(=)}], [:APPENDS, %r{\A(\+=)}], [:PARROW, %r{\A(\+>)}], [:PLUS, %r{\A(\+)}], [:GREATEREQUAL, %r{\A(>=)}], [:RSHIFT, %r{\A(>>)}], [:GREATERTHAN, %r{\A(>)}], [:LESSEQUAL, %r{\A(<=)}], [:LLCOLLECT, %r{\A(<<\|)}], [:OUT_EDGE, %r{\A(<-)}], [:OUT_EDGE_SUB, %r{\A(<~)}], [:LCOLLECT, %r{\A(<\|)}], [:LSHIFT, %r{\A(<<)}], [:LESSTHAN, %r{\A(<)}], [:NOMATCH, %r{\A(!~)}], [:NOTEQUAL, %r{\A(!=)}], [:NOT, %r{\A(!)}], [:RRCOLLECT, %r{\A(\|>>)}], [:RCOLLECT, %r{\A(\|>)}], [:IN_EDGE, %r{\A(->)}], [:IN_EDGE_SUB, %r{\A(~>)}], [:MINUS, %r{\A(-)}], [:COMMA, %r{\A(,)}], [:DOT, %r{\A(\.)}], [:COLON, %r{\A(:)}], [:SEMIC, %r{\A(;)}], [:QMARK, %r{\A(\?)}], [:BACKSLASH, %r{\A(\\)}], [:TIMES, %r{\A(\*)}], [:MODULO, %r{\A(%)}], [:PIPE, %r{\A(\|)}], ].freeze # Internal: A Hash whose keys are Symbols representing token types which # are considered to be formatting tokens (i.e. tokens that don't contain # code). FORMATTING_TOKENS = { :WHITESPACE => true, :NEWLINE => true, :COMMENT => true, :MLCOMMENT => true, :SLASH_COMMENT => true, :INDENT => true, }.freeze # Internal: Access the internal token storage. # # Returns an Array of PuppetLint::Lexer::Toxen objects. def tokens @tokens ||= [] end # Internal: Convert a Puppet manifest into tokens. # # code - The Puppet manifest to be tokenised as a String. # # Returns an Array of PuppetLint::Lexer::Token objects. # Raises PuppetLint::LexerError if it encounters unexpected characters # (usually the result of syntax errors). def tokenise(code) i = 0 while i < code.size chunk = code[i..-1] found = false KNOWN_TOKENS.each do |type, regex| value = chunk[regex, 1] next if value.nil? i += value.size tokens << if type == :NAME && KEYWORDS.include?(value) new_token(value.upcase.to_sym, value) else new_token(type, value) end found = true break end next if found if var_name = chunk[%r{\A\$((::)?(\w+(-\w+)*::)*\w+(-\w+)*(\[.+?\])*)}, 1] length = var_name.size + 1 opts = if chunk.start_with?('$') { :raw => "$#{var_name}" } else {} end tokens << new_token(:VARIABLE, var_name, opts) elsif chunk =~ %r{\A'.*?'}m str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*'}m) length = str_content.size + 1 tokens << new_token(:SSTRING, str_content[0..-2]) elsif chunk.start_with?('"') slurper = PuppetLint::Lexer::StringSlurper.new(code[i + 1..-1]) begin string_segments = slurper.parse process_string_segments(string_segments) length = slurper.consumed_bytes + 1 rescue PuppetLint::Lexer::StringSlurper::UnterminatedStringError raise PuppetLint::LexerError.new(@line_no, @column, 'unterminated string') end elsif heredoc_name = chunk[%r{\A@\(("?.+?"?(:.+?)?#{WHITESPACE_RE}*(/.*?)?)\)}, 1] heredoc_queue << heredoc_name tokens << new_token(:HEREDOC_OPEN, heredoc_name) length = heredoc_name.size + 3 elsif comment = chunk[%r{\A(#[^\r\n]*)#{LINE_END_RE}?}, 1] length = comment.size comment.sub!(%r{#}, '') tokens << new_token(:COMMENT, comment) elsif slash_comment = chunk[%r{\A(//[^\r\n]*)#{LINE_END_RE}?}, 1] length = slash_comment.size slash_comment.sub!(%r{//}, '') tokens << new_token(:SLASH_COMMENT, slash_comment) elsif mlcomment = chunk[%r{\A(/\*.*?\*/)}m, 1] length = mlcomment.size mlcomment_raw = mlcomment.dup mlcomment.sub!(%r{\A/\* ?}, '') mlcomment.sub!(%r{ ?\*/\Z}, '') mlcomment.gsub!(%r{^ *\*}, '') tokens << new_token(:MLCOMMENT, mlcomment, :raw => mlcomment_raw) elsif chunk.match(%r{\A/.*?/}m) && possible_regex? str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*/}m) length = str_content.size + 1 tokens << new_token(:REGEX, str_content[0..-2]) elsif eolindent = chunk[%r{\A(#{LINE_END_RE}#{WHITESPACE_RE}+)}m, 1] eol = eolindent[%r{\A(#{LINE_END_RE})}m, 1] tokens << new_token(:NEWLINE, eol) length = eol.size if heredoc_queue.empty? indent = eolindent[%r{\A#{LINE_END_RE}+(#{WHITESPACE_RE}+)}m, 1] tokens << new_token(:INDENT, indent) length += indent.size else heredoc_tag = heredoc_queue.shift slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..-1]) heredoc_segments = slurper.parse_heredoc(heredoc_tag) process_heredoc_segments(heredoc_segments) length += slurper.consumed_bytes end elsif eol = chunk[%r{\A(#{LINE_END_RE})}, 1] length = eol.size tokens << new_token(:NEWLINE, eol) unless heredoc_queue.empty? heredoc_tag = heredoc_queue.shift slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..-1]) heredoc_segments = slurper.parse_heredoc(heredoc_tag) process_heredoc_segments(heredoc_segments) length += slurper.consumed_bytes end elsif chunk.start_with?('/') length = 1 tokens << new_token(:DIV, '/') elsif chunk.start_with?('@') length = 1 tokens << new_token(:AT, '@') else raise PuppetLint::LexerError.new(@line_no, @column) end i += length end tokens end # Internal: Given the tokens already processed, determine if the next token # could be a regular expression. # # Returns true if the next token could be a regex, otherwise return false. def possible_regex? prev_token = tokens.reject { |r| FORMATTING_TOKENS.include?(r.type) }.last return true if prev_token.nil? REGEX_PREV_TOKENS.include?(prev_token.type) end # Internal: Create a new PuppetLint::Lexer::Token object, calculate its # line number and column and then add it to the Linked List of tokens. # # type - The Symbol token type. # value - The token value. # opts - A Hash of additional values required to determine line number and # column: # :line - The Integer line number if calculated externally. # :column - The Integer column number if calculated externally. # :raw - The String raw value of the token (if necessary). # # Returns the instantiated PuppetLint::Lexer::Token object. def new_token(type, value, *args) # This bit of magic is used instead of an "opts = {}" argument so that we # can safely deprecate the old "length" parameter that might still be # passed by 3rd party plugins that haven't updated yet. opts = args.last.is_a?(Hash) ? args.last : {} # column number is calculated at the end of this method by calling # to_manifest on the token. Because the string tokens (DQPRE, DQMID etc) # are parsed before the variable token, they default to assuming that # they are followed by an enclosed variable and we need to remove 2 from # the column number if we encounter an unenclosed variable because of the # missing ${ at the end of the token value. @column -= 2 if type == :UNENC_VARIABLE column = opts[:column] || @column line_no = opts[:line] || @line_no token = Token.new(type, value, line_no, column) unless tokens.last.nil? token.prev_token = tokens.last tokens.last.next_token = token unless FORMATTING_TOKENS.include?(token.type) prev_nf_idx = tokens.rindex { |r| !FORMATTING_TOKENS.include?(r.type) } unless prev_nf_idx.nil? prev_nf_token = tokens[prev_nf_idx] prev_nf_token.next_code_token = token token.prev_code_token = prev_nf_token end end end token.raw = opts[:raw] if opts[:raw] if type == :NEWLINE @line_no += 1 @column = 1 else lines = token.to_manifest.split(LINE_END_RE, -1) @line_no += lines.length - 1 if lines.length > 1 # if the token renders to multiple lines, set the column state to the # length of the last line plus 1 (because column numbers are # 1 indexed) @column = lines.last.size + 1 else @column += (lines.last || '').size end end token end def process_string_segments(segments) return if segments.empty? if segments.length == 1 tokens << new_token(:STRING, segments[0][1]) return end pre_segment = segments.delete_at(0) post_segment = segments.delete_at(-1) tokens << new_token(:DQPRE, pre_segment[1]) segments.each do |segment| case segment[0] when :INTERP lexer = PuppetLint::Lexer.new lexer.tokenise(segment[1]) lexer.tokens.each_with_index do |t, i| type = i.zero? && (t.type == :NAME || KEYWORDS.include?(t.type.to_s.downcase)) ? :VARIABLE : t.type tokens << new_token(type, t.value, :raw => t.raw) end when :UNENC_VAR tokens << new_token(:UNENC_VARIABLE, segment[1].gsub(%r{\A\$}, '')) else tokens << new_token(:DQMID, segment[1]) end end tokens << new_token(:DQPOST, post_segment[1]) end def process_heredoc_segments(segments) return if segments.empty? end_tag = segments.delete_at(-1) if segments.length == 1 tokens << new_token(:HEREDOC, segments[0][1], :raw => "#{segments[0][1]}#{end_tag[1]}") return end pre_segment = segments.delete_at(0) post_segment = segments.delete_at(-1) tokens << new_token(:HEREDOC_PRE, pre_segment[1]) segments.each do |segment| case segment[0] when :INTERP lexer = PuppetLint::Lexer.new lexer.tokenise(segment[1]) lexer.tokens.each_with_index do |t, i| type = i.zero? && t.type == :NAME ? :VARIABLE : t.type tokens << new_token(type, t.value, :raw => t.raw) end when :UNENC_VAR tokens << new_token(:UNENC_VARIABLE, segment[1].gsub(%r{\A\$}, '')) else tokens << new_token(:HEREDOC_MID, segment[1]) end end tokens << new_token(:HEREDOC_POST, post_segment[1], :raw => "#{post_segment[1]}#{end_tag[1]}") end end end puppet-lint-2.4.2/lib/puppet-lint/tasks/0000755000004100000410000000000013611752231020205 5ustar www-datawww-datapuppet-lint-2.4.2/lib/puppet-lint/tasks/puppet-lint.rb0000644000004100000410000000535713611752231023025 0ustar www-datawww-datarequire 'puppet-lint' require 'puppet-lint/optparser' require 'rake' require 'rake/tasklib' class PuppetLint # Public: A Rake task that can be loaded and used with everything you need. # # Examples # # require 'puppet-lint' # PuppetLint::RakeTask.new class RakeTask < ::Rake::TaskLib include ::Rake::DSL if defined?(::Rake::DSL) DEFAULT_PATTERN = '**/*.pp'.freeze attr_accessor :name attr_accessor :pattern attr_accessor :ignore_paths attr_accessor :with_filename attr_accessor :disable_checks attr_accessor :fail_on_warnings attr_accessor :error_level attr_accessor :log_format attr_accessor :with_context attr_accessor :fix attr_accessor :show_ignored attr_accessor :relative # Public: Initialise a new PuppetLint::RakeTask. # # args - Not used. # # Example # # PuppetLint::RakeTask.new def initialize(*args, &task_block) @name = args.shift || :lint @pattern = DEFAULT_PATTERN @with_filename = true @disable_checks = [] @ignore_paths = [] define(args, &task_block) end def define(args, &task_block) desc 'Run puppet-lint' task_block.call(*[self, args].slice(0, task_block.arity)) if task_block # clear any (auto-)pre-existing task Rake::Task[@name].clear if Rake::Task.task_defined?(@name) task @name do PuppetLint::OptParser.build Array(@disable_checks).each do |check| PuppetLint.configuration.send("disable_#{check}") end %w[with_filename fail_on_warnings error_level log_format with_context fix show_ignored relative].each do |config| value = instance_variable_get("@#{config}") PuppetLint.configuration.send("#{config}=".to_sym, value) unless value.nil? end if PuppetLint.configuration.ignore_paths && @ignore_paths.empty? @ignore_paths = PuppetLint.configuration.ignore_paths end if PuppetLint.configuration.pattern @pattern = PuppetLint.configuration.pattern end RakeFileUtils.send(:verbose, true) do linter = PuppetLint.new matched_files = FileList[@pattern] matched_files = matched_files.exclude(*@ignore_paths) matched_files.to_a.each do |puppet_file| linter.file = puppet_file linter.run linter.print_problems if PuppetLint.configuration.fix && linter.problems.none? { |e| e[:check] == :syntax } IO.write(puppet_file, linter.manifest) end end abort if linter.errors? || ( linter.warnings? && PuppetLint.configuration.fail_on_warnings ) end end end end end PuppetLint::RakeTask.new puppet-lint-2.4.2/lib/puppet-lint/tasks/release_test.rb0000644000004100000410000000657613611752231023227 0ustar www-datawww-datarequire 'rake' require 'open3' require 'English' def run_cmd(message, *cmd) print(" #{message}... ") if Open3.respond_to?(:capture2e) output, status = Open3.capture2e(*cmd) else output = '' Open3.popen3(*cmd) do |stdin, stdout, stderr| stdin.close output += stdout.read output += stderr.read end status = $CHILD_STATUS.dup end if status.success? puts 'Done' else puts 'FAILED' end [output.strip, status.success?] end def with_puppet_lint_head print(' Updating Gemfile to use puppet-lint HEAD... ') buffer = Parser::Source::Buffer.new('Gemfile') buffer.source = File.read('Gemfile') parser = Parser::CurrentRuby.new ast = parser.parse(buffer) modified_gemfile = GemfileRewrite.new.rewrite(buffer, ast) if modified_gemfile == buffer.source puppet_lint_root = File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) File.open('Gemfile', 'a') do |f| f.puts "gem 'puppet-lint', :path => '#{puppet_lint_root}'" end else File.open('Gemfile', 'w') do |f| f.puts modified_gemfile end end puts 'Done' Bundler.with_clean_env { yield } run_cmd('Restoring Gemfile', 'git', 'checkout', '--', 'Gemfile') end task :release_test do branch = if ENV['APPVEYOR'] ENV['APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH'] elsif ENV['TRAVIS'] ENV['TRAVIS_PULL_REQUEST_BRANCH'] else false end if branch && branch !~ %r{\A\d+_\d+_\d+_release\Z} puts 'Skipping release tests on feature branch' exit end if RUBY_VERSION.start_with?('1') puts 'Unable to run release_tests on Ruby < 2.0' exit end require 'puppet-lint/tasks/gemfile_rewrite' modules_to_test = [ 'puppetlabs/puppetlabs-apt', 'puppetlabs/puppetlabs-tomcat', 'puppetlabs/puppetlabs-apache', 'puppetlabs/puppetlabs-mysql', 'puppetlabs/puppetlabs-ntp', 'puppetlabs/puppetlabs-chocolatey', 'voxpupuli/puppet-archive', 'voxpupuli/puppet-collectd', 'garethr/garethr-docker', 'sensu/sensu-puppet', 'jenkinsci/puppet-jenkins', ] FileUtils.mkdir_p('tmp') Dir.chdir('tmp') do modules_to_test.each do |module_name| puts "Testing #{module_name}..." module_dir = File.basename(module_name) if File.directory?(module_dir) Dir.chdir(module_dir) do _, success = run_cmd('Updating repository', 'git', 'pull', '--rebase') next unless success end else _, success = run_cmd('Cloning repository', 'git', 'clone', "https://github.com/#{module_name}") next unless success end Dir.chdir(module_dir) do with_puppet_lint_head do _, success = run_cmd('Installing dependencies', 'bundle', 'install', '--path', File.join('..', 'vendor', 'gems')) next unless success output, success = run_cmd('Running puppet-lint CLI', 'bundle', 'exec', 'puppet-lint', '--relative', '--no-documentation-check', 'manifests') unless output.empty? output.split("\n").each do |line| puts " #{line}" end end output, success = run_cmd('Running puppet-lint Rake task', 'bundle', 'exec', 'rake', 'lint') unless output.empty? output.split("\n").each do |line| puts " #{line}" end end end end end end end puppet-lint-2.4.2/lib/puppet-lint/tasks/gemfile_rewrite.rb0000644000004100000410000000122513611752231023703 0ustar www-datawww-datarequire 'parser/current' # Simple rewriter using whitequark/parser that rewrites the "gem 'puppet-lint'" # entry in the module's Gemfile (if present) to instead use the local # puppet-lint working directory. class GemfileRewrite < Parser::TreeRewriter def on_send(node) _, method_name, *args = *node if method_name == :gem gem_name = args.first if gem_name.type == :str && gem_name.children.first == 'puppet-lint' puppet_lint_root = File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) replace(node.location.expression, "gem 'puppet-lint', :path => '#{puppet_lint_root}'") end end super end end puppet-lint-2.4.2/lib/puppet-lint/monkeypatches.rb0000644000004100000410000000201513611752231022255 0ustar www-datawww-databegin '%{test}' % { :test => 'replaced' } == 'replaced' # rubocop:disable Style/FormatString rescue # monkeypatch String#% into Ruby 1.8.7 class String Percent = instance_method('%') unless defined?(Percent) def %(*a, &b) a.flatten! string = case a.last when Hash expand(a.pop) else self end if a.empty? string else Percent.bind(string).call(a, &b) end end def expand!(vars = {}) loop do changed = false vars.each do |var, value| var = var.to_s var.gsub!(%r{[^a-zA-Z0-9_]}, '') changed = gsub!(%r{\%\{#{var}\}}, value.to_s) end break unless changed end self end def expand(opts = {}) dup.expand!(opts) end end end unless String.respond_to?(:prepend) # monkeypatch String#prepend into Ruby 1.8.7 class String def prepend(lead) replace("#{lead}#{self}") end end end puppet-lint-2.4.2/lib/puppet-lint/checks.rb0000644000004100000410000000724413611752231020654 0ustar www-datawww-datarequire 'puppet-lint/checkplugin' # Internal: Various methods that orchestrate the actions of the puppet-lint # check plugins. class PuppetLint::Checks # Public: Get an Array of problem Hashes. attr_accessor :problems # Public: Initialise a new PuppetLint::Checks object. def initialize @problems = [] end # Internal: Tokenise the manifest code and prepare it for checking. # # path - The path to the file as passed to puppet-lint as a String. # content - The String manifest code to be checked. # # Returns nothing. def load_data(path, content) lexer = PuppetLint::Lexer.new PuppetLint::Data.path = path PuppetLint::Data.manifest_lines = content.split("\n", -1) begin PuppetLint::Data.tokens = lexer.tokenise(content) PuppetLint::Data.parse_control_comments rescue PuppetLint::LexerError => e message = if e.reason.nil? 'Syntax error' else "Syntax error (#{e.reason})" end problems << { :kind => :error, :check => :syntax, :message => message, :line => e.line_no, :column => e.column, :fullpath => PuppetLint::Data.fullpath, :path => PuppetLint::Data.path, :filename => PuppetLint::Data.filename, } PuppetLint::Data.tokens = [] end end # Internal: Run the lint checks over the manifest code. # # fileinfo - The path to the file as passed to puppet-lint as a String. # data - The String manifest code to be checked. # # Returns an Array of problem Hashes. def run(fileinfo, data) load_data(fileinfo, data) checks_run = [] enabled_checks.each do |check| klass = PuppetLint.configuration.check_object[check].new # FIXME: shadowing #problems problems = klass.run checks_run << [klass, problems] end checks_run.each do |klass, problems| if PuppetLint.configuration.fix @problems.concat(klass.fix_problems) else @problems.concat(problems) end end @problems rescue PuppetLint::SyntaxError => e @problems << { :kind => :error, :check => :syntax, :message => 'Syntax error', :fullpath => File.expand_path(fileinfo, ENV['PWD']), :filename => File.basename(fileinfo), :path => fileinfo, :line => e.token.line, :column => e.token.column, } @problems rescue => e $stdout.puts <<-END.gsub(%r{^ {6}}, '') Whoops! It looks like puppet-lint has encountered an error that it doesn't know how to handle. Please open an issue at https://github.com/rodjek/puppet-lint and paste the following output into the issue description. --- puppet-lint version: #{PuppetLint::VERSION} ruby version: #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} platform: #{RUBY_PLATFORM} file path: #{fileinfo} END if File.readable?(fileinfo) $stdout.puts [ 'file contents:', '```', File.read(fileinfo), '```', ].join("\n") end $stdout.puts [ 'error:', '```', "#{e.class}: #{e.message}", e.backtrace.join("\n"), '```', ].join("\n") exit 1 end # Internal: Get a list of checks that have not been disabled. # # Returns an Array of String check names. def enabled_checks @enabled_checks ||= begin PuppetLint.configuration.checks.select do |check| PuppetLint.configuration.send("#{check}_enabled?") end end end # Internal: Render the fixed manifest. # # Returns the manifest as a String. def manifest PuppetLint::Data.tokens.map(&:to_manifest).join('') end end puppet-lint-2.4.2/lib/puppet-lint/configuration.rb0000644000004100000410000000762613611752231022267 0ustar www-datawww-dataclass PuppetLint # Public: A singleton class to store the running configuration of # puppet-lint. class Configuration # Internal: Add helper methods for a new check to the # PuppetLint::Configuration object. # # check - The String name of the check. # # Returns nothing. # # Signature # # _enabled? # disable_ # enable_ def self.add_check(check) # Public: Determine if the named check is enabled. # # Returns true if the check is enabled, otherwise return false. define_method("#{check}_enabled?") do settings["#{check}_disabled"] == true ? false : true end # Public: Disable the named check. # # Returns nothing. define_method("disable_#{check}") do settings["#{check}_disabled"] = true end # Public: Enable the named check. # # Returns nothing. define_method("enable_#{check}") do settings["#{check}_disabled"] = false end end # Public: Catch situations where options are being set for the first time # and create the necessary methods to get & set the option in the future. # # args - An Array of values to set the option to. # method - The String name of the option. # block - Unused. # # Returns nothing. # # Signature # #