diff --git a/.rubocop.yml b/.rubocop.yml index 33c33fa..6a240fe 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,534 +1,515 @@ --- require: - rubocop-performance - rubocop-rspec AllCops: DisplayCopNames: true TargetRubyVersion: '2.4' Include: - "**/*.rb" Exclude: - bin/* - ".vendor/**/*" - "**/Gemfile" - "**/Rakefile" - pkg/**/* - spec/fixtures/**/* - vendor/**/* - "**/Puppetfile" - "**/Vagrantfile" - "**/Guardfile" +inherit_from: ".rubocop_todo.yml" Layout/LineLength: Description: People have wide screens, use them. Max: 200 RSpec/BeforeAfterAll: Description: Beware of using after(:all) as it may cause state to leak between tests. A necessary evil in acceptance testing. Exclude: - spec/acceptance/**/*.rb RSpec/HookArgument: Description: Prefer explicit :each argument, matching existing module's style EnforcedStyle: each Style/BlockDelimiters: Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to be consistent then. EnforcedStyle: braces_for_chaining Style/ClassAndModuleChildren: Description: Compact style reduces the required amount of indentation. EnforcedStyle: compact Style/EmptyElse: Description: Enforce against empty else clauses, but allow `nil` for clarity. EnforcedStyle: empty Style/FormatString: Description: Following the main puppet project's style, prefer the % format format. EnforcedStyle: percent Style/FormatStringToken: Description: Following the main puppet project's style, prefer the simpler template tokens over annotated ones. EnforcedStyle: template Style/Lambda: Description: Prefer the keyword for easier discoverability. EnforcedStyle: literal Style/RegexpLiteral: Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 EnforcedStyle: percent_r Style/TernaryParentheses: Description: Checks for use of parentheses around ternary conditions. Enforce parentheses on complex expressions for better readability, but seriously consider breaking it up. EnforcedStyle: require_parentheses_when_complex Style/TrailingCommaInArguments: Description: Prefer always trailing comma on multiline argument lists. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/TrailingCommaInArrayLiteral: Description: Prefer always trailing comma on multiline literals. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets RSpec/MessageSpies: EnforcedStyle: receive Style/Documentation: Exclude: - lib/puppet/parser/functions/**/* - spec/**/* Style/WordArray: EnforcedStyle: brackets Performance/AncestorsInclude: Enabled: true Performance/BigDecimalWithNumericArgument: Enabled: true Performance/BlockGivenWithExplicitBlock: Enabled: true -Performance/Caller: - Enabled: true Performance/CaseWhenSplat: Enabled: true -Performance/Casecmp: - Enabled: true -Performance/CollectionLiteralInLoop: - Enabled: true -Performance/CompareWithBlock: - Enabled: true Performance/ConstantRegexp: Enabled: true -Performance/Count: - Enabled: true -Performance/Detect: - Enabled: true -Performance/DoubleStartEndWith: - Enabled: true -Performance/EndWith: - Enabled: true -Performance/FixedSize: - Enabled: true -Performance/FlatMap: - Enabled: true Performance/MethodObjectAsBlock: Enabled: true -Performance/RangeInclude: - Enabled: true -Performance/RedundantBlockCall: - Enabled: true -Performance/RedundantMatch: - Enabled: true -Performance/RedundantMerge: - Enabled: true Performance/RedundantSortBlock: Enabled: true Performance/RedundantStringChars: Enabled: true -Performance/RegexpMatch: - Enabled: true -Performance/ReverseEach: - Enabled: true Performance/ReverseFirst: Enabled: true -Performance/Size: - Enabled: true Performance/SortReverse: Enabled: true Performance/Squeeze: Enabled: true -Performance/StartWith: - Enabled: true Performance/StringInclude: Enabled: true -Performance/StringReplacement: - Enabled: true Performance/Sum: Enabled: true -Performance/TimesMap: - Enabled: true Style/CollectionMethods: Enabled: true Style/MethodCalledOnDoEndBlock: Enabled: true Style/StringMethods: Enabled: true Bundler/InsecureProtocolSource: Enabled: false Gemspec/DuplicatedAssignment: Enabled: false Gemspec/OrderedDependencies: Enabled: false Gemspec/RequiredRubyVersion: Enabled: false Gemspec/RubyVersionGlobalsUsage: Enabled: false Layout/ArgumentAlignment: Enabled: false Layout/BeginEndAlignment: Enabled: false Layout/ClosingHeredocIndentation: Enabled: false Layout/EmptyComment: Enabled: false Layout/EmptyLineAfterGuardClause: Enabled: false Layout/EmptyLinesAroundArguments: Enabled: false Layout/EmptyLinesAroundAttributeAccessor: Enabled: false Layout/EndOfLine: Enabled: false Layout/FirstArgumentIndentation: Enabled: false Layout/HashAlignment: Enabled: false Layout/HeredocIndentation: Enabled: false Layout/LeadingEmptyLines: Enabled: false Layout/SpaceAroundMethodCallOperator: Enabled: false Layout/SpaceInsideArrayLiteralBrackets: Enabled: false Layout/SpaceInsideReferenceBrackets: Enabled: false Lint/BigDecimalNew: Enabled: false Lint/BooleanSymbol: Enabled: false Lint/ConstantDefinitionInBlock: Enabled: false Lint/DeprecatedOpenSSLConstant: Enabled: false Lint/DisjunctiveAssignmentInConstructor: Enabled: false -Lint/DuplicateBranch: - Enabled: false Lint/DuplicateElsifCondition: Enabled: false -Lint/DuplicateRegexpCharacterClassElement: - Enabled: false Lint/DuplicateRequire: Enabled: false Lint/DuplicateRescueException: Enabled: false -Lint/EmptyBlock: - Enabled: false -Lint/EmptyClass: - Enabled: false Lint/EmptyConditionalBody: Enabled: false Lint/EmptyFile: Enabled: false Lint/ErbNewArguments: Enabled: false Lint/FloatComparison: Enabled: false Lint/HashCompareByIdentity: Enabled: false Lint/IdentityComparison: Enabled: false Lint/InterpolationCheck: Enabled: false Lint/MissingCopEnableDirective: Enabled: false Lint/MixedRegexpCaptureTypes: Enabled: false Lint/NestedPercentLiteral: Enabled: false -Lint/NoReturnInBeginEndBlocks: - Enabled: false Lint/NonDeterministicRequireOrder: Enabled: false Lint/OrderedMagicComments: Enabled: false Lint/OutOfRangeRegexpRef: Enabled: false Lint/RaiseException: Enabled: false Lint/RedundantCopEnableDirective: Enabled: false Lint/RedundantRequireStatement: Enabled: false Lint/RedundantSafeNavigation: Enabled: false Lint/RedundantWithIndex: Enabled: false Lint/RedundantWithObject: Enabled: false Lint/RegexpAsCondition: Enabled: false Lint/ReturnInVoidContext: Enabled: false Lint/SafeNavigationConsistency: Enabled: false Lint/SafeNavigationWithEmpty: Enabled: false Lint/SelfAssignment: Enabled: false Lint/SendWithMixinArgument: Enabled: false Lint/ShadowedArgument: Enabled: false Lint/StructNewOverride: Enabled: false -Lint/ToEnumArguments: - Enabled: false Lint/ToJSON: Enabled: false Lint/TopLevelReturnWithArgument: Enabled: false Lint/TrailingCommaInAttributeDeclaration: Enabled: false -Lint/UnexpectedBlockArity: - Enabled: false -Lint/UnmodifiedReduceAccumulator: - Enabled: false Lint/UnreachableLoop: Enabled: false Lint/UriEscapeUnescape: Enabled: false Lint/UriRegexp: Enabled: false Lint/UselessMethodDefinition: Enabled: false Lint/UselessTimes: Enabled: false Metrics/AbcSize: Enabled: false Metrics/BlockLength: Enabled: false +Metrics/BlockNesting: + Enabled: false Metrics/ClassLength: Enabled: false Metrics/CyclomaticComplexity: Enabled: false Metrics/MethodLength: Enabled: false Metrics/ModuleLength: Enabled: false Metrics/ParameterLists: Enabled: false Metrics/PerceivedComplexity: Enabled: false Migration/DepartmentName: Enabled: false +Naming/AccessorMethodName: + Enabled: false Naming/BlockParameterName: Enabled: false Naming/HeredocDelimiterCase: Enabled: false Naming/HeredocDelimiterNaming: Enabled: false Naming/MemoizedInstanceVariableName: Enabled: false Naming/MethodParameterName: Enabled: false Naming/RescuedExceptionsVariableName: Enabled: false +Naming/VariableNumber: + Enabled: false +Performance/BindCall: + Enabled: false +Performance/DeletePrefix: + Enabled: false +Performance/DeleteSuffix: + Enabled: false +Performance/InefficientHashSearch: + Enabled: false +Performance/UnfreezeString: + Enabled: false +Performance/UriDefaultParser: + Enabled: false RSpec/Be: Enabled: false RSpec/Capybara/CurrentPathExpectation: Enabled: false RSpec/Capybara/FeatureMethods: Enabled: false RSpec/Capybara/VisibilityMatcher: Enabled: false RSpec/ContextMethod: Enabled: false RSpec/ContextWording: Enabled: false RSpec/DescribeClass: Enabled: false RSpec/EmptyHook: Enabled: false RSpec/EmptyLineAfterExample: Enabled: false RSpec/EmptyLineAfterExampleGroup: Enabled: false RSpec/EmptyLineAfterHook: Enabled: false RSpec/ExampleLength: Enabled: false RSpec/ExampleWithoutDescription: Enabled: false RSpec/ExpectChange: Enabled: false RSpec/ExpectInHook: Enabled: false RSpec/FactoryBot/AttributeDefinedStatically: Enabled: false RSpec/FactoryBot/CreateList: Enabled: false RSpec/FactoryBot/FactoryClassName: Enabled: false RSpec/HooksBeforeExamples: Enabled: false RSpec/ImplicitBlockExpectation: Enabled: false RSpec/ImplicitSubject: Enabled: false RSpec/LeakyConstantDeclaration: Enabled: false RSpec/LetBeforeExamples: Enabled: false RSpec/MissingExampleGroupArgument: Enabled: false RSpec/MultipleExpectations: Enabled: false RSpec/MultipleMemoizedHelpers: Enabled: false RSpec/MultipleSubjects: Enabled: false RSpec/NestedGroups: Enabled: false RSpec/PredicateMatcher: Enabled: false RSpec/ReceiveCounts: Enabled: false RSpec/ReceiveNever: Enabled: false RSpec/RepeatedExampleGroupBody: Enabled: false RSpec/RepeatedExampleGroupDescription: Enabled: false RSpec/RepeatedIncludeExample: Enabled: false RSpec/ReturnFromStub: Enabled: false RSpec/SharedExamples: Enabled: false RSpec/StubbedMock: Enabled: false RSpec/UnspecifiedException: Enabled: false RSpec/VariableDefinition: Enabled: false RSpec/VoidExpect: Enabled: false RSpec/Yield: Enabled: false Security/Open: Enabled: false Style/AccessModifierDeclarations: Enabled: false Style/AccessorGrouping: Enabled: false -Style/ArgumentsForwarding: - Enabled: false Style/AsciiComments: Enabled: false Style/BisectedAttrAccessor: Enabled: false Style/CaseLikeIf: Enabled: false Style/ClassEqualityComparison: Enabled: false -Style/CollectionCompact: - Enabled: false Style/ColonMethodDefinition: Enabled: false Style/CombinableLoops: Enabled: false Style/CommentedKeyword: Enabled: false Style/Dir: Enabled: false -Style/DocumentDynamicEvalDefinition: - Enabled: false Style/DoubleCopDisableDirective: Enabled: false Style/EmptyBlockParameter: Enabled: false Style/EmptyLambdaParameter: Enabled: false Style/Encoding: Enabled: false Style/EvalWithLocation: Enabled: false Style/ExpandPathArguments: Enabled: false Style/ExplicitBlockArgument: Enabled: false Style/ExponentialNotation: Enabled: false Style/FloatDivision: Enabled: false Style/GlobalStdStream: Enabled: false Style/HashAsLastArrayItem: Enabled: false Style/HashLikeCase: Enabled: false Style/HashTransformKeys: Enabled: false Style/HashTransformValues: Enabled: false Style/IfUnlessModifier: Enabled: false Style/KeywordParametersOrder: Enabled: false Style/MinMax: Enabled: false Style/MixinUsage: Enabled: false Style/MultilineWhenThen: Enabled: false -Style/NegatedIfElseCondition: - Enabled: false Style/NegatedUnless: Enabled: false -Style/NilLambda: - Enabled: false Style/NumericPredicate: Enabled: false Style/OptionalBooleanParameter: Enabled: false Style/OrAssignment: Enabled: false Style/RandomWithOffset: Enabled: false -Style/RedundantArgument: - Enabled: false Style/RedundantAssignment: Enabled: false Style/RedundantCondition: Enabled: false Style/RedundantConditional: Enabled: false Style/RedundantFetchBlock: Enabled: false Style/RedundantFileExtensionInRequire: Enabled: false Style/RedundantRegexpCharacterClass: Enabled: false Style/RedundantRegexpEscape: Enabled: false Style/RedundantSelfAssignment: Enabled: false Style/RedundantSort: Enabled: false Style/RescueStandardError: Enabled: false Style/SingleArgumentDig: Enabled: false Style/SlicingWithRange: Enabled: false Style/SoleNestedConditional: Enabled: false Style/StderrPuts: Enabled: false Style/StringConcatenation: Enabled: false Style/Strip: Enabled: false -Style/SwapValues: - Enabled: false Style/SymbolProc: Enabled: false Style/TrailingBodyOnClass: Enabled: false Style/TrailingBodyOnMethodDefinition: Enabled: false Style/TrailingBodyOnModule: Enabled: false Style/TrailingCommaInHashLiteral: Enabled: false Style/TrailingMethodEndStatement: Enabled: false Style/UnpackFirst: Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NilLambda: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..c3fb692 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,26 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2020-12-17 20:35:36 UTC using RuboCop version 1.6.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: 6 +# Configuration parameters: AllowComments. +Lint/SuppressedException: + Exclude: + - 'lib/facter/facter_dot_d.rb' + - 'lib/puppet/functions/merge.rb' + - 'lib/puppet/parser/functions/getvar.rb' + - 'lib/puppet/parser/functions/has_interface_with.rb' + +# Offense count: 62 +# Configuration parameters: IgnoreSharedExamples. +RSpec/NamedSubject: + Enabled: false + +# Offense count: 2 +RSpec/SubjectStub: + Exclude: + - 'spec/unit/facter/facter_dot_d_spec.rb' diff --git a/.sync.yml b/.sync.yml index 9ca7a01..92c9a14 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,65 +1,67 @@ --- ".gitlab-ci.yml": delete: true +".rubocop.yml": + include_todos: true ".travis.yml": global_env: - HONEYCOMB_WRITEKEY="7f3c63a70eecc61d635917de46bea4e6",HONEYCOMB_DATASET="litmus tests" deploy_to_forge: enabled: false dist: trusty user: puppet secure: '' branches: - release use_litmus: true litmus: provision_list: - ---travis_el - travis_deb - travis_el7 - travis_el8 complex: - collection: puppet_collection: - puppet6 provision_list: - travis_ub_6 - collection: puppet_collection: - puppet5 provision_list: - travis_ub_5 simplecov: true notifications: slack: secure: j5y9T97u6QlDPs4eEnDNch2IGAzbfWycVcMutP3u9Klvkgqu33xtxHgyAQOW+2A/Xw2sKQs/LzIiUeQRzlNMcAPRZ0rK19sW1w5OgZGcd131HViFDfX8W7V4R41sZVNF232JekMr7RwPGIaZ9htaGsDJeJF8TaiG1Akk32LQZV8= appveyor.yml: environment: HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6 HONEYCOMB_DATASET: litmus tests use_litmus: true matrix_extras: - RUBY_VERSION: 25-x64 ACCEPTANCE: 'yes' TARGET_HOST: localhost - RUBY_VERSION: 25-x64 ACCEPTANCE: 'yes' TARGET_HOST: localhost APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 simplecov: true Gemfile: optional: ":development": - gem: github_changelog_generator spec/spec_helper.rb: mock_with: ":rspec" coverage_report: true .gitpod.Dockerfile: unmanaged: false .gitpod.yml: unmanaged: false .github/workflows/nightly.yml: unmanaged: false .github/workflows/pr_test.yml: unmanaged: false diff --git a/lib/facter/root_home.rb b/lib/facter/root_home.rb index 8b11f2a..257a182 100644 --- a/lib/facter/root_home.rb +++ b/lib/facter/root_home.rb @@ -1,49 +1,49 @@ # frozen_string_literal: true # root_home.rb module Facter::Util::RootHome # @summary # A facter fact to determine the root home directory. # This varies on PE supported platforms and may be # reconfigured by the end user. class << self # determines the root home directory def returnt_root_home root_ent = Facter::Util::Resolution.exec('getent passwd root') # The home directory is the sixth element in the passwd entry # If the platform doesn't have getent, root_ent will be nil and we should # return it straight away. root_ent && root_ent.split(':')[5] end end end Facter.add(:root_home) do setcode { Facter::Util::RootHome.returnt_root_home } end Facter.add(:root_home) do confine kernel: :darwin setcode do str = Facter::Util::Resolution.exec('dscacheutil -q user -a name root') hash = {} str.split("\n").each do |pair| key, value = pair.split(%r{:}) hash[key] = value end hash['dir'].strip end end Facter.add(:root_home) do confine kernel: :aix root_home = nil setcode do str = Facter::Util::Resolution.exec('lsuser -c -a home root') - str && str.split("\n").each do |line| + str&.split("\n")&.each do |line| next if %r{^#}.match?(line) root_home = line.split(%r{:})[1] end root_home end end diff --git a/lib/puppet/functions/is_a.rb b/lib/puppet/functions/is_a.rb index 6ba6f9f..275d218 100644 --- a/lib/puppet/functions/is_a.rb +++ b/lib/puppet/functions/is_a.rb @@ -1,44 +1,44 @@ # frozen_string_literal: true # @summary # Boolean check to determine whether a variable is of a given data type. # This is equivalent to the `=~` type checks. # # @example Example Usage: # # check a data type # foo = 3 # $bar = [1,2,3] # $baz = 'A string!' # # if $foo.is_a(Integer) { # notify { 'foo!': } # } # if $bar.is_a(Array) { # notify { 'bar!': } # } # if $baz.is_a(String) { # notify { 'baz!': } # } # # See the documentation for "The Puppet Type System" for more information about types. # See the `assert_type()` function for flexible ways to assert the type of a value. # Puppet::Functions.create_function(:is_a) do # @param value # The value to be checked # # @param type # The expected type # # @return [Boolean] # Return's `true` or `false`. dispatch :is_a do param 'Any', :value param 'Type', :type end - def is_a(value, type) # rubocop:disable Style/PredicateName : Used in to many other places to rename at this time, attempting to refactor caused Rubocop to crash. + def is_a(value, type) # rubocop:disable Naming/PredicateName : Used in to many other places to rename at this time, attempting to refactor caused Rubocop to crash. # See puppet's lib/puppet/pops/evaluator/evaluator_impl.rb eval_MatchExpression Puppet::Pops::Types::TypeCalculator.instance?(type, value) end end diff --git a/lib/puppet/parser/functions/assert_private.rb b/lib/puppet/parser/functions/assert_private.rb index 5c504b0..0e64bd6 100644 --- a/lib/puppet/parser/functions/assert_private.rb +++ b/lib/puppet/parser/functions/assert_private.rb @@ -1,33 +1,33 @@ # frozen_string_literal: true # # assert_private.rb # module Puppet::Parser::Functions newfunction(:assert_private, doc: <<-DOC @summary Sets the current class or definition as private. @return set the current class or definition as private. Calling the class or definition from outside the current module will fail. DOC ) do |args| raise(Puppet::ParseError, "assert_private(): Wrong number of arguments given (#{args.size}}) for 0 or 1)") if args.size > 1 scope = self if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name') message = nil - if args[0] && args[0].is_a?(String) + if args[0]&.is_a?(String) message = args[0] else manifest_name = scope.source.name manifest_type = scope.source.type message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition' message += " #{manifest_name} is private" end raise(Puppet::ParseError, message) end end end diff --git a/lib/puppet/parser/functions/getparam.rb b/lib/puppet/parser/functions/getparam.rb index b666710..18b7b51 100644 --- a/lib/puppet/parser/functions/getparam.rb +++ b/lib/puppet/parser/functions/getparam.rb @@ -1,61 +1,61 @@ # frozen_string_literal: true # Test whether a given class or definition is defined require 'puppet/parser/functions' Puppet::Parser::Functions.newfunction(:getparam, type: :rvalue, doc: <<-'DOC', @summary Returns the value of a resource's parameter. @return value of a resource's parameter. Takes a resource reference and name of the parameter and returns value of resource's parameter. Note that user defined resource types are evaluated lazily. @example Example Usage: # define a resource type with a parameter define example_resource($param) { } # declare an instance of that type example_resource { "example_resource_instance": param => "'the value we are getting in this example''" } # Because of order of evaluation, a second definition is needed # that will be evaluated after the first resource has been declared # define example_get_param { # This will notice the value of the parameter notice(getparam(Example_resource["example_resource_instance"], "param")) } # Declare an instance of the second resource type - this will call notice example_get_param { 'show_notify': } Would notice: 'the value we are getting in this example' > **Note** that since Puppet 4.0.0 it is possible to get a parameter value by using its data type and the [ ] operator. The example below is equivalent to a call to getparam(): ```Example_resource['example_resource_instance']['param']`` DOC ) do |vals| reference, param = vals raise(ArgumentError, 'Must specify a reference') unless reference - raise(ArgumentError, 'Must specify name of a parameter') unless param && param.instance_of?(String) + raise(ArgumentError, 'Must specify name of a parameter') unless param&.instance_of?(String) return '' if param.empty? resource = findresource(reference.to_s) if resource return resource[param] unless resource[param].nil? end return '' end diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb index 9fb281c..41e0531 100644 --- a/lib/puppet/provider/file_line/ruby.rb +++ b/lib/puppet/provider/file_line/ruby.rb @@ -1,182 +1,182 @@ # frozen_string_literal: true Puppet::Type.type(:file_line).provide(:ruby) do desc <<-DOC @summary This type allows puppet to manage small config files. The implementation matches the full line, including whitespace at the beginning and end. If the line is not contained in the given file, Puppet will append the line to the end of the file to ensure the desired state. Multiple resources may be declared to manage multiple lines in the same file. DOC def exists? found = false lines_count = 0 lines.each do |line| found = line.chomp == resource[:line] if found lines_count += 1 end end return found = lines_count > 0 if resource[:match].nil? match_count = count_matches(new_match_regex) found = if resource[:ensure] == :present if match_count.zero? if lines_count.zero? && resource[:append_on_no_match].to_s == 'false' true # lies, but gets the job done elsif lines_count.zero? && resource[:append_on_no_match].to_s != 'false' false else true end elsif resource[:replace_all_matches_not_matching_line].to_s == 'true' false # maybe lies, but knows there's still work to do elsif lines_count.zero? resource[:replace].to_s == 'false' else true end elsif match_count.zero? if lines_count.zero? false else true end elsif lines_count.zero? resource[:match_for_absence].to_s == 'true' else true end end def create return if resource[:replace].to_s != 'true' && count_matches(new_match_regex) > 0 if resource[:match] handle_create_with_match elsif resource[:after] handle_create_with_after else handle_append_line end end def destroy if resource[:match_for_absence].to_s == 'true' && resource[:match] handle_destroy_with_match else handle_destroy_line end end private def lines # If this type is ever used with very large files, we should # write this in a different way, using a temp # file; for now assuming that this type is only used on # small-ish config files that can fit into memory without # too much trouble. @lines ||= File.readlines(resource[:path], encoding: resource[:encoding]) rescue TypeError => _e # Ruby 1.8 doesn't support open_args @lines ||= File.readlines(resource[:path]) end def new_after_regex resource[:after] ? Regexp.new(resource[:after]) : nil end def new_match_regex resource[:match] ? Regexp.new(resource[:match]) : nil end def count_matches(regex) - lines.select { |line| + lines.count do |line| if resource[:replace_all_matches_not_matching_line].to_s == 'true' line.match(regex) unless line.chomp == resource[:line] else line.match(regex) end - }.size + end end def handle_create_with_match after_regex = new_after_regex match_regex = new_match_regex match_count = count_matches(new_match_regex) if match_count > 1 && resource[:multiple].to_s != 'true' raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'" end File.open(resource[:path], 'w') do |fh| lines.each do |line| fh.puts(match_regex.match(line) ? resource[:line] : line) next unless match_count.zero? && after_regex if after_regex.match(line) fh.puts(resource[:line]) match_count += 1 # Increment match_count to indicate that the new line has been inserted. end end if match_count.zero? fh.puts(resource[:line]) end end end def handle_create_with_after after_regex = new_after_regex after_count = count_matches(after_regex) if after_count > 1 && resource[:multiple].to_s != 'true' raise Puppet::Error, "#{after_count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern." end File.open(resource[:path], 'w') do |fh| lines.each do |line| fh.puts(line) if after_regex.match(line) fh.puts(resource[:line]) end end if after_count.zero? fh.puts(resource[:line]) end end end def handle_destroy_with_match match_regex = new_match_regex match_count = count_matches(match_regex) if match_count > 1 && resource[:multiple].to_s != 'true' raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'" end local_lines = lines File.open(resource[:path], 'w') do |fh| fh.write(local_lines.reject { |line| match_regex.match(line) }.join('')) end end def handle_destroy_line local_lines = lines File.open(resource[:path], 'w') do |fh| fh.write(local_lines.reject { |line| line.chomp == resource[:line] }.join('')) end end def handle_append_line local_lines = lines File.open(resource[:path], 'w') do |fh| local_lines.each do |line| fh.puts(line) end fh.puts(resource[:line]) end end end