diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index 286c98e..97befb3 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -21,26 +21,25 @@ on: jobs: ruby-style: - if: false # TODO Modules will need: rubocop in Gemfile, .rubocop.yml - name: 'Ruby Style (experimental)' + name: 'Ruby Style' runs-on: ubuntu-latest continue-on-error: true steps: - uses: actions/checkout@v6 - - name: "Install Ruby ${{matrix.puppet.ruby_version}}" + - name: "Install Ruby 2.7" uses: ruby/setup-ruby@v1 with: ruby-version: 2.7.8 bundler-cache: true - run: | bundle show - bundle exec rake rubocop + bundle exec rubocop releng-checks: name: 'RELENG checks' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - name: 'Install Ruby ${{matrix.puppet.ruby_version}}' + - name: 'Install Ruby 2.7' uses: ruby/setup-ruby@v1 with: ruby-version: 2.7.8 @@ -76,7 +75,7 @@ jobs: # unit test uses mkisofs and rpmbuild - run: 'command -v mkisofs || if command -v apt-get; then sudo apt-get update; sudo apt-get install -y genisoimage; fi ||:' - run: 'command -v rpmbuild || if command -v apt-get; then sudo apt-get update; sudo apt-get install -y rpm-build; fi ||:' - - run: 'command -v createrepo || if command -v apt-get; then sudo apt-get update; sudo apt-get install -y createrepo; fi ||:' + - run: 'command -v createrepo_c || if command -v apt-get; then sudo apt-get update; sudo apt-get install -y createrepo-c; fi ||:' - run: 'bundle exec rake spec' # dump_contexts: diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..6e2c30d --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,699 @@ +--- +plugins: + - rubocop-performance + - rubocop-rake + - rubocop-rspec +AllCops: + NewCops: enable + DisplayCopNames: true + TargetRubyVersion: 2.7 + Include: + - "**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" +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 +RSpec/DescribeSymbol: + Exclude: + - spec/unit/facter/**/*.rb +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/CaseWhenSplat: + Enabled: true +Performance/ConstantRegexp: + Enabled: true +Performance/MethodObjectAsBlock: + Enabled: true +Performance/RedundantSortBlock: + Enabled: true +Performance/RedundantStringChars: + Enabled: true +Performance/ReverseFirst: + Enabled: true +Performance/SortReverse: + Enabled: true +Performance/Squeeze: + Enabled: true +Performance/StringInclude: + Enabled: true +Performance/Sum: + Enabled: true +Style/CollectionMethods: + Enabled: true +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true +Bundler/GemFilename: + Enabled: false +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: true +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/DuplicateElsifCondition: + Enabled: false +Lint/DuplicateRequire: + Enabled: false +Lint/DuplicateRescueException: + 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/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/ToJSON: + Enabled: false +Lint/TopLevelReturnWithArgument: + Enabled: false +Lint/TrailingCommaInAttributeDeclaration: + 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/Dialect: + Enabled: false +RSpec/ContainExactly: + 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/HooksBeforeExamples: + Enabled: false +RSpec/ImplicitBlockExpectation: + Enabled: false +RSpec/ImplicitSubject: + Enabled: false +RSpec/LeakyConstantDeclaration: + Enabled: false +RSpec/LetBeforeExamples: + Enabled: false +RSpec/MatchArray: + 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/BisectedAttrAccessor: + Enabled: false +Style/CaseLikeIf: + Enabled: false +Style/ClassEqualityComparison: + Enabled: false +Style/ColonMethodDefinition: + Enabled: false +Style/CombinableLoops: + Enabled: false +Style/CommentedKeyword: + Enabled: false +Style/Dir: + 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/FrozenStringLiteralComment: + 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/NegatedUnless: + Enabled: false +Style/NumericPredicate: + Enabled: false +Style/OptionalBooleanParameter: + Enabled: false +Style/OrAssignment: + Enabled: false +Style/RandomWithOffset: + 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/SymbolProc: + Enabled: false +Style/TrailingBodyOnClass: + Enabled: false +Style/TrailingBodyOnMethodDefinition: + Enabled: false +Style/TrailingBodyOnModule: + Enabled: false +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: comma +Style/TrailingMethodEndStatement: + Enabled: false +Style/UnpackFirst: + Enabled: false +Gemspec/DeprecatedAttributeAssignment: + Enabled: false +Gemspec/DevelopmentDependencies: + Enabled: false +Gemspec/RequireMFA: + Enabled: false +Layout/LineContinuationLeadingSpace: + Enabled: false +Layout/LineContinuationSpacing: + Enabled: false +Layout/LineEndStringConcatenationIndentation: + Enabled: false +Layout/SpaceBeforeBrackets: + Enabled: false +Lint/AmbiguousAssignment: + Enabled: false +Lint/AmbiguousOperatorPrecedence: + Enabled: false +Lint/AmbiguousRange: + Enabled: false +Lint/ConstantOverwrittenInRescue: + Enabled: false +Lint/DeprecatedConstants: + Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateMagicComment: + Enabled: false +Lint/DuplicateMatchPattern: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/EmptyInPattern: + Enabled: false +Lint/IncompatibleIoSelectWithFiberScheduler: + Enabled: false +Lint/LambdaWithoutLiteralBlock: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/NonAtomicFileOperation: + Enabled: false +Lint/NumberedParameterAssignment: + Enabled: false +Lint/OrAssignmentToConstant: + Enabled: false +Lint/RedundantDirGlobSort: + Enabled: false +Lint/RefinementImportMethods: + Enabled: false +Lint/RequireRangeParentheses: + Enabled: false +Lint/RequireRelativeSelfPath: + Enabled: false +Lint/SymbolConversion: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/TripleQuotes: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Lint/UselessRescue: + Enabled: false +Lint/UselessRuby2Keywords: + Enabled: false +Metrics/CollectionLiteralLength: + Enabled: false +Naming/BlockForwarding: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Performance/ConcurrentMonotonicTime: + Enabled: false +Performance/MapCompact: + Enabled: false +Performance/RedundantEqualityComparisonBlock: + Enabled: false +Performance/RedundantSplitRegexpArgument: + Enabled: false +Performance/StringIdentifierArgument: + Enabled: false +RSpec/BeEq: + Enabled: false +RSpec/BeNil: + Enabled: false +RSpec/ChangeByZero: + Enabled: false +RSpec/ClassCheck: + Enabled: false +RSpec/DuplicatedMetadata: + Enabled: false +RSpec/ExcessiveDocstringSpacing: + Enabled: false +RSpec/IdenticalEqualityAssertion: + Enabled: false +RSpec/NoExpectationExample: + Enabled: false +RSpec/PendingWithoutReason: + Enabled: false +RSpec/RedundantAround: + Enabled: false +RSpec/SkipBlockInsideExample: + Enabled: false +RSpec/SortMetadata: + Enabled: false +RSpec/SubjectDeclaration: + Enabled: false +RSpec/VerifiedDoubleReference: + Enabled: false +Security/CompoundHash: + Enabled: false +Security/IoMethods: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/ArrayIntersect: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/ComparableClamp: + Enabled: false +Style/ConcatArrayLiterals: + Enabled: false +Style/DataInheritance: + Enabled: false +Style/DirEmpty: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/EmptyHeredoc: + Enabled: false +Style/EndlessMethod: + Enabled: false +Style/EnvHome: + Enabled: false +Style/FetchEnvVar: + Enabled: false +Style/FileEmpty: + Enabled: false +Style/FileRead: + Enabled: false +Style/FileWrite: + Enabled: false +Style/HashConversion: + Enabled: false +Style/HashExcept: + Enabled: false +Style/IfWithBooleanLiteralBranches: + Enabled: false +Style/InPatternThen: + Enabled: false +Style/MagicCommentFormat: + Enabled: false +Style/MapCompactWithConditionalBlock: + Enabled: false +Style/MapToHash: + Enabled: false +Style/MapToSet: + Enabled: false +Style/MinMaxComparison: + Enabled: false +Style/MultilineInPatternThen: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NestedFileDirname: + Enabled: false +Style/NilLambda: + Enabled: false +Style/NumberedParameters: + Enabled: false +Style/NumberedParametersLimit: + Enabled: false +Style/ObjectThen: + Enabled: false +Style/OpenStructUse: + Enabled: false +Style/OperatorMethodCall: + Enabled: false +Style/QuotedSymbols: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/RedundantConstantBase: + Enabled: false +Style/RedundantDoubleSplatHashBraces: + Enabled: false +Style/RedundantEach: + Enabled: false +Style/RedundantHeredocDelimiterQuotes: + Enabled: false +Style/RedundantInitialize: + Enabled: false +Style/RedundantLineContinuation: + Enabled: false +Style/RedundantSelfAssignmentBranch: + Enabled: false +Style/RedundantStringEscape: + Enabled: false +Style/SelectByRegexp: + Enabled: false +Style/StringChars: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/Gemfile b/Gemfile index e6927c3..911d971 100644 --- a/Gemfile +++ b/Gemfile @@ -2,24 +2,34 @@ gem_sources = ENV.fetch('GEM_SERVERS','https://rubygems.org').split(/[, ]+/) gem_sources.each { |gem_source| source gem_source } +group :syntax do + gem 'metadata-json-lint' + gem 'puppet-lint-trailing_comma-check', require: false + gem 'rubocop', '~> 1.81.0' + gem 'rubocop-performance', '~> 1.26.0' + gem 'rubocop-rake', '~> 0.7.1' + gem 'rubocop-rspec', '~> 3.7.0' +end + group :test do gem 'rake' # renovate: datasource=rubygems versioning=ruby - gem 'puppet', ENV.fetch('PUPPET_VERSION', '~> 7') + gem 'puppet', ENV.fetch('PUPPET_VERSION', ['>= 7', '< 9']) gem 'rspec' gem 'simplecov' gem 'mocha' # renovate: datasource=rubygems versioning=ruby gem 'simp-rake-helpers', ENV.fetch('SIMP_RAKE_HELPERS_VERSION', '~> 5.24.0') - gem 'pathspec', '~> 0.2' if Gem::Requirement.create('< 2.6').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - +end +group :development do gem 'pry' gem 'pry-byebug' gem 'pry-doc' end group :system_tests do + gem 'bcrypt_pbkdf' gem 'beaker' gem 'beaker-rspec' # renovate: datasource=rubygems versioning=ruby @@ -28,13 +38,13 @@ end # Evaluate extra gemfiles if they exist extra_gemfiles = [ - ENV['EXTRA_GEMFILE'] || '', + ENV.fetch('EXTRA_GEMFILE', ''), "#{__FILE__}.project", "#{__FILE__}.local", File.join(Dir.home, '.gemfile'), ] extra_gemfiles.each do |gemfile| if File.file?(gemfile) && File.readable?(gemfile) - eval(File.read(gemfile), binding) + eval(File.read(gemfile), binding) # rubocop:disable Security/Eval end end diff --git a/Rakefile b/Rakefile old mode 100644 new mode 100755 index 5ac2693..26d7727 --- a/Rakefile +++ b/Rakefile @@ -10,8 +10,7 @@ require 'simp/rake/ci' # coverage/ contains SimpleCov results CLEAN.include 'coverage' - -desc "Run spec tests" +desc 'Run spec tests' RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = ['--color'] t.pattern = 'spec/scripts/**/*_spec.rb' @@ -25,4 +24,3 @@ Simp::Rake::Beaker.new(File.dirname(__FILE__)) # simp:ci_* Rake tasks Simp::Rake::Ci.new(File.dirname(__FILE__)) - diff --git a/build/simp-utils.spec b/build/simp-utils.spec index f1909d5..ec80041 100644 --- a/build/simp-utils.spec +++ b/build/simp-utils.spec @@ -43,7 +43,7 @@ end Summary: SIMP Utils Name: simp-utils -Version: 6.8.0 +Version: 6.8.1 Release: %{lua: print(package_release)}%{?dist} License: Apache License, Version 2.0 Group: Applications/System @@ -113,6 +113,9 @@ chmod -R u=rwx,g=rx,o=rx %{buildroot}/usr/local/*bin # Post uninstall stuff %changelog +* Wed Sep 17 2025 Steven Pritchard - 6.8.1-1 +- Cleanup for rubocop + * Tue Jul 16 2024 Steven Pritchard - 6.8.0-1 - Updates for Puppet 8 - Various fixes for Ruby 3 compatibility diff --git a/scripts/bin/set_environment b/scripts/bin/set_environment index a77c41f..b132580 100755 --- a/scripts/bin/set_environment +++ b/scripts/bin/set_environment @@ -81,50 +81,49 @@ # # require 'yaml' -module Simp - class YamlNodeClassifier - DEFAULT_CONFIG_FILE = '/etc/puppetlabs/puppet/environments.yaml' - DEFAULT_ENVIRONMENT = 'production' - - def run(args, config_file = DEFAULT_CONFIG_FILE, default_env = DEFAULT_ENVIRONMENT) - fqdn = args[0] - - raise("You must pass the FQDN of the host as the first argument") unless fqdn - - # Set result to the default environment if there is no match - result = { 'environment' => default_env } - - if File.readable?(config_file) - environment_data = YAML.load(File.read(config_file)).to_hash - - environment_data.each_pair do |host,value| - if host[0].chr == '/' - if host[-1].chr == '/' - - clean_host = host[1..-2] - - if Regexp.new(clean_host).match(fqdn) - result['environment'] = value.to_s.strip - break - end - else - fail("Rule '#{host}' is not a valid hostname or regex") - end - else - if host == fqdn - result['environment'] = value.to_s.strip - break - end + +# Simp module namespace +module Simp; end + +# Simp::YamlNodeClassifier class +class Simp::YamlNodeClassifier + DEFAULT_CONFIG_FILE = '/etc/puppetlabs/puppet/environments.yaml'.freeze + DEFAULT_ENVIRONMENT = 'production'.freeze + + def run(args, config_file = DEFAULT_CONFIG_FILE, default_env = DEFAULT_ENVIRONMENT) + fqdn = args[0] + + raise('You must pass the FQDN of the host as the first argument') unless fqdn + + # Set result to the default environment if there is no match + result = { 'environment' => default_env } + + if File.readable?(config_file) + environment_data = YAML.load_file(config_file).to_hash + + environment_data.each_pair do |host, value| + if host[0].chr == '/' + raise("Rule '#{host}' is not a valid hostname or regex") unless host[-1].chr == '/' + + clean_host = host[1..-2] + + if Regexp.new(clean_host).match(fqdn) + result['environment'] = value.to_s.strip + break end + + elsif host == fqdn + result['environment'] = value.to_s.strip + break end end - - puts result.to_yaml - return 0 end + + puts result.to_yaml + 0 end end -if __FILE__ == $0 +if __FILE__ == $PROGRAM_NAME exit Simp::YamlNodeClassifier.new.run(ARGV) end diff --git a/scripts/bin/unpack_dvd b/scripts/bin/unpack_dvd index b6b1289..9fa68fd 100755 --- a/scripts/bin/unpack_dvd +++ b/scripts/bin/unpack_dvd @@ -53,29 +53,28 @@ require 'shellwords' require 'find' require 'yaml' -File.umask(0022) +File.umask(0o022) # This class shamelessly borrowed from # http://www.software-testing.com.au/blog/2010/01/13/text-based-progress-bar-in-ruby-for-command-line-programs/ class ProgressBar - attr_accessor :items_to_do, :items_done - def initialize(items_to_do, items_done=0) + def initialize(items_to_do, items_done = 0) reset(items_to_do, items_done) end def percent_complete - return (@items_complete*1.0/@items_to_do*1.0)*100 + (@items_complete * 1.0 / @items_to_do * 1.0) * 100 end - def advance(steps_to_advance=1) - @items_complete+=steps_to_advance + def advance(steps_to_advance = 1) + @items_complete += steps_to_advance end - def reset(items_to_do, items_done=0) - @items_to_do=items_to_do - @items_complete=items_done + def reset(items_to_do, items_done = 0) + @items_to_do = items_to_do + @items_complete = items_done end def report @@ -87,14 +86,14 @@ class ProgressBar end def progress_bar - complete_bar=(percent_complete/2.0).floor - incomplete_bar=((100-percent_complete)/2.0).ceil - return "[#{"*"*complete_bar}#{"-"*incomplete_bar}]" + complete_bar = (percent_complete / 2.0).floor + incomplete_bar = ((100 - percent_complete) / 2.0).ceil + "[#{'*' * complete_bar}#{'-' * incomplete_bar}]" end end def bnr - ('='*4) + ' ' + ('=' * 4) + ' ' end # Extract the .treeinfo file from the disc and parse out the relevant values. @@ -103,23 +102,22 @@ end def parse_treeinfo_into_discattrs(text) discattrs = {} text.each_line do |line| - if line =~ /^family = (.*)$/ - fam = $1.chomp - if fam.chomp =~ /CentOS/ - discattrs[:family] = "CentOS" - elsif fam.chomp =~ /Red Hat|RHEL|RedHat/ - discattrs[:family] = "RedHat" - end - elsif line =~ /^version = (.*)$/ - discattrs[:version] = $1.chomp - elsif line =~ /^arch = (.*)$/ - discattrs[:arch] = $1.chomp + if line =~ %r{^family = (.*)$} + fam = Regexp.last_match(1).chomp + if fam.chomp.include?('CentOS') + discattrs[:family] = 'CentOS' + elsif %r{Red Hat|RHEL|RedHat}.match?(fam.chomp) + discattrs[:family] = 'RedHat' + end + elsif line =~ %r{^version = (.*)$} + discattrs[:version] = Regexp.last_match(1).chomp + elsif line =~ %r{^arch = (.*)$} + discattrs[:arch] = Regexp.last_match(1).chomp end end discattrs end - def update_yum_repo(repo, group) repo_dirs = [ repo ] @@ -132,11 +130,11 @@ def update_yum_repo(repo, group) end # Add RPM-only directories - rpm_only_dirs = Dir.glob(File.join('..', '**', '*.rpm')).map{|x| File.split(x).first}.uniq - rpm_only_dirs.delete_if{|x| discovered_repos.find{|y| x =~ %r{^#{Regexp.escape(y)}}}} + rpm_only_dirs = Dir.glob(File.join('..', '**', '*.rpm')).map { |x| File.split(x).first }.uniq + rpm_only_dirs.delete_if { |x| discovered_repos.find { |y| x =~ %r{^#{Regexp.escape(y)}} } } discovered_repos += rpm_only_dirs - discovered_repos.delete_if{|x| File.basename(x) == File.basename(repo)} + discovered_repos.delete_if { |x| File.basename(x) == File.basename(repo) } discovered_modular_repos = Dir.glob(File.join('..', '**', 'repodata', '*module*')) discovered_modular_repos.map! do |x| @@ -160,13 +158,13 @@ def update_yum_repo(repo, group) # this, it simply sits there and looks like it has hung. buffer = '' first = true - IO.popen("createrepo -p --update .").each_byte do |b| + IO.popen('createrepo_c -p --update .').each_byte do |b| b = b.chr - if b == "\r" or b == "\n" - next if buffer =~ /^\s*$/ + if (b == "\r") || (b == "\n") + next if %r{^\s*$}.match?(buffer) - if buffer =~ /(\d+)\/(\d+).*\.rpm/ - print "\r#{((($1.to_f/$2.to_f) * 100) * 100).round.to_f / 100}% Complete" + if buffer =~ %r{(\d+)/(\d+).*\.rpm} + print "\r#{(((Regexp.last_match(1).to_f / Regexp.last_match(2).to_f) * 100) * 100).round.to_f / 100}% Complete" else if first puts '' @@ -181,68 +179,66 @@ def update_yum_repo(repo, group) end end - if Process.uid == 0 - repo_dirs.each { |dir| - begin - FileUtils.chown_R('root',group, dir) - rescue Exception => e - $stderr.puts("WARNING: Could not change permissions on #{dir} to root:#{group}.") - $stderr.puts(e) - end + return unless Process.uid == 0 + repo_dirs.each do |dir| + begin + FileUtils.chown_R('root', group, dir) + rescue StandardError => e + $stderr.puts("WARNING: Could not change permissions on #{dir} to root:#{group}.") + $stderr.puts(e) + end - begin - FileUtils.chmod_R('g+rX',dir) - rescue Exception => e - $stderr.puts("WARNING: Could not change permissions on #{dir} to 'g+rX'.") - $stderr.puts(e) - end - begin - FileUtils.chmod('g+s',dir) - rescue Exception => e - $stderr.puts("WARNING: Could not set group id permission on #{dir} 'g+s'.") - $stderr.puts(e) - end - } + begin + FileUtils.chmod_R('g+rX', dir) + rescue StandardError => e + $stderr.puts("WARNING: Could not change permissions on #{dir} to 'g+rX'.") + $stderr.puts(e) + end + begin + FileUtils.chmod('g+s', dir) + rescue StandardError => e + $stderr.puts("WARNING: Could not set group id permission on #{dir} 'g+s'.") + $stderr.puts(e) + end end end def sort_noarch(dir, arch) -# dir = directory you are searching -# arch = the architecture of the machine -# -# This module sorts the noarch RPMs into the noarch -# directory. -# - noarchdir = File.expand_path("../noarch", dir ) + # dir = directory you are searching + # arch = the architecture of the machine + # + # This module sorts the noarch RPMs into the noarch + # directory. + # + noarchdir = File.expand_path('../noarch', dir) FileUtils.mkdir_p(noarchdir, mode: 0o755) Dir.chdir(dir) do Dir.glob('*.rpm').each do |rpmfile| next if File.symlink?(rpmfile) rpmarch = rpmfile.split('.')[-2] unless [ arch, 'noarch'].include?(rpmarch) - rpmarch = `rpm -qp #{rpmfile} --queryformat '%{ARCH}' 2> /dev/null` + rpmarch = `rpm -qp #{rpmfile} --queryformat '%{ARCH}' 2> /dev/null` end - FileUtils.mv(rpmfile, noarchdir, :force => true) if rpmarch.eql? 'noarch' + FileUtils.mv(rpmfile, noarchdir, force: true) if rpmarch.eql? 'noarch' end end end def get_iso_toc(isoinfo) - iso_list = %x{#{isoinfo} -Rl}.split("\n") + iso_list = `#{isoinfo} -Rl`.split("\n") iso_toc = [] current_dir = nil iso_list.each do |line| - if line =~ /Directory listing of (.*)/ - current_dir = $1.strip + if line =~ %r{Directory listing of (.*)} + current_dir = Regexp.last_match(1).strip next end - if (line !~ /->/) and (line =~ /^\S{10}\s/) - file = line.split.last.strip - next if file =~ /^\/?\.+$/ - iso_toc << "#{current_dir + file}" - end + next unless !line.include?('->') && (line =~ %r{^\S{10}\s}) + file = line.split.last.strip + next if %r{^/?\.+$}.match?(file) + iso_toc << (current_dir + file).to_s end iso_toc end @@ -269,7 +265,7 @@ def unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) puts "Unpacking RPM packages from #{discattrs[:path]}...", '' # Bail if we're trying to unpack into an old-format directory - legacy_repodata = Dir.glob(File.join(options[:dest],'SIMP','*','repodata')) + legacy_repodata = Dir.glob(File.join(options[:dest], 'SIMP', '*', 'repodata')) unless legacy_repodata.empty? # Old SIMP layout will have one directory with repodata (/SIMP/x86_64). puts "ERROR: '#{File.dirname(legacy_repodata.first)}' is in the legacy SIMP repo layout!" @@ -280,38 +276,38 @@ def unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) end iso_toc = get_iso_toc(isoinfo) - kill_dirs = iso_toc.map{ |x| File.dirname( x ) }.uniq - iso_toc = iso_toc - kill_dirs - distdir = File.join( + kill_dirs = iso_toc.map { |x| File.dirname(x) }.uniq + iso_toc -= kill_dirs + distdir = File.join( options[:dest], discattrs[:family], versiondir, discattrs[:arch], - '' + '', ) - simpdir = File.join( + simpdir = File.join( options[:dest], 'SIMP', discattrs[:family], versiondir, discattrs[:arch], - '' + '', ) simp_old_iso = true progress = ProgressBar.new(iso_toc.size) skip_list = [ - 'TRANS.TBL' + 'TRANS.TBL', ] iso_toc.each do |iso_entry| unless skip_list.include?(File.split(iso_entry).last) # SIMP 6.6.0 EL8+ if iso_entry =~ %r{^/SimpRepos/(.+)} - target = File.join(simpdir, $1) + target = File.join(simpdir, Regexp.last_match(1)) simp_old_iso = false - elsif iso_entry =~ %r{^/SIMP/} + elsif %r{^/SIMP/}.match?(iso_entry) target = "#{simpdir}#{File.basename(iso_entry)}" else target = "#{distdir}#{iso_entry}" @@ -319,7 +315,7 @@ def unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) begin FileUtils.mkdir_p(File.dirname(target)) - rescue Exception => e + rescue StandardError => e warn "#{e.class}: #{e.message}" puts "This is iso_toc: #{iso_entry}" puts "This is the target: #{target}" @@ -345,13 +341,13 @@ def unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) if simp_old_iso if File.directory?(simpdir) - sort_noarch(simpdir,discattrs[:arch] ) - update_yum_repo(simpdir, options[:group]) unless (simpdir == distdir) + sort_noarch(simpdir, discattrs[:arch]) + update_yum_repo(simpdir, options[:group]) unless simpdir == distdir end end update_yum_repo("#{distdir}/Updates", options[:group]) - puts "Yum repo creation complete" + puts 'Yum repo creation complete' if options[:create_major_os_symlink] maj_versiondir = discattrs[:version].split('.').first @@ -359,7 +355,7 @@ def unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) target_basedir = File.join(options[:dest], discattrs[:family]) create_major_os_version_symlink(target_basedir, versiondir, maj_versiondir) # create major link for SIMP repository - target_basedir = File.join(options[:dest],'SIMP',discattrs[:family]) + target_basedir = File.join(options[:dest], 'SIMP', discattrs[:family]) create_major_os_version_symlink(target_basedir, versiondir, maj_versiondir) end @@ -367,21 +363,21 @@ def unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) end def unpack_pxeboot_from_iso(discattrs, versiondir, isoinfo, options) - if options[:actions][:unpack_pxeboot].is_a?(String) - linux_install_path = options[:actions][:unpack_pxeboot] - else - linux_install_path = File.expand_path( - "#{options[:var_simp]}/environments/#{options[:environment]}" + - "/rsync/#{discattrs[:family]}/Global/tftpboot/linux-install" - ) - end + linux_install_path = if options[:actions][:unpack_pxeboot].is_a?(String) + options[:actions][:unpack_pxeboot] + else + File.expand_path( + "#{options[:var_simp]}/environments/#{options[:environment]}" \ + "/rsync/#{discattrs[:family]}/Global/tftpboot/linux-install", + ) + end if options[:verbose] puts "#{bnr}linux_install_path: #{linux_install_path}" end unless File.directory?(linux_install_path) - fail("ERROR: pxeboot unpack dest directory not found: '#{linux_install_path}'") + raise("ERROR: pxeboot unpack dest directory not found: '#{linux_install_path}'") end iso_toc = get_iso_toc(isoinfo) @@ -392,29 +388,29 @@ def unpack_pxeboot_from_iso(discattrs, versiondir, isoinfo, options) iso_pxeboot_images_dir = '/images/pxeboot' iso_pxeboot_images = iso_toc.grep( - %r[^#{iso_pxeboot_images_dir}] - ).reject{|x| x == iso_pxeboot_images_dir} + %r{^#{iso_pxeboot_images_dir}}, + ).reject { |x| x == iso_pxeboot_images_dir } if options[:verbose] puts "#{bnr}iso_toc files under /images/pxeboot (#{iso_pxeboot_images.size}):", iso_pxeboot_images.to_yaml, '' end - if iso_pxeboot_images.size > 0 - puts "Unpacking PXE boot image files..." + if !iso_pxeboot_images.empty? + puts 'Unpacking PXE boot image files...' else puts "WARNING: No PXE boot files found on ISO under #{iso_pxeboot_images_dir}" end iso_pxeboot_images.each do |image| image_file = Shellwords.escape(File.basename(image)) - dest_file = File.join(pxe_dest_dir,image_file) + dest_file = File.join(pxe_dest_dir, image_file) # Just in case there are subdirectories (haven't run across any yet) - image_dir = File.dirname(image).sub(%r[^#{iso_pxeboot_images_dir}], '') + image_dir = File.dirname(image).sub(%r{^#{iso_pxeboot_images_dir}}, '') unless image_dir.empty? - newdir = File.expand_path(image_dir,pxe_dest_dir) + newdir = File.expand_path(image_dir, pxe_dest_dir) FileUtils.mkdir_p(newdir, mode: 0o750, verbose: options[:verbose]) - dest_file = File.join(newdir,image_file) + dest_file = File.join(newdir, image_file) end if options[:verbose] @@ -426,7 +422,7 @@ def unpack_pxeboot_from_iso(discattrs, versiondir, isoinfo, options) if Process.uid == 0 # set ownership + file permissions for tftpboot - puts "Setting PXE boot files ownership and SELinux context..." + puts 'Setting PXE boot files ownership and SELinux context...' FileUtils.chown_R('root', 'nobody', pxe_dest_dir, verbose: options[:verbose]) system("chcon --reference '#{linux_install_path}' -R '#{pxe_dest_dir}'") end @@ -436,153 +432,150 @@ def unpack_pxeboot_from_iso(discattrs, versiondir, isoinfo, options) create_major_os_version_symlink(linux_install_path, pxe_dest_version, maj_versiondir) end - puts "Unpacking PXE boot image files complete." + puts 'Unpacking PXE boot image files complete.' end -def fail_on_unspecific_versiondir(versiondir, options, discattrs) - if versiondir.split('.').size <= 1 - if options[:version] == versiondir - warn <<~MSG - WARNING: unspecific versioned directory name ('#{versiondir}'), - (Allowing because it was passed in by option) +def fail_on_unspecific_versiondir(versiondir, options, _discattrs) + return unless versiondir.split('.').size <= 1 + if options[:version] == versiondir + warn <<~MSG + WARNING: unspecific versioned directory name ('#{versiondir}'), + (Allowing because it was passed in by option) MSG - return - end + return + end - puts <<~MSG - ERROR: + puts <<~MSG + ERROR: - The versioned directory name ('#{versiondir}') this script is configured to unpack into - is not specific enough to be safe; if used, this ISO\'s data may overwrite/be - overwritten by other unpacked ISOs. + The versioned directory name ('#{versiondir}') this script is configured to unpack into + is not specific enough to be safe; if used, this ISO\'s data may overwrite/be + overwritten by other unpacked ISOs. - Specific release versions must contain at least one dot (.) character. + Specific release versions must contain at least one dot (.) character. - The version '#{versiondir}' may have been automatically determined from the ISO\'s - metadata; some OS distributions (CentOS) only provide the major OS release - version in their ISOs\' metadata. + The version '#{versiondir}' may have been automatically determined from the ISO\'s + metadata; some OS distributions (CentOS) only provide the major OS release + version in their ISOs\' metadata. - WORKAROUND: + WORKAROUND: - Run this script again with `-v` and specify a more specific version. For - instance, when unpacking ISO CentOS-7-x86_64-DVD-2003.iso, you could run: + Run this script again with `-v` and specify a more specific version. For + instance, when unpacking ISO CentOS-7-x86_64-DVD-2003.iso, you could run: - unpack_dvd -v 7.0.2003 CentOS-7-x86_64-DVD-2003.iso + unpack_dvd -v 7.0.2003 CentOS-7-x86_64-DVD-2003.iso - This would use '7.0.2003' as the specific versioned directory name to unpack - into, and point the major release directory name '7' to '7.0.2003' - (auto-linking can be disabled with `-n`). + This would use '7.0.2003' as the specific versioned directory name to unpack + into, and point the major release directory name '7' to '7.0.2003' + (auto-linking can be disabled with `-n`). - MSG - exit 1 - end + MSG + exit 1 end # Set defaults options = { verbose: false, - var_simp: File.directory?('/var/simp') ? '/var/simp' : - (File.directory?('/srv/simp') ? '/srv/simp' : nil ), + var_simp: if File.directory?('/var/simp') + '/var/simp' + else + (File.directory?('/srv/simp') ? '/srv/simp' : nil) + end, create_major_os_symlink: true, group: 'apache', - dest: File.directory?('/var/www/yum') ? '/var/www/yum' : - (File.directory?('/srv/www/yum') ? '/srv/www/yum' : nil), + dest: if File.directory?('/var/www/yum') + '/var/www/yum' + else + (File.directory?('/srv/www/yum') ? '/srv/www/yum' : nil) + end, environment: 'production', actions: { unpack_yum_repo: true, unpack_pxeboot: false, - } + }, } # Get command line options opt_parser = OptionParser.new do |opts| - opts.banner = "Usage: #{$0} [options] /path/to/dvd/to/unpack" + opts.banner = "Usage: #{$PROGRAM_NAME} [options] /path/to/dvd/to/unpack" opts.separator '' opts.separator 'Basic unpack options:' opts.separator '' - opts.on("-v", "--version VERSION", + opts.on('-v', '--version VERSION', "Override OS version from the ISO's .treeinfo", - " file (which is often just the major OS", - " version, and not specific enough to", - " prevent overwriting directories from", - " previously unpacked ISOs from the same ", - " major OS version." - ) do |version| + ' file (which is often just the major OS', + ' version, and not specific enough to', + ' prevent overwriting directories from', + ' previously unpacked ISOs from the same ', + ' major OS version.') do |version| options[:version] = version.chomp end opts.separator 'RPM/yum repo unpack options:' opts.separator '' - opts.on("-Y", "--[no-]unpack-yum", - "unpack RPMs from DVD and create yum repo", - " (default: #{options[:actions][:unpack_yum_repo]})", - ) do |n| + opts.on('-Y', '--[no-]unpack-yum', + 'unpack RPMs from DVD and create yum repo', + " (default: #{options[:actions][:unpack_yum_repo]})") do |n| options[:actions][:unpack_yum_repo] = n end - opts.on("-d", "--dest DIR", - "Set the yum repo target directory", + opts.on('-d', '--dest DIR', + 'Set the yum repo target directory', " (Default: #{options[:dest]})", - " The // directories will be", - " created under here.") do |dest| + ' The // directories will be', + ' created under here.') do |dest| options[:dest] = dest.chomp end - opts.on("-n", "--[no-]nolink", - "Do not symlink the unpacked OS yum repo to", - " serve as the OS's major version repo." - ) do |n| + opts.on('-n', '--[no-]nolink', + 'Do not symlink the unpacked OS yum repo to', + " serve as the OS's major version repo.") do |n| options[:create_major_os_symlink] = !n end - opts.on("-g", "--group GROUP", String, - "Specify group ownership of unpacked packages", + opts.on('-g', '--group GROUP', String, + 'Specify group ownership of unpacked packages', " (Default: '#{options[:group]}')", - " Note: This option does not verify that", - " GROUP actually exists!" - ) do |group| + ' Note: This option does not verify that', + ' GROUP actually exists!') do |group| options[:group] = group end opts.separator 'PXE tftpboot unpack options:' opts.separator '' - opts.on("-X", "--[no-]unpack-pxe [DIR]", String, - "unpack pxeboot tftpboot files from iso", + opts.on('-X', '--[no-]unpack-pxe [DIR]', String, + 'unpack pxeboot tftpboot files from iso', " (default: #{options[:actions][:unpack_pxeboot]})", - " May optionally specify an alternate", - " target directory for `linux-install/`" - ) do |pxeboot| - pxeboot = true if (!pxeboot.is_a?(FalseClass) && pxeboot.to_s.empty?) + ' May optionally specify an alternate', + ' target directory for `linux-install/`') do |pxeboot| + pxeboot = true if !pxeboot.is_a?(FalseClass) && pxeboot.to_s.empty? if pxeboot.is_a?(String) pxeboot.chomp! - fail("ERROR: pxeboot directory '#{pxeboot}' does not exist") unless File.directory?(pxeboot) + raise("ERROR: pxeboot directory '#{pxeboot}' does not exist") unless File.directory?(pxeboot) end options[:actions][:unpack_pxeboot] = pxeboot end - opts.on("-e", "--environment ENVIRONMENT", %r[\A[a-z0-9_]+\Z], - "Set target SIMP environment (used by -X)", - " (Default: #{options[:environment]}" - ) do |env| + opts.on('-e', '--environment ENVIRONMENT', %r{\A[a-z0-9_]+\Z}, + 'Set target SIMP environment (used by -X)', + " (Default: #{options[:environment]}") do |env| options[:environment] = env.chomp end opts.separator 'Global options:' opts.separator '' - opts.on("-V", "--[no-]verbose", - "Add verbose output (default: #{options[:verbose]}" - ) do |n| + opts.on('-V', '--[no-]verbose', + "Add verbose output (default: #{options[:verbose]}") do |n| options[:verbose] = n end - - opts.on("-h", "--help", "Output this useful help message") do + opts.on('-h', '--help', 'Output this useful help message') do puts opts exit end @@ -591,21 +584,21 @@ end opt_parser.parse! # Option checking -fail("ERROR: You must specify an ISO to unpack") if (ARGV.length < 1) -fail("ERROR: Could not detect a package destination directory, and no --dest option provided") unless options[:dest] -fail("ERROR: Destination directory '#{options[:dest]}' does not exist") unless File.directory?(options[:dest]) +raise('ERROR: You must specify an ISO to unpack') if ARGV.empty? +raise('ERROR: Could not detect a package destination directory, and no --dest option provided') unless options[:dest] +raise("ERROR: Destination directory '#{options[:dest]}' does not exist") unless File.directory?(options[:dest]) # Set nice names for options discattrs = { - :family => nil, - :version => nil, - :arch => nil, - :path => nil + family: nil, + version: nil, + arch: nil, + path: nil, } discattrs[:path] = ARGV.first -if not File.readable?(discattrs[:path]) +unless File.readable?(discattrs[:path]) $stderr.puts("ERROR: Could not read file #{discattrs[:path]}") exit 1 end @@ -620,10 +613,10 @@ if File.blockdev?(discattrs[:path]) isoinfo = "isoinfo dev=#{discattrs[:path]}" end -discattrs.merge!(parse_treeinfo_into_discattrs(%x{#{isoinfo} -R -x /.treeinfo})) +discattrs.merge!(parse_treeinfo_into_discattrs(`#{isoinfo} -R -x /.treeinfo`)) # If everything isn't filled, die a slow death. -discattrs.each_pair do |k,v| +discattrs.each_pair do |k, v| if v.nil? $stderr.puts("ERROR: Was not able to find the value for #{k} in the DVD .treeinfo file.") exit 1 @@ -641,7 +634,7 @@ if options[:verbose] puts bnr + "versiondir: #{versiondir}", '' end -fail_on_unspecific_versiondir(versiondir,options,discattrs) +fail_on_unspecific_versiondir(versiondir, options, discattrs) if options[:actions][:unpack_yum_repo] unpack_and_create_yum_repo_from_iso(discattrs, versiondir, isoinfo, options) diff --git a/scripts/sbin/gen-ldap-update b/scripts/sbin/gen-ldap-update index f42cc8e..c0bc300 100755 --- a/scripts/sbin/gen-ldap-update +++ b/scripts/sbin/gen-ldap-update @@ -4,7 +4,7 @@ # to the values found in /etc/openldap/default.ldif. This output should # be saved to a file or piped to ldapmodify directly. -default_ldif = "/etc/openldap/default.ldif" +default_ldif = '/etc/openldap/default.ldif' unless File.readable?(default_ldif) $stderr.puts("Error: Could not read #{default_ldif}. Unable to proceed.") @@ -16,26 +16,31 @@ end # Try /etc/openldap/ldap.conf first. base_dn = nil -if File.readable?("/etc/openldap/ldap.conf") - File.open("/etc/openldap/ldap.conf",'r').each do |ln| - if ln =~ /^\s*BASE\s+(.*)$/ - base_dn = $1.strip +if File.readable?('/etc/openldap/ldap.conf') + File.open('/etc/openldap/ldap.conf', 'r').each do |ln| + if ln =~ %r{^\s*BASE\s+(.*)$} + base_dn = Regexp.last_match(1).strip end end -elsif File.readable?("/etc/ldap.conf") - File.open("/etc/ldap.conf").each do |ln| - if ln =~ /^\s*base\s+(.*)$/ - base_dn = $1.strip +elsif File.readable?('/etc/ldap.conf') + File.open('/etc/ldap.conf').each do |ln| + if ln =~ %r{^\s*base\s+(.*)$} + base_dn = Regexp.last_match(1).strip end end else require 'socket' begin - #TODO use facter to get domain - base_dn = Socket.gethostbyname(Socket.gethostname).first.split('.')[1..-1].map { |x| x = "dc=#{x}" }.join(',') + # TODO: use facter to get domain + base_dn = Addrinfo.getaddrinfo(Socket.gethostname, nil, :INET, :STREAM, nil, Socket::AI_CANONNAME) + .first + .canonname + .split('.')[1..-1] + .map { |x| "dc=#{x}" } + .join(',') raise if base_dn.empty? - rescue Exception => e + rescue StandardError $stderr.puts('Error: Could not determine base_dn from hostname.') exit(1) end @@ -44,25 +49,25 @@ end # DN's we want to update. update_dn = [ "cn=default,ou=pwpolicies,#{base_dn}", - "cn=noExpire_noLockout,ou=pwpolicies,#{base_dn}" + "cn=noExpire_noLockout,ou=pwpolicies,#{base_dn}", ] -new_entries = Hash.new +new_entries = {} current_dn = nil -File.open(default_ldif,'r').each do |ln| - if ln =~ /^\s*$/ +File.open(default_ldif, 'r').each do |ln| + if %r{^\s*$}.match?(ln) current_dn = nil end if current_dn.nil? update_dn.each do |dn| - if ln =~ /^dn:\s+#{dn}/ + if %r{^dn:\s+#{dn}}.match?(ln) current_dn = "dn: #{dn}" - new_entries[current_dn] = Array.new + new_entries[current_dn] = [] end end - elsif ln !~ /^objectClass/ + elsif !%r{^objectClass}.match?(ln) new_entries[current_dn].push(ln.strip) end end @@ -78,12 +83,12 @@ puts "# You probably want to pipe the output of this script into something like keys = new_entries.keys.sort keys.each do |key| puts key - puts "changetype: modify" - new_entries[key].map! { |x| + puts 'changetype: modify' + new_entries[key].map! do |x| lhs = x.split(' ').first.chop rhs = x.split(' ')[1..-1].join(' ') - x = "replace: #{lhs}\n#{lhs}: #{rhs}" - } + "replace: #{lhs}\n#{lhs}: #{rhs}" + end puts new_entries[key].join("\n-\n") puts diff --git a/scripts/sbin/puppetlast b/scripts/sbin/puppetlast index 05441ef..1fffe3b 100755 --- a/scripts/sbin/puppetlast +++ b/scripts/sbin/puppetlast @@ -1,17 +1,15 @@ #!/opt/puppetlabs/puppet/bin/ruby -# + # puppetlast queries PuppetDB and local file reports and returns a list of # nodes and the last time the catalog was compiled - class PuppetLast - - def setup_logger(log_level='info', force=false) - return if (@logger && !force) + def setup_logger(log_level = 'info', force = false) + return if @logger && !force require 'logger' @logger = Logger.new($stdout) - @logger.level = eval("Logger::#{log_level.upcase}") + @logger.level = Object.const_get("Logger::#{log_level.upcase}") @logger.formatter = proc do |severity, _datetime, _progname, msg| "#{severity}: #{msg}\n" end @@ -38,115 +36,115 @@ class PuppetLast opts = OptionParser.new do |opts| opts.banner = "Usage: #{File.basename(__FILE__)} [options]" - opts.separator "" + opts.separator '' opts.summary_width = 26 opts.summary_indent = ' ' opts.on( - "-d", - "--detailed", - "Show environment and last run status information" + '-d', + '--detailed', + 'Show environment and last run status information', ) do |detailed| @options.detailed = detailed end opts.on( - "-e", - "--expiration NUM", + '-e', + '--expiration NUM', Float, - "Don't show systems that have not checked in for more than NUM days." + "Don't show systems that have not checked in for more than NUM days.", ) do |exp| - if exp == 0 - @options.expiration = 99999 - else - @options.expiration = exp.to_f.abs - end + @options.expiration = if exp == 0 + 99_999 + else + exp.to_f.abs + end end opts.on( - "-S", - "--status a,b,c", + '-S', + '--status a,b,c', ['failed', 'changed', 'unchanged'], - "Return only nodes with statuses: 'failed', 'changed', or 'unchanged'" + "Return only nodes with statuses: 'failed', 'changed', or 'unchanged'", ) do |statuses| @options.statuses = statuses end opts.on( - "-H", - "--hosts a,b,c", + '-H', + '--hosts a,b,c', Array, - "List of hosts (short or long) that you wish to get data on" + 'List of hosts (short or long) that you wish to get data on', ) do |hosts| @options.hosts = hosts end opts.on( - "-E", - "--environments a,b,c", + '-E', + '--environments a,b,c', Array, - "List of environments you want to get data from" + 'List of environments you want to get data from', ) do |environments| @options.environments = environments end opts.on( - "-s", - "--sort-by SORT_OPTION", + '-s', + '--sort-by SORT_OPTION', [:nil, :certname, :time, :status, :environments], - "Sort by a given attribute: 'nil' => unsorted, 'certname' => default, 'time' => last checkin, 'status' => last run status, 'environments' => node environment" + "Sort by a given attribute: 'nil' => unsorted, 'certname' => default, 'time' => last checkin, 'status' => last run status, 'environments' => node environment", ) do |sort_by| @options.sort_by = sort_by end opts.on( - "-t", - "--timeformat TF", + '-t', + '--timeformat TF', [:seconds, :minutes, :hours, :days], - "Select output time format (seconds, minutes, hours, days)" + 'Select output time format (seconds, minutes, hours, days)', ) do |tf| @options.outtime = tf end opts.on( - "-p", - "--pretty", - "Format the output more attractively." + '-p', + '--pretty', + 'Format the output more attractively.', ) do |pretty| @options.pretty = pretty end opts.on( - "-P", - "--port", + '-P', + '--port', Array, - "The port that PuppetDB is listening on" + 'The port that PuppetDB is listening on', ) do |port| @options.port = port end opts.on( - "-f", - "--files-only", - "Only use the local files, not PuppetDB", - ) do |port| + '-f', + '--files-only', + 'Only use the local files, not PuppetDB', + ) do |_port| @options.files_only = true end opts.on( - "-l", - "--log-level level", + '-l', + '--log-level level', ['fatal', 'error', 'warn', 'info', 'debug'], - "Set the log level (fatal, error, warn, info, debug)" + 'Set the log level (fatal, error, warn, info, debug)', ) do |log_level| setup_logger(log_level, true) end opts.on( - "-h", - "--help", - "Help Message" + '-h', + '--help', + 'Help Message', ) do puts opts @options.help_requested = true @@ -156,25 +154,25 @@ class PuppetLast begin opts.parse!(args) rescue OptionParser::ParseError => e - raise "#{e.message}\n#{opts.to_s}" + raise "#{e.message}\n#{opts}" end case @options.outtime.to_s - when /^s.*/ - @options.outtime = 'seconds' - @options.divisor = 1 - when /^h.*/ - @options.outtime = 'hours' - @options.divisor = 1/Float(3600) - when /^d.*/ - @options.outtime = 'days' - @options.divisor = 1/Float(86400) - else - @options.outtime = 'minutes' - @options.divisor = 1/Float(60) + when %r{^s.*} + @options.outtime = 'seconds' + @options.divisor = 1 + when %r{^h.*} + @options.outtime = 'hours' + @options.divisor = 1 / Float(3600) + when %r{^d.*} + @options.outtime = 'days' + @options.divisor = 1 / Float(86_400) + else + @options.outtime = 'minutes' + @options.divisor = 1 / Float(60) end - @options.expsecs = @options.expiration * 86400 + @options.expsecs = @options.expiration * 86_400 end # grabs info about a particular host from PuppetDB @@ -183,22 +181,22 @@ class PuppetLast require 'uri' require 'net/http' - # TODO move to ssl + # TODO: move to ssl uri = URI("http://localhost:#{port}/pdb/query/v4/nodes/#{certname}") @logger.debug("Running PDB query: #{uri}") begin - data = JSON.parse(Net::HTTP.get(uri), :symbolize_names => true) - rescue Exception => e - err_msg = "#{e}\n" + - " Please make sure PuppetDB is running, this script is being run from\n" + - " the PuppetDB host, and the port is correct" + data = JSON.parse(Net::HTTP.get(uri), symbolize_names: true) + rescue StandardError => e + err_msg = "#{e}\n" \ + " Please make sure PuppetDB is running, this script is being run from\n" \ + ' the PuppetDB host, and the port is correct' @logger.error err_msg end if data.keys.include? :error - err_msg = "Could not retrieve node data for #{certname}" + + err_msg = "Could not retrieve node data for #{certname}" \ " Server Said: #{data}" @logger.error err_msg end @@ -214,17 +212,17 @@ class PuppetLast require 'uri' require 'net/http' - # TODO move to ssl + # TODO: move to ssl uri = URI("http://localhost:#{port}/pdb/query/v4/nodes") @logger.debug("Running PDB query: #{uri}") begin - data = JSON.parse(Net::HTTP.get(uri), :symbolize_names => true) - rescue Exception => e - err_msg = "#{e}\n" + - " Please make sure PuppetDB is running, this script is being run from\n" + - " the PuppetDB host, and the port is correct" + data = JSON.parse(Net::HTTP.get(uri), symbolize_names: true) + rescue StandardError => e + err_msg = "#{e}\n" \ + " Please make sure PuppetDB is running, this script is being run from\n" \ + ' the PuppetDB host, and the port is correct' @logger.error err_msg end @@ -238,29 +236,27 @@ class PuppetLast def query_files_hosts(hostlist, hosts) report_dir = get_report_dir - existing_nodes = hostlist.map{|x| x[:certname]} + existing_nodes = hostlist.map { |x| x[:certname] } local_host_template = { - :deactivated=>false, - :latest_report_hash=>nil, - :facts_environment=>nil, - :cached_catalog_status=>"not_used", - :report_environment=>nil, - :latest_report_corrective_change=>nil, - :catalog_environment=>nil, - :facts_timestamp=>nil, - :latest_report_noop=>nil, - :expired=>false, - :latest_report_noop_pending=>nil, - :report_timestamp=>nil, - :certname=>nil, - :catalog_timestamp=>nil, - :latest_report_job_id=>nil, - :latest_report_status=>nil + deactivated: false, + latest_report_hash: nil, + facts_environment: nil, + cached_catalog_status: 'not_used', + report_environment: nil, + latest_report_corrective_change: nil, + catalog_environment: nil, + facts_timestamp: nil, + latest_report_noop: nil, + expired: false, + latest_report_noop_pending: nil, + report_timestamp: nil, + certname: nil, + catalog_timestamp: nil, + latest_report_job_id: nil, + latest_report_status: nil, }.freeze - local_host_reports = [] - if File.directory?(report_dir) @logger.debug("Processing Report Directory: #{report_dir}") @@ -276,7 +272,7 @@ class PuppetLast transaction_report = YAML.safe_load(File.read(latest_report), permitted_classes: [Puppet::Transaction::Report]) - unless (hosts.empty? || hosts.include?(transaction_report.host)) + unless hosts.empty? || hosts.include?(transaction_report.host) @logger.debug("Skipping #{transaction_report.host} since it is not in the host list") next end @@ -331,64 +327,64 @@ class PuppetLast host[:expired] = nil else last_checkin = Time.now - Time.parse(host[:report_timestamp]) - formatted_checkin = sprintf("%#{@options.round_to}f",(last_checkin * @options.divisor).abs) + formatted_checkin = "%#{@options.round_to}f" % (last_checkin * @options.divisor).abs end node_data << { - :last_checkin => last_checkin, - :expired => host[:expired].nil? ? false : host[:expired], - :certname => host[:certname], - :environment => host[:report_environment].nil? ? 'N/A' : host[:report_environment], - :status => host[:latest_report_status].nil? ? 'N/A' : host[:latest_report_status], - :formatted_checkin => formatted_checkin + last_checkin: last_checkin, + expired: host[:expired].nil? ? false : host[:expired], + certname: host[:certname], + environment: host[:report_environment].nil? ? 'N/A' : host[:report_environment], + status: host[:latest_report_status].nil? ? 'N/A' : host[:latest_report_status], + formatted_checkin: formatted_checkin, } end unless @options.environments.empty? - node_data.delete_if {|node| not @options.environments.include? node[:environment] } + node_data.delete_if { |node| !@options.environments.include? node[:environment] } end unless @options.statuses.empty? - node_data.delete_if {|node| not @options.statuses.include? node[:status] } + node_data.delete_if { |node| !@options.statuses.include? node[:status] } end node_data end # sort hosts list according to the option - def sort_hosts(hosts,sort_by) + def sort_hosts(hosts, sort_by) case sort_by when :certname - return hosts.sort{ |a,b| a[:certname] <=> b[:certname] } + hosts.sort_by { |a| a[:certname] } when :time - return hosts.sort{ |a,b| - if a[:last_checkin].nil? and !b[:last_checkin].nil? + hosts.sort do |a, b| + if a[:last_checkin].nil? && !b[:last_checkin].nil? 1 - elsif !a[:last_checkin].nil? and b[:last_checkin].nil? + elsif !a[:last_checkin].nil? && b[:last_checkin].nil? -1 else a[:last_checkin] <=> b[:last_checkin] end - } + end when :status - return hosts.sort{ |a,b| a[:status].downcase <=> b[:status].downcase } + hosts.sort { |a, b| a[:status].downcase <=> b[:status].downcase } when :environment - return hosts.sort{ |a,b| a[:environment] <=> b[:environment] } + hosts.sort_by { |a| a[:environment] } else - return hosts + hosts end end # find max length of element and return it def find_longest(sorted_data, key) keys = sorted_data.map { |h| h[key].to_s } - return keys.max_by(&:length).length + keys.max_by(&:length).length end def print_node_without_checkin(node, col_len) if @options.detailed printf( - "%-#{col_len[:certname]}s from environment %-#{col_len[:environment]}s has no reported check in\n", + "%-#{col_len[:certname]}s from environment %-#{col_len[:environment]}s has no reported check in\n", node[:certname], - node[:environment] + node[:environment], ) else printf("%-#{col_len[:certname]}s has no reported check in\n", node[:certname]) @@ -398,32 +394,30 @@ class PuppetLast def print_node_with_checkin(node, col_len) if node[:last_checkin] < 0 msg = "%-#{col_len[:certname]}s time issue: %#{col_len[:formatted_checkin]}#{@options.round_to}f %s in the future\n" - else node[:last_checkin] < @options.expsecs - if @options.detailed - msg = "%-#{col_len[:certname]}s from environment %-#{col_len[:environment]}s checked in %#{col_len[:formatted_checkin]}#{@options.round_to}f %s ago with status %-#{col_len[:status]}s\n" - else - msg = "%-#{col_len[:certname]}s checked in %#{col_len[:formatted_checkin]}#{@options.round_to}f %s ago\n" - end + else + node[:last_checkin] + @options.expsecs + msg = if @options.detailed + "%-#{col_len[:certname]}s from environment %-#{col_len[:environment]}s checked in %#{col_len[:formatted_checkin]}#{@options.round_to}f %s ago with status %-#{col_len[:status]}s\n" + else + "%-#{col_len[:certname]}s checked in %#{col_len[:formatted_checkin]}#{@options.round_to}f %s ago\n" + end end - if node[:last_checkin].to_s =~ /e/ + if node[:last_checkin].to_s.include?('e') @logger.warn "#{node[:certname]} outside the bounds of time and space" - else - if @options.detailed - printf(msg, + elsif @options.detailed + printf(msg, node[:certname], node[:environment], node[:formatted_checkin], @options.outtime, - node[:status] - ) - else - printf(msg, - node[:certname], - node[:formatted_checkin], - @options.outtime - ) - end + node[:status]) + else + printf(msg, + node[:certname], + node[:formatted_checkin], + @options.outtime) end end @@ -437,22 +431,22 @@ class PuppetLast unless @options.files_only if @options.hosts.empty? - hostlist = query_pdb_hosts( @options.port ) || [] + hostlist = query_pdb_hosts(@options.port) || [] else @options.hosts.each do |host| - hostlist << query_pdb_host( host, @options.port ) + hostlist << query_pdb_host(host, @options.port) end end end query_files_hosts(hostlist, @options.hosts) - node_data = transform_hosts( hostlist ) - return 1 if node_data.size == 0 + node_data = transform_hosts(hostlist) + return 1 if node_data.empty? - sorted_data = sort_hosts( node_data,@options.sort_by ) + sorted_data = sort_hosts(node_data, @options.sort_by) - col_len = { :certname=>0, :formatted_checkin=>0, :environment=>0, :status=>0 } + col_len = { certname: 0, formatted_checkin: 0, environment: 0, status: 0 } if @options.pretty col_len.keys.each do |col| col_len[col] = find_longest(sorted_data, col) @@ -465,40 +459,38 @@ class PuppetLast # but users can specify nodes manually if node[:expired] @logger.info "#{node[:certname]} expired" + elsif node[:last_checkin].nil? + print_node_without_checkin(node, col_len) else - if node[:last_checkin].nil? - print_node_without_checkin(node, col_len) - else - print_node_with_checkin(node, col_len) - end + print_node_with_checkin(node, col_len) end end - return 0 - rescue SignalException =>e + 0 + rescue SignalException => e if e.inspect == 'Interrupt' @logger.fatal "\nProcessing interrupted! Exiting." else @logger.fatal "\nProcess received signal #{e.message}. Exiting!" - e.backtrace.first(10).each{|l| @logger.fatal l } + e.backtrace.first(10).each { |l| @logger.fatal l } end - return 1 - rescue RuntimeError =>e + 1 + rescue RuntimeError => e @logger.error(e.message) - return 1 + 1 rescue => e @logger.error("\n#{e.message}") - e.backtrace.first(10).each{|l| @logger.error l } - return 1 + e.backtrace.first(10).each { |l| @logger.error l } + 1 end private def get_report_dir - %x{puppet config print reportdir}.strip + `puppet config print reportdir`.strip end end -if __FILE__ == $0 +if __FILE__ == $PROGRAM_NAME pl = PuppetLast.new exit pl.main(ARGV) end diff --git a/scripts/sbin/updaterepos b/scripts/sbin/updaterepos index 7504178..74ea28e 100755 --- a/scripts/sbin/updaterepos +++ b/scripts/sbin/updaterepos @@ -1,26 +1,27 @@ #!/opt/puppetlabs/puppet/bin/ruby +require 'English' + # This class shamelessly borrowed from # http://www.software-testing.com.au/blog/2010/01/13/text-based-progress-bar-in-ruby-for-command-line-programs/ class ProgressBar - attr_accessor :items_to_do, :items_done - def initialize(items_to_do, items_done=0) + def initialize(items_to_do, items_done = 0) reset(items_to_do, items_done) end def percent_complete - return (@items_complete*1.0/@items_to_do*1.0)*100 + (@items_complete * 1.0 / @items_to_do * 1.0) * 100 end - def advance(steps_to_advance=1) - @items_complete+=steps_to_advance + def advance(steps_to_advance = 1) + @items_complete += steps_to_advance end - def reset(items_to_do, items_done=0) - @items_to_do=items_to_do - @items_complete=items_done + def reset(items_to_do, items_done = 0) + @items_to_do = items_to_do + @items_complete = items_done end def report @@ -32,59 +33,57 @@ class ProgressBar end def progress_bar - complete_bar=(percent_complete/2.0).floor - incomplete_bar=((100-percent_complete)/2.0).ceil - return "[#{"*"*complete_bar}#{"-"*incomplete_bar}]" + complete_bar = (percent_complete / 2.0).floor + incomplete_bar = ((100 - percent_complete) / 2.0).ceil + "[#{'*' * complete_bar}#{'-' * incomplete_bar}]" end end require 'find' require 'fileutils' -File.umask(0027) +File.umask(0o027) -( ARGV[0] && tgt_dir = ARGV[0] ) || tgt_dir = '/var/www/yum/SIMP' +(ARGV[0] && tgt_dir = ARGV[0]) || tgt_dir = '/var/www/yum/SIMP' -if not File.directory?(tgt_dir) then - fail "Error: Could not find directory '#{tgt_dir}'." +unless File.directory?(tgt_dir) + raise "Error: Could not find directory '#{tgt_dir}'." end -Dir.chdir(tgt_dir) { - +Dir.chdir(tgt_dir) do Dir.glob('*').each do |dir| - if File.directory?(dir) and dir.to_s != 'noarch' then - Dir.chdir(dir) { - $stdout.puts "Updating: #{tgt_dir}/#{dir}" - - Dir.glob('*.rpm').each do |symlink| - if File.symlink?(symlink) and File.readlink(symlink) =~ /^\.\.\/noarch/ then - File.unlink(symlink) - end + next unless File.directory?(dir) && (dir.to_s != 'noarch') + Dir.chdir(dir) do + $stdout.puts "Updating: #{tgt_dir}/#{dir}" + + Dir.glob('*.rpm').each do |symlink| + if File.symlink?(symlink) && File.readlink(symlink) =~ %r{^\.\./noarch} + File.unlink(symlink) end + end - link_rpms = Dir.glob('../noarch/*.rpm') + link_rpms = Dir.glob('../noarch/*.rpm') - progress = ProgressBar.new(link_rpms.size) + progress = ProgressBar.new(link_rpms.size) - link_rpms.each do |rpm| - FileUtils.ln_sf(rpm,"./#{File.basename(rpm)}") - progress.advance - progress.percent_report - end - puts + link_rpms.each do |rpm| + FileUtils.ln_sf(rpm, "./#{File.basename(rpm)}") + progress.advance + progress.percent_report + end + puts - File.umask(0022) - %x{/usr/bin/createrepo -p --update .} - result = $? - File.umask(0027) + File.umask(0o022) + `/usr/bin/createrepo_c -p --update .` + result = $CHILD_STATUS + File.umask(0o027) - FileUtils.chown_R('root','apache', Dir.pwd) - FileUtils.chmod_R('g+srX', Dir.pwd) + FileUtils.chown_R('root', 'apache', Dir.pwd) + FileUtils.chmod_R('g+srX', Dir.pwd) - if result != 0 then - $stderr.puts("Warning: There was an error running createrepo on #{tgt_dir}/#{dir}") - end - } + if result != 0 + $stderr.puts("Warning: There was an error running createrepo_c on #{tgt_dir}/#{dir}") + end end end -} +end diff --git a/share/ldifs/convert_to_inetorg.rb b/share/ldifs/convert_to_inetorg.rb index a828369..f8eabad 100755 --- a/share/ldifs/convert_to_inetorg.rb +++ b/share/ldifs/convert_to_inetorg.rb @@ -8,28 +8,28 @@ # LDAP Stuff domain = 'your.domain' -base_dn = domain.split('.').map{|x| x = "dc=#{x}"}.join(',') +base_dn = domain.split('.').map { |x| "dc=#{x}" }.join(',') ldap_server = "puppet.#{domain}" ldap_admin_user = "cn=LDAPAdmin,ou=People,#{base_dn}" -print "Enter LDAP Admin Password: " -stty_settings = %x{stty -g} +print 'Enter LDAP Admin Password: ' +stty_settings = `stty -g` begin - %x{stty -echo} + `stty -echo` password = gets password.chomp! ensure - %x{stty #{stty_settings}} + `stty #{stty_settings}` end # Get the appropriate LDAP entries -conn = LDAP::SSLConn.new(ldap_server,389,true) +conn = LDAP::SSLConn.new(ldap_server, 389, true) conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) -conn.set_option(LDAP::LDAP_OPT_TIMELIMIT,30) -conn.simple_bind(ldap_admin_user,password) +conn.set_option(LDAP::LDAP_OPT_TIMELIMIT, 30) +conn.simple_bind(ldap_admin_user, password) search_string = '(!(objectClass=inetOrgPerson))' -conn.search("ou=People,#{base_dn}",LDAP::LDAP_SCOPE_SUBTREE,search_string,'*',false,30) { |entry| +conn.search("ou=People,#{base_dn}", LDAP::LDAP_SCOPE_SUBTREE, search_string, '*', false, 30) do |entry| new_entry = entry.to_hash dn = new_entry.delete('dn') @@ -41,23 +41,23 @@ new_entry['objectClass'] << 'inetOrgPerson' uid = new_entry['uid'].first - gn,sn = uid.split('.') - if not sn then + gn, sn = uid.split('.') + unless sn sn = gn[1..-1] gn = gn[0].chr end gn.capitalize! - sn and sn.capitalize! + sn&.capitalize! - new_entry['givenName'] = ["#{gn}"] - new_entry['sn'] = ["#{sn}"] + new_entry['givenName'] = [gn.to_s] + new_entry['sn'] = [sn.to_s] new_entry['cn'] = ["#{gn} #{sn}"] new_entry['mail'] = ["#{uid}@#{domain}"] conn.delete(dn) - conn.add(dn,new_entry) -} + conn.add(dn, new_entry) +end exit diff --git a/share/transition_scripts/openldap_to_389ds/openldap_to_389ds.rb b/share/transition_scripts/openldap_to_389ds/openldap_to_389ds.rb index dbf4720..3679775 100755 --- a/share/transition_scripts/openldap_to_389ds/openldap_to_389ds.rb +++ b/share/transition_scripts/openldap_to_389ds/openldap_to_389ds.rb @@ -26,14 +26,14 @@ # - memberuid is copied into to member before deletion # - sshpublickey is copied into nssshpublickey before deletion -DELETE_KEYS = %i[ - entrycsn - entryuuid - memberuid - pwdaccountlockedtime - pwdchangedtime - pwdfailuretime - sshpublickey +DELETE_KEYS = [ + :entrycsn, + :entryuuid, + :memberuid, + :pwdaccountlockedtime, + :pwdchangedtime, + :pwdfailuretime, + :sshpublickey, ].freeze def convert_group(attrs, userdn) @@ -43,7 +43,7 @@ def convert_group(attrs, userdn) newattrs[a].delete_if { |x| x.nil? || x.strip.empty? } - newattrs[a] += %w[groupOfNames nsMemberOf posixGroup] if a == :objectclass + newattrs[a] += ['groupOfNames', 'nsMemberOf', 'posixGroup'] if a == :objectclass newattrs[a].uniq! end @@ -56,8 +56,8 @@ def convert_group(attrs, userdn) def convert_user(attrs) newattrs = {} - lastname = "" - firstname = "" + lastname = '' + firstname = '' attrs.each do |a, v| newattrs[a] = v.dup @@ -79,7 +79,6 @@ def convert_user(attrs) firstname = newattrs[a].first end - if a == :sshpublickey newattrs[a] = [''] if newattrs[a].empty? newattrs[:nssshpublickey] = newattrs[a] @@ -105,7 +104,7 @@ def convert_user(attrs) opts.banner = "Usage: #{$PROGRAM_NAME} -i INFILE -o OUTFILE [-b BASEDN]" # in case we are using system Ruby on EL7 (2.0.0), don't use # <<~ - opts.separator <<-HELP_MSG.gsub(/^ /,'') + opts.separator <<~HELP_MSG See the README.md for detailed instructions. OPTIONS: @@ -115,23 +114,20 @@ def convert_user(attrs) opts.on('-b', '--basedn BASEDN', 'Base DN of the LDAP server. When absent,', 'will attempt to determine it from the input', - 'file.' - ) do |b| + 'file.') do |b| basedn = b.strip end opts.on('-i', '--input INFILE', 'Input LDIF file containing the slapcat dump', 'of the OpenLDAP server.', - 'Default: ./simp_openldap.ldif' - ) do |f| + 'Default: ./simp_openldap.ldif') do |f| input_ldif = f.strip end opts.on('-o', '--output OUTFILE', 'Generated LDIF file for import into 389-DS.', - 'Default: ./simp_389ds.ldif' - ) do |f| + 'Default: ./simp_389ds.ldif') do |f| output_ldif = f.strip end @@ -140,7 +136,7 @@ def convert_user(attrs) exit end - opts.separator <<-HELP_MSG.gsub(/^ /,'') + opts.separator <<~HELP_MSG EXAMPLES: # To use the default locations for input and output files @@ -163,7 +159,7 @@ def convert_user(attrs) fh = File.open(input_ldif, 'r') begin ldifs = Net::LDAP::Dataset.read_ldif(fh) -rescue Exception => e +rescue StandardError => e warn "ERROR: Malformed LDIF input:\n#{e}\n#{e.backtrace.join("\n")}" exit 1 ensure @@ -208,7 +204,7 @@ def convert_user(attrs) File.open(output_ldif, 'w') do |ofh| ofh.puts(ldifs389.to_ldif.join("\n")) end -rescue Exception => e +rescue StandardError => e warn "ERROR: Output file could not be created:\n#{e}\n#{e.backtrace.join("\n")}" exit 1 end diff --git a/spec/acceptance/suites/default/00_gen_ldap_update_spec.rb b/spec/acceptance/suites/default/00_gen_ldap_update_spec.rb index c68a642..960dcfd 100644 --- a/spec/acceptance/suites/default/00_gen_ldap_update_spec.rb +++ b/spec/acceptance/suites/default/00_gen_ldap_update_spec.rb @@ -18,7 +18,7 @@ hosts.each do |host| context 'set up' do - it 'should set up common test files' do + it 'sets up common test files' do scp_to(host, 'scripts/sbin/gen-ldap-update', '/root/gen-ldap-update') on(host, 'chmod +x /root/gen-ldap-update') @@ -28,101 +28,100 @@ end context 'when /etc/openldap/ldap.conf is present' do - it 'should remove old ldap.conf files and install test /etc/openldap/ldap.conf' do + it 'removes old ldap.conf files and install test /etc/openldap/ldap.conf' do on(host, 'rm -f /etc/ldap.conf /etc/openldap/ldap.conf') scp_to(host, File.join(files_dir, 'etc_openldap_ldap.conf'), '/etc/openldap/ldap.conf') end - it 'should generate ldap modify instructions for configured domain' do + it 'generates ldap modify instructions for configured domain' do results = on(host, '/root/gen-ldap-update') expect(results.stdout).to eq modify_ldif end end context 'when /etc/ldap.conf is present' do - it 'should remove old ldap.conf files and install test /etc/ldap.conf' do + it 'removes old ldap.conf files and install test /etc/ldap.conf' do on(host, 'rm -f /etc/ldap.conf /etc/openldap/ldap.conf') scp_to(host, File.join(files_dir, 'etc_ldap.conf'), '/etc/ldap.conf') end - it 'should generate ldap modify instructions for configured domain' do + it 'generates ldap modify instructions for configured domain' do results = on(host, '/root/gen-ldap-update') expect(results.stdout).to eq modify_ldif end end context 'when host domain does not match default.ldif domain' do - it 'should remove old ldap.conf files and install /etc/openldap/ldap.conf with different domain' do + it 'removes old ldap.conf files and install /etc/openldap/ldap.conf with different domain' do on(host, 'rm -f /etc/ldap.conf /etc/openldap/ldap.conf') scp_to(host, File.join(files_dir, 'etc_openldap_ldap_other_domain.conf'), '/etc/openldap/ldap.conf') end - it 'should fail to generate ldap modify instructions' do - on(host, '/root/gen-ldap-update', :acceptable_exit_codes => [1]) + it 'fails to generate ldap modify instructions' do + on(host, '/root/gen-ldap-update', acceptable_exit_codes: [1]) end end context 'when DNs of interest do not exist in default.ldif' do - it 'should restore test /etc/openldap/ldap.conf' do + it 'restores test /etc/openldap/ldap.conf' do scp_to(host, File.join(files_dir, 'etc_openldap_ldap.conf'), '/etc/openldap/ldap.conf') end - it 'should install test /etc/openldap/default.ldif missing DNs of interest' do + it 'installs test /etc/openldap/default.ldif missing DNs of interest' do scp_to(host, File.join(files_dir, 'incomplete_default.ldif'), '/etc/openldap/default.ldif') end - it 'should fail to generate ldap modify instructions' do - on(host, '/root/gen-ldap-update', :acceptable_exit_codes => [1]) + it 'fails to generate ldap modify instructions' do + on(host, '/root/gen-ldap-update', acceptable_exit_codes: [1]) end end context 'when /etc/openldap/default.ldif is absent' do - it 'should remove default.ldif on hosts' do + it 'removes default.ldif on hosts' do on(host, 'rm /etc/openldap/default.ldif') end - it 'should fail to generate ldap modify instructions' do - on(host, '/root/gen-ldap-update', :acceptable_exit_codes => [1]) + it 'fails to generate ldap modify instructions' do + on(host, '/root/gen-ldap-update', acceptable_exit_codes: [1]) end end context 'when no ldap configuration is present' do - let(:host_base_dn) { - fact_on(host, 'networking.domain').split('.').map{ |d| "dc=#{d}" }.join(',') - } + let(:host_base_dn) do + fact_on(host, 'networking.domain').split('.').map { |d| "dc=#{d}" }.join(',') + end - it 'should remove old ldap.conf files' do + it 'removes old ldap.conf files' do on(host, 'rm -f /etc/ldap.conf /etc/openldap/ldap.conf') end - it 'should install default.ldif with base_dn using host domain' do + it 'installs default.ldif with base_dn using host domain' do default_ldif_txt = File.read(File.join(files_dir, 'default.ldif')) default_ldif_txt.gsub!('dc=example,dc=com', host_base_dn) create_remote_file(host, '/etc/openldap/default.ldif', default_ldif_txt) end - # FIXME This is hack that wouldn't be necessary if gen-ldap-update used + # FIXME: This is hack that wouldn't be necessary if gen-ldap-update used # the domain fact? - it 'should fix hostname' do - fqdn = fact_on(host,'networking.fqdn').strip + it 'fixes hostname' do + fqdn = fact_on(host, 'networking.fqdn').strip hostname = on(host, 'hostname').stdout.strip if fqdn != hostname on(host, "hostname #{fqdn}") end end - it 'should generate ldap modify instructions for host domain' do + it 'generates ldap modify instructions for host domain' do results = on(host, '/root/gen-ldap-update') expected = modify_ldif.gsub('dc=example,dc=com', host_base_dn) expect(results.stdout).to eq expected end - end context 'restore for next test' do - it 'should remove mock system directories/files created for tests' do + it 'removes mock system directories/files created for tests' do on(host, 'rm -rf /etc/ldap.conf /etc/openldap') - end + end end end end diff --git a/spec/acceptance/suites/default/10_updaterepos_spec.rb b/spec/acceptance/suites/default/10_updaterepos_spec.rb index 3354b75..edb24a2 100644 --- a/spec/acceptance/suites/default/10_updaterepos_spec.rb +++ b/spec/acceptance/suites/default/10_updaterepos_spec.rb @@ -8,15 +8,12 @@ # +repo_filename+: Path of the repo file to be installed # # @fails if the specified repo file cannot be installed on host -def copy_repo(host, repo_filename, repo_name = 'simp_manual.repo') - if File.exist?(repo_filename) - puts('='*72) - puts("Using repos defined in #{repo_filename}") - puts('='*72) - scp_to(hosts, repo_filename, "/etc/yum.repos.d/#{repo_name}") - else - fail("File #{repo_filename} could not be found") - end +def copy_repo(_host, repo_filename, repo_name = 'simp_manual.repo') + raise("File #{repo_filename} could not be found") unless File.exist?(repo_filename) + puts('=' * 72) + puts("Using repos defined in #{repo_filename}") + puts('=' * 72) + scp_to(hosts, repo_filename, "/etc/yum.repos.d/#{repo_name}") end # Set up SIMP repos on the host @@ -33,7 +30,7 @@ def copy_repo(host, repo_filename, repo_name = 'simp_manual.repo') # simp-community-postgresql) # # @fails if the specified repos cannot be installed on host -def set_up_simp_repos(host, set_up_simp_main = true, set_up_simp_deps = true ) +def set_up_simp_repos(host, set_up_simp_main = true, set_up_simp_deps = true) reponame = ENV['BEAKER_repo'] if reponame && (reponame[0] == '/') copy_repo(host, reponame) @@ -58,82 +55,80 @@ def repo_dir(repo) end def set_up_local_repo(host, repo_name) - repo_spec = < [1]) + on(host, command, acceptable_exit_codes: [1]) end end context "#{repo_dir(repo)} does exist" do - it 'should set up local repositories' do + it 'sets up local repositories' do set_up_local_repo(host, repo) end - it "should set up #{repo_dir(repo)}" do + it "sets up #{repo_dir(repo)}" do on(host, "mkdir -p #{repo_dir(repo)}/noarch #{repo_dir(repo)}/x86_64") on(host, "cp /root/staging/noarch/* #{repo_dir(repo)}/noarch") on(host, "cp /root/staging/x86_64/* #{repo_dir(repo)}/x86_64") end it "updaterepos should update the #{repo} YUM repo" do - on(host, command, :pty => true ) + on(host, command, pty: true) on(host, 'yum makecache') (noarch_rpms + x86_64_rpms).each do |pkg| result = on(host, "yum provides -C #{pkg}") - expect(result.stdout).to match(/^Repo\s*:\s*#{repo}\-local\-x86_64/) + expect(result.stdout).to match(%r{^Repo\s*:\s*#{repo}\-local\-x86_64}) end end it 'updaterepos should provide links of noarch RPMs' do noarch_rpms.each do |pkg| info = on(host, "ls -al #{repo_dir(repo)}/x86_64/#{pkg}*.rpm").stdout.strip - expect(info).to match(/lrwxrwxrwx.*\s+\->\s+\.\.\/noarch\/#{Regexp.escape(pkg)}/) + expect(info).to match(%r{lrwxrwxrwx.*\s+\->\s+\.\./noarch/#{Regexp.escape(pkg)}}) end end it 'updaterepos should allow apache group access to repodata' do info = on(host, "ls -ld #{repo_dir(repo)}/x86_64/repodata").stdout.strip - expect(info).to match(/^drwxr\-[xs].*root\s+apache/) + expect(info).to match(%r{^drwxr\-[xs].*root\s+apache}) info = on(host, "ls -l #{repo_dir(repo)}/x86_64/repodata/").stdout.strip info.split("\n").each do |file_info| - next if file_info.match(/^total/) - expect(file_info).to match(/^.rw.r\-..*root\s+apache/) + next if file_info.match?(%r{^total}) + expect(file_info).to match(%r{^.rw.r\-..*root\s+apache}) end end it 'updaterepos should allow apache group access to directories and files' do info = on(host, "ls -ld #{repo_dir(repo)}/x86_64").stdout.strip - expect(info).to match(/^drwxr\-[xs].*root\s+apache/) + expect(info).to match(%r{^drwxr\-[xs].*root\s+apache}) info = on(host, "ls -l #{repo_dir(repo)}/x86_64/").stdout.strip info.split("\n").each do |file_info| - next if file_info.match(/^total/) - expect(file_info).to match(/^.rw.r..*root\s+apache/) + next if file_info.match?(%r{^total}) + expect(file_info).to match(%r{^.rw.r..*root\s+apache}) end end it 'updaterepos should be safely re-run' do - on(host, command, :pty => true ) + on(host, command, pty: true) end end end - test_name 'updaterepos unit test' describe 'updaterepos unit test' do - hosts.each do |host| os_major = fact_on(host, 'os.release.major') if os_major == '8' @@ -141,33 +136,37 @@ def set_up_local_repo(host, repo_name) next end - let(:noarch_rpms) { [ - 'pupmod-puppetlabs-stdlib', - 'pupmod-simp-simplib', - 'simp-adapter' - ] } + let(:noarch_rpms) do + [ + 'pupmod-puppetlabs-stdlib', + 'pupmod-simp-simplib', + 'simp-adapter', + ] + end - let(:x86_64_rpms) { [ - 'sudosh2', - 'chkrootkit' - ] } + let(:x86_64_rpms) do + [ + 'sudosh2', + 'chkrootkit', + ] + end context "setup on #{host}" do - it 'should set up common test files' do + it 'sets up common test files' do scp_to(host, 'scripts/sbin/updaterepos', '/root/updaterepos') on(host, 'chmod +x /root/updaterepos') end - it 'should set up remote repositories' do + it 'sets up remote repositories' do enable_epel_on(host) set_up_simp_repos(host) - host.install_package('createrepo') + host.install_package('createrepo_c') host.install_package('yum-utils') host.install_package('httpd') on(host, 'yum makecache') end - it 'should download but not install packages' do + it 'downloads but not install packages' do on(host, 'mkdir -p /root/staging/noarch') noarch_rpms.each do |pkg| on(host, "cd /root/staging/noarch; yumdownloader #{pkg}") @@ -178,11 +177,9 @@ def set_up_local_repo(host, repo_name) on(host, "cd /root/staging/x86_64; yumdownloader #{pkg}") end end - end context "updaterepos operation on #{host}" do - context 'with no arguments' do it_behaves_like('a YUM repo updater', host, 'SIMP', '/root/updaterepos') end diff --git a/spec/acceptance/suites/default/20_openldap_to_389ds_spec.rb b/spec/acceptance/suites/default/20_openldap_to_389ds_spec.rb index 6ad9d1e..48fc2ec 100644 --- a/spec/acceptance/suites/default/20_openldap_to_389ds_spec.rb +++ b/spec/acceptance/suites/default/20_openldap_to_389ds_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper_acceptance' describe 'OpenLDAP to 389DS convert and import scripts' do - ldap_server = only_host_with_role(hosts, 'ldap_server') ldap_server_fqdn = fact_on(ldap_server, 'networking.fqdn') @@ -16,7 +15,6 @@ let(:base_dn) { 'dc=test,dc=org' } - # Notes: # - We tell the users to install simp-utils and rubygem-net-ldap packages # on the EL8 server hosting 389DS, but they may try to run the converter @@ -29,35 +27,35 @@ # hosts.each do |host| context "Executing converter script on #{host}" do - it 'should install net-ldap Ruby gem RPM from EPEL' do + it 'installs net-ldap Ruby gem RPM from EPEL' do # This will install into system ruby host.install_package('rubygem-net-ldap') end - it 'should install the converter script' do + it 'installs the converter script' do scp_to(host, "#{scripts_src}/#{File.basename(converter)}", converter) on(host, "chmod +x #{converter}") end - it 'should install input data' do + it 'installs input data' do on(host, "mkdir -p #{ldif_dir}") scp_to(host, "#{files_dir}/#{File.basename(openldap_ldif)}", openldap_ldif) scp_to(host, "#{files_dir}/#{File.basename(malformed_openldap_ldif)}", malformed_openldap_ldif) scp_to(host, "#{files_dir}/#{File.basename(missing_domain_openldap_ldif)}", missing_domain_openldap_ldif) end - it 'should print help' do + it 'prints help' do on(host, 'echo $PATH') on(host, "/usr/bin/ruby #{converter} -h") end - it 'should convert a valid input file using default options' do + it 'converts a valid input file using default options' do on(host, "cd #{ldif_dir}; /usr/bin/ruby #{converter}") output = on(host, "cat #{ds389_ldif}").stdout expect(output).to eq File.read(File.join(files_dir, 'simp_389ds.ldif')) end - it 'should convert a valid input file using specified options' do + it 'converts a valid input file using specified options' do infile = "#{ldif_dir}/myinput.ldif" outfile = "#{ldif_dir}/myoutput.ldif" on(host, "cp #{openldap_ldif} #{infile}") @@ -66,120 +64,122 @@ converter, "-i #{infile}", "-o #{outfile}", - "-b #{base_dn}" + "-b #{base_dn}", ].join(' ') on(host, cmd) output = on(host, "cat #{outfile}").stdout expect(output).to eq File.read(File.join(files_dir, 'simp_389ds.ldif')) end - it 'should fail when the input file does not exist' do + it 'fails when the input file does not exist' do cmd = [ '/usr/bin/ruby', converter, '-i /oops/simp_openldap.ldif', '-o oops_simp_389ds.ldif', - "-b #{base_dn}" + "-b #{base_dn}", ].join(' ') - on(host, cmd, :acceptable_exit_codes => [1]) + on(host, cmd, acceptable_exit_codes: [1]) end - it 'should fail when the input file does not contain valid LDIF data' do + it 'fails when the input file does not contain valid LDIF data' do cmd = [ '/usr/bin/ruby', converter, "-i #{malformed_openldap_ldif}", '-o malformed_389ds.ldif', - "-b #{base_dn}" + "-b #{base_dn}", ].join(' ') - on(host, cmd, :acceptable_exit_codes => [1]) + on(host, cmd, acceptable_exit_codes: [1]) end - it 'should fail when base DN is not specified and cannot be determined from input LDIF' do + it 'fails when base DN is not specified and cannot be determined from input LDIF' do cmd = [ '/usr/bin/ruby', converter, "-i #{missing_domain_openldap_ldif}", - '-o missing_domain_389ds.ldif' + '-o missing_domain_389ds.ldif', ].join(' ') - on(host, cmd, :acceptable_exit_codes => [1]) + on(host, cmd, acceptable_exit_codes: [1]) end - it 'should fail when the output file cannot be created' do + it 'fails when the output file cannot be created' do cmd = [ '/usr/bin/ruby', converter, "-i #{openldap_ldif}", '-o /does/not/exist/dir/simp_d389ds.ldif', ].join(' ') - on(host, cmd, :acceptable_exit_codes => [1]) + on(host, cmd, acceptable_exit_codes: [1]) end - it 'should fail when the input file has no users or groups for base DN' do + it 'fails when the input file has no users or groups for base DN' do cmd = [ '/usr/bin/ruby', converter, "-i #{openldap_ldif}", # specify a domain that does not match what is in the input file - '-b dc=some,dc=other,dc=org' + '-b dc=some,dc=other,dc=org', ].join(' ') - on(host, cmd, :acceptable_exit_codes => [1]) + on(host, cmd, acceptable_exit_codes: [1]) end end end context "Executing importer script on #{ldap_server}" do let(:ds_root_name) { 'accounts' } - let(:hieradata) { { - 'simp_options::firewall' => false, - 'simp_options::trusted_nets' => ['any'], - 'simp_options::pki' => true, - 'simp_options::pki::source' => '/etc/pki/simp-testing/pki', - 'pki::private_key_source' => '/etc/pki/simp-testing/pki/private/%{facts.networking.fqdn}.pem', - 'pki::public_key_source' => '/etc/pki/simp-testing/pki/public/%{facts.networking.fqdn}.pub', - 'pki::cacerts_sources' => [ '/etc/pki/simp-testing/pki/cacerts'], - 'simp_options::ldap' => true, - 'simp_options::ldap::uri' => [ "ldaps://#{ldap_server_fqdn}" ], - 'simp_options::ldap::base_dn' => base_dn, - 'simp_options::ldap::bind_dn' => "cn=hostAuth,ou=Hosts,#{base_dn}", - 'simp_options::ldap::bind_pw' => 'foobarbaz', - 'simp_options::ldap::bind_hash' => '{SSHA}BNPDR0qqE6HyLTSlg13T0e/+yZnSgYQz', - 'simp_options::ldap::master' => "ldaps://#{ldap_server_fqdn}", - 'simp_options::ldap::root_dn' => "cn=LDAPAdmin,ou=People,#{base_dn}", - 'simp_ds389::instances::accounts::root_pw' => 'suP3rP@ssw0r!' - } } - - let(:remove_ldap_server_manifest) { + let(:hieradata) do + { + 'simp_options::firewall' => false, + 'simp_options::trusted_nets' => ['any'], + 'simp_options::pki' => true, + 'simp_options::pki::source' => '/etc/pki/simp-testing/pki', + 'pki::private_key_source' => '/etc/pki/simp-testing/pki/private/%{facts.networking.fqdn}.pem', + 'pki::public_key_source' => '/etc/pki/simp-testing/pki/public/%{facts.networking.fqdn}.pub', + 'pki::cacerts_sources' => [ '/etc/pki/simp-testing/pki/cacerts'], + 'simp_options::ldap' => true, + 'simp_options::ldap::uri' => [ "ldaps://#{ldap_server_fqdn}" ], + 'simp_options::ldap::base_dn' => base_dn, + 'simp_options::ldap::bind_dn' => "cn=hostAuth,ou=Hosts,#{base_dn}", + 'simp_options::ldap::bind_pw' => 'foobarbaz', + 'simp_options::ldap::bind_hash' => '{SSHA}BNPDR0qqE6HyLTSlg13T0e/+yZnSgYQz', + 'simp_options::ldap::master' => "ldaps://#{ldap_server_fqdn}", + 'simp_options::ldap::root_dn' => "cn=LDAPAdmin,ou=People,#{base_dn}", + 'simp_ds389::instances::accounts::root_pw' => 'suP3rP@ssw0r!', + } + end + + let(:remove_ldap_server_manifest) do "ds389::instance { 'accounts': ensure => 'absent' }" - } + end - let(:install_ldap_server_manifest) { + let(:install_ldap_server_manifest) do "include 'simp_ds389::instances::accounts'" - } + end shared_examples_for 'an accounts 389DS instance installer' do - it 'should ensure hieradata is appropriately set' do + it 'ensures hieradata is appropriately set' do set_hieradata_on(ldap_server, hieradata) end - it 'should ensure any existing accounts instance is removed' do + it 'ensures any existing accounts instance is removed' do apply_manifest_on(ldap_server, remove_ldap_server_manifest, catch_failures: true) end - it 'should apply simp_ds389::accounts::instance with no errors' do + it 'applies simp_ds389::accounts::instance with no errors' do apply_manifest_on(ldap_server, install_ldap_server_manifest, catch_failures: true) apply_manifest_on(ldap_server, install_ldap_server_manifest, catch_changes: true) end end shared_examples_for 'a LDAP import validator' do - it 'should create a searchable LDAP tree' do + it 'creates a searchable LDAP tree' do # Just verifying a standard ldapsearch from the top of the tree doesn't # fail. This output is also helpful for debug. on(ldap_server, 'ldapsearch -Y EXTERNAL -H ldapi://%2fvar%2frun%2fslapd-accounts.socket') end - it 'should import groups' do + it 'imports groups' do group_list = on(ldap_server, "dsidm accounts -b #{base_dn} posixgroup list").stdout [ 'NotAllowed', @@ -198,7 +198,7 @@ end end - it 'should import users' do + it 'imports users' do user_list = on(ldap_server, "dsidm accounts -b #{base_dn} user list").stdout [ 'admin1', # in admin1, administrators, and users groups @@ -212,29 +212,29 @@ end end - it 'should add members to groups' do + it 'adds members to groups' do { 'NotAllowed' => [ - "member: uid=baduser,ou=People,#{base_dn}" + "member: uid=baduser,ou=People,#{base_dn}", ], 'administrators' => [ "member: uid=admin1,ou=People,#{base_dn}", - "member: uid=admin2,ou=People,#{base_dn}" + "member: uid=admin2,ou=People,#{base_dn}", ], 'security' => [ - "member: uid=auditor1,ou=People,#{base_dn}" + "member: uid=auditor1,ou=People,#{base_dn}", ], 'testgroup' => [ "member: uid=user1,ou=People,#{base_dn}", - "member: uid=user2,ou=People,#{base_dn}" + "member: uid=user2,ou=People,#{base_dn}", ], 'users' => [ "member: uid=admin1,ou=People,#{base_dn}", "member: uid=admin2,ou=People,#{base_dn}", "member: uid=user1,ou=People,#{base_dn}", - "member: uid=user2,ou=People,#{base_dn}" - ] - }.each do |group,member_attrs| + "member: uid=user2,ou=People,#{base_dn}", + ], + }.each do |group, member_attrs| group_ldif = on(ldap_server, "dsidm accounts -b #{base_dn} posixgroup get #{group}").stdout member_attrs.each do |member_attr| expect(group_ldif).to match(%r{^#{member_attr}$}) @@ -244,7 +244,7 @@ end context 'import script install' do - it 'should install import script' do + it 'installs import script' do scp_to(ldap_server, "#{scripts_src}/#{File.basename(importer)}", importer) on(ldap_server, "chmod +x #{importer}") end @@ -252,53 +252,53 @@ # usecase that matches the README.md context 'import into a base accounts instance using specified input file' do - include_examples 'an accounts 389DS instance installer' + it_behaves_like 'an accounts 389DS instance installer' - it 'should execute without error using specified LDIF file' do + it 'executes without error using specified LDIF file' do on(ldap_server, "#{importer} #{ds389_ldif}") end - include_examples 'a LDAP import validator' + it_behaves_like 'a LDAP import validator' end context 'import into a base accounts instance using default input file' do - include_examples 'an accounts 389DS instance installer' + it_behaves_like 'an accounts 389DS instance installer' - it 'should execute without error using default LDIF file' do + it 'executes without error using default LDIF file' do on(ldap_server, "cd #{ldif_dir}; #{importer}") end - include_examples 'a LDAP import validator' + it_behaves_like 'a LDAP import validator' end context 'import failures' do - it 'should fail if the input file does not exist' do + it 'fails if the input file does not exist' do missing_ldif = '/does/not/exist/simp_ds389.ldif' - result = on(ldap_server, "#{importer} #{missing_ldif}", :acceptable_exit_codes => [1]) + result = on(ldap_server, "#{importer} #{missing_ldif}", acceptable_exit_codes: [1]) expect(result.stdout).to match(%r{File '#{missing_ldif}' does not exist}) end - it 'should fail if there are no People or Groups in the LDIF to import' do + it 'fails if there are no People or Groups in the LDIF to import' do empty_ldif = "#{ldif_dir}/empty_simp_ds389.ldif" on(ldap_server, "touch #{empty_ldif}") - result = on(ldap_server, "#{importer} #{empty_ldif}", :acceptable_exit_codes => [1]) + result = on(ldap_server, "#{importer} #{empty_ldif}", acceptable_exit_codes: [1]) expect(result.stdout).to match('Could not find any People or Groups') end - it 'should fail to import into an accounts instance with non-empty users or administrators groups' do + it 'fails to import into an accounts instance with non-empty users or administrators groups' do # this test **assumes** the account instance is up and had populated the # users and/or administrators groups via a previous, successful import - on(ldap_server, "#{importer} #{ds389_ldif}", :acceptable_exit_codes => [1]) + on(ldap_server, "#{importer} #{ds389_ldif}", acceptable_exit_codes: [1]) end - it 'should fail if the accounts 389ds instance does not exist' do + it 'fails if the accounts 389ds instance does not exist' do apply_manifest_on(ldap_server, remove_ldap_server_manifest, catch_failures: true) - result = on(ldap_server, "#{importer} #{ds389_ldif}", :acceptable_exit_codes => [1]) + on(ldap_server, "#{importer} #{ds389_ldif}", acceptable_exit_codes: [1]) end - it 'should fail if it cannot find the dsidm command' do + it 'fails if it cannot find the dsidm command' do # dsidm is in /usr/sbin - result = on(ldap_server, "PATH=/usr/bin #{importer} #{ds389_ldif}", :acceptable_exit_codes => [1]) + on(ldap_server, "PATH=/usr/bin #{importer} #{ds389_ldif}", acceptable_exit_codes: [1]) end end end diff --git a/spec/scripts/bin/set_environment_spec.rb b/spec/scripts/bin/set_environment_spec.rb index 7fa8434..d636206 100644 --- a/spec/scripts/bin/set_environment_spec.rb +++ b/spec/scripts/bin/set_environment_spec.rb @@ -1,4 +1,4 @@ -$: << File.expand_path(File.join(File.dirname(__FILE__), '..','..','..', 'tests')) +$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'tests')) require 'spec_helper' require 'set_environment' @@ -6,35 +6,34 @@ # "require 'set_environment'" works properly. (Missing suffix is the # problem...) describe 'Simp::YamlNodeClassifier' do - let(:classifier) { Simp::YamlNodeClassifier.new } describe '#run' do let(:config) { File.join(File.dirname(__FILE__), 'files', 'valid_config.yaml') } let(:latest_and_greatest_yaml) { "---\nenvironment: latest_and_greatest\n" } let(:production_yaml) { "---\nenvironment: production\n" } - + context 'valid configuration' do it 'outputs environment for matching, specific hostname rule' do - expect{ + expect { classifier.run(['worker1.test.local'], config) }.to output(latest_and_greatest_yaml).to_stdout end it 'outputs environment for matching, hostname regex rule' do - expect{ + expect { classifier.run(['worker10.test.local'], config) }.to output(production_yaml).to_stdout end it 'outputs environment for first matching rule found' do - expect{ + expect { classifier.run(['logserver1.test.local'], config) }.to output(production_yaml).to_stdout end it 'outputs default environment when no matching rule is found' do - expect{ + expect { classifier.run(['es1.test.local'], config) }.to output(production_yaml).to_stdout end @@ -42,7 +41,7 @@ context 'no configuration' do it "outputs 'production' environment for any node" do - expect{ + expect { classifier.run(['anything'], '/does/not/exist.yaml') }.to output(production_yaml).to_stdout end @@ -50,16 +49,16 @@ context 'invalid configuration' do it 'fails when the configuration YAML cannot be parsed' do - invalid_config = File.join(File.dirname(__FILE__), 'files', 'invalid_config.yaml') - expect{ + invalid_config = File.join(File.dirname(__FILE__), 'files', 'invalid_config.yaml') + expect { classifier.run(['logserver1.test.local'], invalid_config) }.to raise_error(RuntimeError) end it "'fails when a regex rule is missing the trailing '/'" do - invalid_config = File.join(File.dirname(__FILE__), 'files', 'invalid_rule_config.yaml') - err_msg = /is not a valid hostname or regex/ - expect{ + invalid_config = File.join(File.dirname(__FILE__), 'files', 'invalid_rule_config.yaml') + err_msg = %r{is not a valid hostname or regex} + expect { classifier.run(['logserver1.test.local'], invalid_config) }.to raise_error(RuntimeError, err_msg) end @@ -67,7 +66,7 @@ context 'extra input' do it 'ignores extra inputs when more than 1 input is supplied' do - expect{ + expect { classifier.run(['worker1.test.local', 'extra.test.local'], config) }.to output(latest_and_greatest_yaml).to_stdout end @@ -75,8 +74,8 @@ context 'invalid input' do it 'fails when a single input is not supplied' do - err_msg = /You must pass the FQDN of the host as the first argument/ - expect{ + err_msg = %r{You must pass the FQDN of the host as the first argument} + expect { classifier.run([], config).to raise_error(RuntimeError, err_msg) }.to raise_error(RuntimeError, err_msg) end diff --git a/spec/scripts/bin/unpack_dvd_spec.rb b/spec/scripts/bin/unpack_dvd_spec.rb index 8858a22..f121c4e 100644 --- a/spec/scripts/bin/unpack_dvd_spec.rb +++ b/spec/scripts/bin/unpack_dvd_spec.rb @@ -1,15 +1,20 @@ +require 'English' require 'spec_helper' -describe 'unpack_dvd script' do - before(:all) do - require 'tmpdir' - @tmpdir = Dir.mktmpdir +def tmpdir + return @tmpdir if @tmpdir - at_exit do - FileUtils.remove_entry_secure(@tmpdir) if File.directory?(@tmpdir) - end + require 'tmpdir' + @tmpdir = Dir.mktmpdir + + at_exit do + FileUtils.remove_entry_secure(@tmpdir) if File.directory?(@tmpdir) end + @tmpdir +end + +describe 'unpack_dvd script' do let(:unpack_dvd) do File.expand_path('../../../scripts/bin/unpack_dvd', __dir__) end @@ -25,7 +30,7 @@ '-r', '-v', '-T', - '-m TRANS.TBL' + '-m TRANS.TBL', ].join(' ') end @@ -33,35 +38,33 @@ 'mkisofs', 'isoinfo', 'rpmbuild', - 'createrepo', + 'createrepo_c', ] require 'facter' - missing_apps = required_apps.select{|x| !Facter::Core::Execution.which(x)} - + missing_apps = required_apps.reject { |x| Facter::Core::Execution.which(x) } Dir.glob(File.join(__dir__, 'files', 'unpack_dvd', 'ISO', '*')).each do |target| next unless File.directory?(target) target_name = File.basename(target) context "when unpacking an ISO for #{target_name}" do - before(:each) { - working_dir = File.join(@tmpdir, target_name) - @output_dir = File.join(working_dir,'output') - @tftpboot_dir = File.join(working_dir,'tftpboot') - FileUtils.mkdir_p([@output_dir, @tftpboot_dir]) - } - after(:each) do - FileUtils.remove_entry_secure(@output_dir) if File.directory?(@output_dir) - FileUtils.remove_entry_secure(@tftpboot_dir) if File.directory?(@tftpboot_dir) - end - + let(:working_dir) { File.join(tmpdir, target_name) } let(:os) { target_name.split('_').first } let(:os_version) { target_name.split('_').last } let(:os_version_xyz) { (os_version.split('.').size > 1) ? os_version : "#{os_version}.x.y" } - let(:iso_path) { File.join(@tmpdir, "#{target_name}.iso") } - let(:output_dir) { @output_dir } - let(:tftpboot_dir) { @tftpboot_dir } - let(:cmd){ "ruby '#{unpack_dvd}' -d '#{output_dir}' '#{iso_path}'" } + let(:iso_path) { File.join(tmpdir, "#{target_name}.iso") } + let(:output_dir) { File.join(working_dir, 'output') } + let(:tftpboot_dir) { File.join(working_dir, 'tftpboot') } + let(:cmd) { "ruby '#{unpack_dvd}' -d '#{output_dir}' '#{iso_path}'" } + + before(:each) do + FileUtils.mkdir_p([output_dir, tftpboot_dir]) + end + + after(:each) do + FileUtils.remove_entry_secure(output_dir) if File.directory?(output_dir) + FileUtils.remove_entry_secure(tftpboot_dir) if File.directory?(tftpboot_dir) + end unless missing_apps.empty? it 'runs unpack_dvd' do @@ -70,60 +73,64 @@ break end - it "builds a mock ISO to test #{target_name}" do - Dir.chdir(target) do - %x[#{mkisofs} -o #{iso_path} .] - expect($?.exitstatus).to eq 0 - end - end - - context 'when running unpack_dvd' do + context 'when running unpack_dvd' do before(:each) do + # Build the mock ISO for testing + Dir.chdir(target) do + `#{mkisofs} -o #{iso_path} .` + raise "Failed to build mock ISO for #{target_name}" unless $CHILD_STATUS.exitstatus == 0 + end + + # Run the unpack_dvd command Dir.chdir(target) do - %x{#{cmd}} + `#{cmd}` end end + + after(:each) do + File.delete(iso_path) if File.exist?(iso_path) + end + let!(:exit_status) do - $?.exitstatus + $CHILD_STATUS.exitstatus end context 'without -v' do if target_name.split('_').first == 'CentOS' - it('fails (because CentOS ISOs only provide major OS versions)'){ expect(exit_status).to eq 1 } + it('fails (because CentOS ISOs only provide major OS versions)') { expect(exit_status).to eq 1 } else - it("executes without failures"){ expect(exit_status).to eq 0 } + it('executes without failures') { expect(exit_status).to eq 0 } end end context 'with -v x.y.z' do - let(:cmd){ "#{super()} -v #{os_version_xyz}" } + let(:cmd) { "#{super()} -v #{os_version_xyz}" } - it('executes without failures'){ expect(exit_status).to eq 0 } + it('executes without failures') { expect(exit_status).to eq 0 } it 'creates a populated Updates/repodata' do glob = File.join(output_dir, os, os_version_xyz, '**', 'Updates', 'repodata', '*') - expect( Dir.glob(glob).grep(/repomd\.xml$/)).not_to be_empty + expect(Dir.glob(glob).grep(%r{repomd\.xml$})).not_to be_empty end - it "symlinks yum repo [os_version] to [os_version_xyz]" do + it 'symlinks yum repo [os_version] to [os_version_xyz]' do src = File.join(output_dir, os, os_version_xyz) symlink = File.join(output_dir, os, os_version) - expect( File.readlink(symlink) ).to eql File.basename(src) + expect(File.readlink(symlink)).to eql File.basename(src) end context 'with --unpack-pxe' do - let(:cmd){ "#{super()} --unpack-pxe #{tftpboot_dir} --no-unpack-yum" } + let(:cmd) { "#{super()} --unpack-pxe #{tftpboot_dir} --no-unpack-yum" } - it('executes without failures'){ expect(exit_status).to eq 0 } + it('executes without failures') { expect(exit_status).to eq 0 } it 'has a populated tftpboot directory' do glob = File.join(tftpboot_dir, "#{os.downcase}-#{os_version_xyz}-x86_64", '*') - expect( Dir.glob(glob).grep(%r[/dummy\.img$])).not_to be_empty + expect(Dir.glob(glob).grep(%r{/dummy\.img$})).not_to be_empty end - it "symlinks tftpboot/centos-[os_version]-x86_64 to tftpboot/centos-[os_version_xyz]-x86_64" do + it 'symlinks tftpboot/centos-[os_version]-x86_64 to tftpboot/centos-[os_version_xyz]-x86_64' do src = File.join(tftpboot_dir, "#{os.downcase}-#{os_version_xyz}-x86_64") symlink = File.join(tftpboot_dir, "#{os.downcase}-#{os_version}-x86_64") - expect( File.readlink(symlink) ).to eql File.basename(src) + expect(File.readlink(symlink)).to eql File.basename(src) end - end end end diff --git a/spec/scripts/sbin/puppetlast_spec.rb b/spec/scripts/sbin/puppetlast_spec.rb index 0e9bee7..2a59b8c 100644 --- a/spec/scripts/sbin/puppetlast_spec.rb +++ b/spec/scripts/sbin/puppetlast_spec.rb @@ -1,4 +1,4 @@ -$: << File.expand_path(File.join(File.dirname(__FILE__), '..','..','..', 'tests')) +$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'tests')) require 'spec_helper' require 'uri' require 'pry' @@ -9,33 +9,42 @@ # was difficult or impossible to test, so there was as symlink created in the # tests/ directory to rename the file to a proper '.rb'. describe 'PuppetLast' do - let(:pl) { PuppetLast.new } - let(:all_hosts) { { - :json_doc => File.read(File.expand_path('spec/files/all_hosts.json')), - :json_obj => JSON.parse(File.read(File.expand_path('spec/files/all_hosts.json')), :symbolize_names => true) - } } + let(:all_hosts) do + { + json_doc: File.read(File.expand_path('spec/files/all_hosts.json')), + json_obj: JSON.parse(File.read(File.expand_path('spec/files/all_hosts.json')), symbolize_names: true), + } + end - let(:client6) { { - :json_doc => File.read(File.expand_path('spec/files/client6.json')), - :json_obj => JSON.parse(File.read(File.expand_path('spec/files/client6.json')), :symbolize_names => true) - } } + let(:client6) do # rubocop:disable RSpec/IndexedLet + { + json_doc: File.read(File.expand_path('spec/files/client6.json')), + json_obj: JSON.parse(File.read(File.expand_path('spec/files/client6.json')), symbolize_names: true), + } + end - let(:client7) { { - :json_doc => File.read(File.expand_path('spec/files/client7.json')), - :json_obj => JSON.parse(File.read(File.expand_path('spec/files/client7.json')), :symbolize_names => true) - } } + let(:client7) do # rubocop:disable RSpec/IndexedLet + { + json_doc: File.read(File.expand_path('spec/files/client7.json')), + json_obj: JSON.parse(File.read(File.expand_path('spec/files/client7.json')), symbolize_names: true), + } + end - let(:client9) { { - :json_doc => File.read(File.expand_path('spec/files/client9.json')), - :json_obj => JSON.parse(File.read(File.expand_path('spec/files/client9.json')), :symbolize_names => true) - } } + let(:client9) do # rubocop:disable RSpec/IndexedLet + { + json_doc: File.read(File.expand_path('spec/files/client9.json')), + json_obj: JSON.parse(File.read(File.expand_path('spec/files/client9.json')), symbolize_names: true), + } + end - let(:puppet) { { - :json_doc => File.read(File.expand_path('spec/files/puppet.json')), - :json_obj => JSON.parse(File.read(File.expand_path('spec/files/puppet.json')), :symbolize_names => true) - } } + let(:puppet) do + { + json_doc: File.read(File.expand_path('spec/files/puppet.json')), + json_obj: JSON.parse(File.read(File.expand_path('spec/files/puppet.json')), symbolize_names: true), + } + end describe 'parse_options' do skip('this is just an optparse implementation') @@ -56,20 +65,19 @@ it 'lists data about a specific host from PuppetDB' do expect(pl.query_pdb_host('client6.test.net', 8138)).to eq(client6[:json_obj]) end - end context 'without PuppetDB running' do it 'tells the user it cannot reach PuppetDB' do - expect{ - err_msg =< unsorted, 'certname' => default, 'time' => last checkin, 'status' => last run status, 'environments' => node environment - -t, --timeformat TF Select output time format (seconds, minutes, hours, days) - -p, --pretty Format the output more attractively. - -P, --port The port that PuppetDB is listening on - -f, --files-only Only use the local files, not PuppetDB - -l, --log-level level Set the log level (fatal, error, warn, info, debug) - -h, --help Help Message -EOF - expect{ pl.main(['-h']) }.to output(expected).to_stdout - expect( pl.main(['-h']) ).to eq(0) + expected = <<~EOF + Usage: puppetlast.rb [options] + + -d, --detailed Show environment and last run status information + -e, --expiration NUM Don't show systems that have not checked in for more than NUM days. + -S, --status a,b,c Return only nodes with statuses: 'failed', 'changed', or 'unchanged' + -H, --hosts a,b,c List of hosts (short or long) that you wish to get data on + -E, --environments a,b,c List of environments you want to get data from + -s, --sort-by SORT_OPTION Sort by a given attribute: 'nil' => unsorted, 'certname' => default, 'time' => last checkin, 'status' => last run status, 'environments' => node environment + -t, --timeformat TF Select output time format (seconds, minutes, hours, days) + -p, --pretty Format the output more attractively. + -P, --port The port that PuppetDB is listening on + -f, --files-only Only use the local files, not PuppetDB + -l, --log-level level Set the log level (fatal, error, warn, info, debug) + -h, --help Help Message + EOF + expect { pl.main(['-h']) }.to output(expected).to_stdout + expect(pl.main(['-h'])).to eq(0) end end context 'no parameters' do - it 'should print the last time puppet was ran in hours for all in certname order' do + it 'prints the last time puppet was ran in hours for all in certname order' do expected = <<~EOF client3.test.net has no reported check in client6.test.net checked in 4286.38 minutes ago @@ -154,16 +158,15 @@ client9.test.net checked in 1466.38 minutes ago filehost.test.net checked in 60.01 minutes ago puppet.test.net checked in 60.00 minutes ago - EOF - expect{ pl.main([]) }.to output(expected).to_stdout - expect( pl.main([]) ).to eq(0) + EOF + expect { pl.main([]) }.to output(expected).to_stdout + expect(pl.main([])).to eq(0) end end - context 'with days instead of minutes' do - it 'should print the last time puppet was ran in days' do - out =<<~EOF + it 'prints the last time puppet was ran in days' do + out = <<~EOF client3.test.net has no reported check in client6.test.net checked in 2.98 days ago client7.test.net checked in 1.10 days ago @@ -171,16 +174,15 @@ client9.test.net checked in 1.02 days ago filehost.test.net checked in 0.04 days ago puppet.test.net checked in 0.04 days ago - EOF - expect{pl.main(['-t','days'])}.to output(out).to_stdout - expect(pl.main(['-t','days'])).to eq(0) + EOF + expect { pl.main(['-t', 'days']) }.to output(out).to_stdout + expect(pl.main(['-t', 'days'])).to eq(0) end end - context 'with pretty print' do - it 'should pretty print the last time puppet was ran' do - out =<<~EOF + it 'pretties print the last time puppet was ran' do + out = <<~EOF client3.test.net has no reported check in client6.test.net checked in 4286.38 minutes ago client7.test.net checked in 1586.38 minutes ago @@ -188,14 +190,14 @@ client9.test.net checked in 1466.38 minutes ago filehost.test.net checked in 60.01 minutes ago puppet.test.net checked in 60.00 minutes ago - EOF - expect{pl.main(['-p'])}.to output(out).to_stdout + EOF + expect { pl.main(['-p']) }.to output(out).to_stdout expect(pl.main(['-p'])).to eq(0) end end context 'with detailed print' do - it 'should print the last time puppet was ran and environment and status' do - out =<<~EOF + it 'prints the last time puppet was ran and environment and status' do + out = <<~EOF client3.test.net from environment test has no reported check in client6.test.net from environment production checked in 4286.38 minutes ago with status N/A client7.test.net from environment production checked in 1586.38 minutes ago with status N/A @@ -203,15 +205,15 @@ client9.test.net from environment test checked in 1466.38 minutes ago with status failed filehost.test.net from environment production checked in 60.01 minutes ago with status changed puppet.test.net from environment production checked in 60.00 minutes ago with status changed - EOF + EOF - expect{pl.main(['-d'])}.to output(out).to_stdout + expect { pl.main(['-d']) }.to output(out).to_stdout expect(pl.main(['-d'])).to eq(0) end end context 'certname sorted option' do - it 'should print in certname order' do + it 'prints in certname order' do expected = <<~EOF client3.test.net has no reported check in client6.test.net checked in 4286.38 minutes ago @@ -220,14 +222,14 @@ client9.test.net checked in 1466.38 minutes ago filehost.test.net checked in 60.01 minutes ago puppet.test.net checked in 60.00 minutes ago - EOF - expect{ pl.main(['-s', 'certname']) }.to output(expected).to_stdout - expect( pl.main(['-s', 'certname']) ).to eq(0) + EOF + expect { pl.main(['-s', 'certname']) }.to output(expected).to_stdout + expect(pl.main(['-s', 'certname'])).to eq(0) end end context 'with pretty print and unsorted option' do - it 'should align columns and print in db order' do + it 'aligns columns and print in db order' do expected = <<~EOF puppet.test.net checked in 60.00 minutes ago client6.test.net checked in 4286.38 minutes ago @@ -236,25 +238,25 @@ client9.test.net checked in 1466.38 minutes ago client3.test.net has no reported check in filehost.test.net checked in 60.01 minutes ago - EOF - expect{ pl.main(['-p', '-s', 'nil']) }.to output(expected).to_stdout - expect( pl.main(['-p', '-s', 'nil']) ).to eq(0) + EOF + expect { pl.main(['-p', '-s', 'nil']) }.to output(expected).to_stdout + expect(pl.main(['-p', '-s', 'nil'])).to eq(0) end end context 'with pretty print, detailed print and time-sorted option' do - it 'should align columns, print details and sort based on checked in time' do + it 'aligns columns, print details and sort based on checked in time' do expected = <<~EOF puppet.test.net from environment production checked in 60.00 minutes ago with status changed filehost.test.net from environment production checked in 60.01 minutes ago with status changed - client9.test.net from environment test checked in 1466.38 minutes ago with status failed + client9.test.net from environment test checked in 1466.38 minutes ago with status failed#{' '} client8.test.net from environment test checked in 1526.38 minutes ago with status changed - client7.test.net from environment production checked in 1586.38 minutes ago with status N/A - client6.test.net from environment production checked in 4286.38 minutes ago with status N/A + client7.test.net from environment production checked in 1586.38 minutes ago with status N/A#{' '} + client6.test.net from environment production checked in 4286.38 minutes ago with status N/A#{' '} client3.test.net from environment test has no reported check in - EOF - expect{ pl.main(['-p', '-d', '-s', 'time']) }.to output(expected).to_stdout - expect( pl.main(['-p', '-d', '-s', 'time']) ).to eq(0) + EOF + expect { pl.main(['-p', '-d', '-s', 'time']) }.to output(expected).to_stdout + expect(pl.main(['-p', '-d', '-s', 'time'])).to eq(0) end end @@ -262,17 +264,17 @@ # The sort order when 2 items have the same sort value differs # with different versions of Ruby. So for definitive results, # this test specifies only one node of each status type. - it 'should print details and sort based on status' do + it 'prints details and sort based on status' do expected = <<~EOF puppet.test.net from environment production checked in 60.00 minutes ago with status changed client9.test.net from environment test checked in 1466.38 minutes ago with status failed client7.test.net from environment production checked in 1586.38 minutes ago with status N/A - EOF - args = [ '-d', '-s', 'status', '--hosts', - 'puppet.test.net,client7.test.net,client9.test.net' ] + EOF + args = [ '-d', '-s', 'status', '--hosts', + 'puppet.test.net,client7.test.net,client9.test.net' ] - expect{ pl.main(args) }.to output(expected).to_stdout - expect( pl.main(args) ).to eq(0) + expect { pl.main(args) }.to output(expected).to_stdout + expect(pl.main(args)).to eq(0) end end @@ -280,46 +282,45 @@ # The sort order when 2 items have the same sort value differs # with different versions of Ruby. So for definitive results, # this test specifies only one node of each status type. - it 'should print details and sort based on environment' do - expected = <<-EOF -puppet.test.net from environment production checked in 60.00 minutes ago with status changed -client9.test.net from environment test checked in 1466.38 minutes ago with status failed -EOF - args = [ '-d', '-s', 'environment', '--hosts', - 'puppet.test.net,client9.test.net' ] - - expect{ pl.main(args) }.to output(expected).to_stdout - expect( pl.main(args) ).to eq(0) + it 'prints details and sort based on environment' do + expected = <<~EOF + puppet.test.net from environment production checked in 60.00 minutes ago with status changed + client9.test.net from environment test checked in 1466.38 minutes ago with status failed + EOF + args = [ '-d', '-s', 'environment', '--hosts', + 'puppet.test.net,client9.test.net' ] + + expect { pl.main(args) }.to output(expected).to_stdout + expect(pl.main(args)).to eq(0) end end context 'for a specific host' do - it 'should print the last time puppet was ran' do - expected = <<-EOF -client7.test.net checked in 1586.38 minutes ago -EOF - expect{ pl.main(['--hosts', 'client7.test.net']) }.to output(expected).to_stdout - expect( pl.main(['--hosts', 'client7.test.net']) ).to eq(0) + it 'prints the last time puppet was ran' do + expected = <<~EOF + client7.test.net checked in 1586.38 minutes ago + EOF + expect { pl.main(['--hosts', 'client7.test.net']) }.to output(expected).to_stdout + expect(pl.main(['--hosts', 'client7.test.net'])).to eq(0) end end context 'for multiple hosts' do - it 'should print the last time puppet was ran' do - expected = <<-EOF -client6.test.net checked in 4286.38 minutes ago -client7.test.net checked in 1586.38 minutes ago -EOF - expect{ pl.main(['--hosts', 'client6.test.net,client7.test.net']) }.to output(expected).to_stdout - expect( pl.main(['--hosts', 'client6.test.net,client7.test.net']) ).to eq(0) + it 'prints the last time puppet was ran' do + expected = <<~EOF + client6.test.net checked in 4286.38 minutes ago + client7.test.net checked in 1586.38 minutes ago + EOF + expect { pl.main(['--hosts', 'client6.test.net,client7.test.net']) }.to output(expected).to_stdout + expect(pl.main(['--hosts', 'client6.test.net,client7.test.net'])).to eq(0) end end - - context "time skew early all" do + context 'time skew early all' do # time before oldest timestamp before :each do - Time.stubs(:now).returns(Time.parse("2016-09-24T15:57:36.320Z")) + Time.stubs(:now).returns(Time.parse('2016-09-24T15:57:36.320Z')) end - it 'should tell the user their time in the future' do + it 'tells the user their time in the future' do expected = <<~EOF client3.test.net has no reported check in client6.test.net time issue: 39033.62 minutes in the future @@ -328,27 +329,26 @@ client9.test.net time issue: 41853.62 minutes in the future filehost.test.net time issue: 43259.99 minutes in the future puppet.test.net time issue: 43260.00 minutes in the future - EOF - expect{ pl.main([]) }.to output(expected).to_stdout - expect( pl.main([]) ).to eq(0) + EOF + expect { pl.main([]) }.to output(expected).to_stdout + expect(pl.main([])).to eq(0) end end - context 'for only one environment' do - it 'should print hosts from the specified environment' do + it 'prints hosts from the specified environment' do expected = <<~EOF client6.test.net checked in 4286.38 minutes ago client7.test.net checked in 1586.38 minutes ago filehost.test.net checked in 60.01 minutes ago puppet.test.net checked in 60.00 minutes ago - EOF - expect{ pl.main(['-E', 'production']) }.to output(expected).to_stdout - expect( pl.main(['-E', 'production']) ).to eq(0) + EOF + expect { pl.main(['-E', 'production']) }.to output(expected).to_stdout + expect(pl.main(['-E', 'production'])).to eq(0) end end context 'for many environments' do - it 'should print hosts from the specified environments' do + it 'prints hosts from the specified environments' do expected = <<~EOF client3.test.net has no reported check in client6.test.net checked in 4286.38 minutes ago @@ -357,21 +357,21 @@ client9.test.net checked in 1466.38 minutes ago filehost.test.net checked in 60.01 minutes ago puppet.test.net checked in 60.00 minutes ago - EOF - expect{ pl.main(['-E', 'production,test']) }.to output(expected).to_stdout - expect( pl.main(['-E', 'production,test']) ).to eq(0) + EOF + expect { pl.main(['-E', 'production,test']) }.to output(expected).to_stdout + expect(pl.main(['-E', 'production,test'])).to eq(0) end end context 'with only one status' do - it 'should print hosts from the specified environment' do + it 'prints hosts from the specified environment' do expected = <<~EOF client8.test.net checked in 1526.38 minutes ago filehost.test.net checked in 60.01 minutes ago puppet.test.net checked in 60.00 minutes ago - EOF - expect{ pl.main(['-S', 'changed']) }.to output(expected).to_stdout - expect( pl.main(['-S', 'changed']) ).to eq(0) + EOF + expect { pl.main(['-S', 'changed']) }.to output(expected).to_stdout + expect(pl.main(['-S', 'changed'])).to eq(0) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bf714d9..a9a89e3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -18,7 +18,7 @@ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration require 'simplecov' SimpleCov.start do - add_filter "/spec/" # don't count coverage of test files! + add_filter '/spec/' # don't count coverage of test files! end RSpec.configure do |config| @@ -55,8 +55,8 @@ # Useless backtrace noise backtrace_exclusion_patterns = [ - /spec_helper/, - /gems/ + %r{spec_helper}, + %r{gems}, ] if config.respond_to?(:backtrace_exclusion_patterns) @@ -65,57 +65,55 @@ config.backtrace_clean_patterns = backtrace_exclusion_patterns end -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # This setting enables warnings. It's recommended, but in some cases may - # be too noisy due to issues in dependencies. - config.warnings = true - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # This setting enables warnings. It's recommended, but in some cases may + # # be too noisy due to issues in dependencies. + # config.warnings = true + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = 'doc' + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 1dec9fd..8404c50 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -20,7 +20,6 @@ end end - RSpec.configure do |c| # ensure that environment OS is ready on each host fix_errata_on hosts @@ -34,25 +33,21 @@ # Configure all nodes in nodeset c.before :suite do - begin - # Install modules and dependencies from spec/fixtures/modules - copy_fixture_modules_to( hosts ) - server = only_host_with_role(hosts, 'default') - - # Generate and install PKI certificates on each SUT - Dir.mktmpdir do |cert_dir| - run_fake_pki_ca_on(server, hosts, cert_dir ) - hosts.each{ |sut| copy_pki_to( sut, cert_dir, '/etc/pki/simp-testing' )} - end - - # add PKI keys - copy_keydist_to(server) - rescue StandardError, ScriptError => e - if ENV['PRY'] - require 'pry'; binding.pry - else - raise e - end + # Install modules and dependencies from spec/fixtures/modules + copy_fixture_modules_to(hosts) + server = only_host_with_role(hosts, 'default') + + # Generate and install PKI certificates on each SUT + Dir.mktmpdir do |cert_dir| + run_fake_pki_ca_on(server, hosts, cert_dir) + hosts.each { |sut| copy_pki_to(sut, cert_dir, '/etc/pki/simp-testing') } end + + # add PKI keys + copy_keydist_to(server) + rescue StandardError, ScriptError => e + raise e unless ENV['PRY'] + require 'pry' + binding.pry # rubocop:disable Lint/Debugger end end