diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fe7a8b12b..cdd65d220 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,7 @@ "settings": { "terminal.integrated.profiles.linux": { "bash": { - "path": "bash", + "path": "bash" } } }, diff --git a/.fixtures.yml b/.fixtures.yml index a142a6ab8..a27ae9b8e 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -6,4 +6,4 @@ fixtures: "provision": "https://github.com/puppetlabs/provision.git" puppet_agent: repo: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' - ref: v4.12.1 + ref: v4.13.0 diff --git a/.github/workflows/auto_release.yml b/.github/workflows/auto_release.yml index ca677186e..d6270c56f 100644 --- a/.github/workflows/auto_release.yml +++ b/.github/workflows/auto_release.yml @@ -5,6 +5,5 @@ on: jobs: release_prep: - name: "Release Prep" uses: "puppetlabs/cat-github-actions/.github/workflows/module_release_prep.yml@main" secrets: "inherit" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 82caec76a..0b7b8a05d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,6 @@ on: workflow_dispatch: jobs: - release: - name: "Release" + release: uses: "puppetlabs/cat-github-actions/.github/workflows/module_release.yml@main" secrets: "inherit" diff --git a/.rubocop.yml b/.rubocop.yml index 31e8248ff..a206e025c 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,10 +1,15 @@ --- +inherit_from: .rubocop_todo.yml + require: - rubocop-performance - rubocop-rspec AllCops: + NewCops: enable DisplayCopNames: true - TargetRubyVersion: '2.5' + ExtraDetails: true + DisplayStyleGuide: true + TargetRubyVersion: '2.7' Include: - "**/*.rb" Exclude: @@ -79,441 +84,5 @@ Style/Documentation: - 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/InsecureProtocolSource: - Enabled: false -Gemspec/DuplicatedAssignment: - Enabled: false -Gemspec/OrderedDependencies: - Enabled: false -Gemspec/RequiredRubyVersion: - Enabled: false -Gemspec/RubyVersionGlobalsUsage: - Enabled: false -Layout/ArgumentAlignment: - Enabled: false -Layout/BeginEndAlignment: - Enabled: false -Layout/ClosingHeredocIndentation: - Enabled: false -Layout/EmptyComment: - Enabled: false -Layout/EmptyLineAfterGuardClause: - Enabled: false -Layout/EmptyLinesAroundArguments: - Enabled: false -Layout/EmptyLinesAroundAttributeAccessor: - Enabled: false -Layout/EndOfLine: - Enabled: false -Layout/FirstArgumentIndentation: - Enabled: false -Layout/HashAlignment: - Enabled: false -Layout/HeredocIndentation: - Enabled: false -Layout/LeadingEmptyLines: - Enabled: false -Layout/SpaceAroundMethodCallOperator: - Enabled: false -Layout/SpaceInsideArrayLiteralBrackets: - Enabled: false -Layout/SpaceInsideReferenceBrackets: - Enabled: false -Lint/BigDecimalNew: - Enabled: false -Lint/BooleanSymbol: - Enabled: false -Lint/ConstantDefinitionInBlock: - Enabled: false -Lint/DeprecatedOpenSSLConstant: - Enabled: false -Lint/DisjunctiveAssignmentInConstructor: - Enabled: false -Lint/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/Capybara/CurrentPathExpectation: - Enabled: false -RSpec/Capybara/FeatureMethods: - Enabled: false -RSpec/Capybara/VisibilityMatcher: - Enabled: false -RSpec/ContextMethod: - Enabled: false -RSpec/ContextWording: - Enabled: false -RSpec/DescribeClass: - Enabled: false -RSpec/EmptyHook: - Enabled: false -RSpec/EmptyLineAfterExample: - Enabled: false -RSpec/EmptyLineAfterExampleGroup: - Enabled: false -RSpec/EmptyLineAfterHook: - Enabled: false -RSpec/ExampleLength: - Enabled: false -RSpec/ExampleWithoutDescription: - Enabled: false -RSpec/ExpectChange: - Enabled: false -RSpec/ExpectInHook: - Enabled: false -RSpec/FactoryBot/AttributeDefinedStatically: - Enabled: false -RSpec/FactoryBot/CreateList: - Enabled: false -RSpec/FactoryBot/FactoryClassName: - Enabled: false -RSpec/HooksBeforeExamples: - Enabled: false -RSpec/ImplicitBlockExpectation: - Enabled: false -RSpec/ImplicitSubject: - Enabled: false -RSpec/LeakyConstantDeclaration: - Enabled: false -RSpec/LetBeforeExamples: - Enabled: false -RSpec/MissingExampleGroupArgument: - Enabled: false RSpec/MultipleExpectations: - Enabled: false -RSpec/MultipleMemoizedHelpers: - Enabled: false -RSpec/MultipleSubjects: - Enabled: false -RSpec/NestedGroups: - Enabled: false -RSpec/PredicateMatcher: - Enabled: false -RSpec/ReceiveCounts: - Enabled: false -RSpec/ReceiveNever: - Enabled: false -RSpec/RepeatedExampleGroupBody: - Enabled: false -RSpec/RepeatedExampleGroupDescription: - Enabled: false -RSpec/RepeatedIncludeExample: - Enabled: false -RSpec/ReturnFromStub: - Enabled: false -RSpec/SharedExamples: - Enabled: false -RSpec/StubbedMock: - Enabled: false -RSpec/UnspecifiedException: - Enabled: false -RSpec/VariableDefinition: - Enabled: false -RSpec/VoidExpect: - Enabled: false -RSpec/Yield: - Enabled: false -Security/Open: - Enabled: false -Style/AccessModifierDeclarations: - Enabled: false -Style/AccessorGrouping: - Enabled: false -Style/AsciiComments: - 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: - Enabled: false -Style/TrailingMethodEndStatement: - Enabled: false -Style/UnpackFirst: - Enabled: false -Lint/DuplicateBranch: - Enabled: false -Lint/DuplicateRegexpCharacterClassElement: - Enabled: false -Lint/EmptyBlock: - Enabled: false -Lint/EmptyClass: - Enabled: false -Lint/NoReturnInBeginEndBlocks: - Enabled: false -Lint/ToEnumArguments: - Enabled: false -Lint/UnexpectedBlockArity: - Enabled: false -Lint/UnmodifiedReduceAccumulator: - Enabled: false -Performance/CollectionLiteralInLoop: - Enabled: false -Style/ArgumentsForwarding: - Enabled: false -Style/CollectionCompact: - Enabled: false -Style/DocumentDynamicEvalDefinition: - Enabled: false -Style/NegatedIfElseCondition: - Enabled: false -Style/NilLambda: - Enabled: false -Style/RedundantArgument: - Enabled: false -Style/SwapValues: - Enabled: false + Max: 3 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 000000000..4aca98123 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,128 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2023-04-12 10:15:38 UTC using RuboCop version 1.48.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +Lint/FloatComparison: + Exclude: + - 'spec/spec_helper_acceptance_local.rb' + +# Offense count: 18 +Lint/ReturnInVoidContext: + Exclude: + - 'lib/puppet/provider/mysql_database/mysql.rb' + - 'lib/puppet/provider/mysql_user/mysql.rb' + +# Offense count: 18 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 64 + +# Offense count: 12 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 210 + +# Offense count: 4 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 170 + +# Offense count: 11 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 15 + +# Offense count: 23 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 75 + +# Offense count: 10 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 18 + +# Offense count: 24 +# Configuration parameters: MinSize. +Performance/CollectionLiteralInLoop: + Exclude: + - 'lib/puppet/type/mysql_grant.rb' + - 'spec/classes/mysql_backup_mysqldump_spec.rb' + - 'spec/classes/mysql_backup_xtrabackup_spec.rb' + - 'spec/classes/mysql_server_account_security_spec.rb' + - 'spec/classes/mysql_server_backup_spec.rb' + - 'spec/defines/mysql_db_spec.rb' + +# Offense count: 64 +# Configuration parameters: Prefixes, AllowedPatterns. +# Prefixes: when, with, without +RSpec/ContextWording: + Enabled: false + +# Offense count: 35 +# Configuration parameters: IgnoredMetadata. +RSpec/DescribeClass: + Enabled: false + +# Offense count: 33 +# Configuration parameters: CountAsOne. +RSpec/ExampleLength: + Max: 32 + +# Offense count: 36 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 8 + +# Offense count: 121 +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only +RSpec/NamedSubject: + Exclude: + - 'spec/classes/graceful_failures_spec.rb' + - 'spec/classes/mycnf_template_spec.rb' + - 'spec/classes/mysql_backup_mysqldump_spec.rb' + - 'spec/classes/mysql_backup_xtrabackup_spec.rb' + - 'spec/classes/mysql_client_spec.rb' + - 'spec/classes/mysql_server_account_security_spec.rb' + - 'spec/classes/mysql_server_backup_spec.rb' + - 'spec/classes/mysql_server_spec.rb' + - 'spec/defines/mysql_db_spec.rb' + - 'spec/functions/mysql_normalise_and_deepmerge_spec.rb' + - 'spec/functions/mysql_strip_hash_spec.rb' + +# Offense count: 45 +# Configuration parameters: AllowedGroups. +RSpec/NestedGroups: + Max: 5 + +# Offense count: 64 +# Configuration parameters: AllowedPatterns. +# AllowedPatterns: ^expect_, ^assert_ +RSpec/NoExpectationExample: + Enabled: false + +# Offense count: 61 +RSpec/StubbedMock: + Exclude: + - 'spec/unit/puppet/provider/mysql_database/mysql_spec.rb' + - 'spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb' + - 'spec/unit/puppet/provider/mysql_user/mysql_spec.rb' + +# Offense count: 1 +# Configuration parameters: MinBranchesCount. +Style/HashLikeCase: + Exclude: + - 'lib/puppet/provider/mysql_login_path/inifile.rb' + +# Offense count: 2 +Style/MixinUsage: + Exclude: + - 'spec/spec_helper.rb' + - 'spec/spec_helper_local.rb' diff --git a/Gemfile b/Gemfile index 1881afe15..3f6f5c7d5 100644 --- a/Gemfile +++ b/Gemfile @@ -14,31 +14,31 @@ def location_for(place_or_version, fake_version = nil) end group :development do - gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.5.1', require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.6.1', require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.6.3', require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "voxpupuli-puppet-lint-plugins", '~> 3.1', require: false - gem "facterdb", '~> 1.18', require: false - gem "metadata-json-lint", '>= 2.0.2', '< 4.0.0', require: false - gem "puppetlabs_spec_helper", '>= 3.0.0', '< 5.0.0', require: false - gem "rspec-puppet-facts", '~> 2.0', require: false - gem "codecov", '~> 0.2', require: false - gem "dependency_checker", '~> 0.2', require: false - gem "parallel_tests", '~> 3.4', require: false - gem "pry", '~> 0.10', require: false - gem "simplecov-console", '~> 0.5', require: false - gem "puppet-debugger", '~> 1.0', require: false - gem "rubocop", '= 1.6.1', require: false - gem "rubocop-performance", '= 1.9.1', require: false - gem "rubocop-rspec", '= 2.0.1', require: false - gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "github_changelog_generator", '= 1.15.2', require: false + gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.5.1', require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.6.1', require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.6.3', require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "voxpupuli-puppet-lint-plugins", '~> 4.0', require: false + gem "facterdb", '~> 1.18', require: false + gem "metadata-json-lint", '>= 2.0.2', '< 4.0.0', require: false + gem "puppetlabs_spec_helper", '~> 5.0', require: false + gem "rspec-puppet-facts", '~> 2.0', require: false + gem "codecov", '~> 0.2', require: false + gem "dependency_checker", '~> 0.2', require: false + gem "parallel_tests", '= 3.12.1', require: false + gem "pry", '~> 0.10', require: false + gem "simplecov-console", '~> 0.5', require: false + gem "puppet-debugger", '~> 1.0', require: false + gem "rubocop", '= 1.48.1', require: false + gem "rubocop-performance", '= 1.16.0', require: false + gem "rubocop-rspec", '= 2.19.0', require: false + gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "github_changelog_generator", '= 1.15.2', require: false end group :system_tests do - gem "puppet_litmus", '<= 0.34.6', require: false, platforms: [:ruby] - gem "serverspec", '~> 2.41', require: false + gem "puppet_litmus", '< 1.0.0', require: false, platforms: [:ruby, :x64_mingw] + gem "serverspec", '~> 2.41', require: false end puppet_version = ENV['PUPPET_GEM_VERSION'] diff --git a/REFERENCE.md b/REFERENCE.md index 1b7d9b3f0..7a30e9c31 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -499,6 +499,7 @@ The following parameters are available in the `mysql::server` class: * [`users`](#-mysql--server--users) * [`grants`](#-mysql--server--grants) * [`databases`](#-mysql--server--databases) +* [`reload_on_config_change`](#-mysql--server--reload_on_config_change) * [`enabled`](#-mysql--server--enabled) * [`manage_service`](#-mysql--server--manage_service) * [`old_root_password`](#-mysql--server--old_root_password) @@ -768,6 +769,14 @@ Optional hash of databases to create, which are passed to [mysql_database](#mysq Default value: `{}` +##### `reload_on_config_change` + +Data type: `Boolean` + +By default, a my.cnf change won't reload/restart the database. Turn this flag to true to enable it + +Default value: `false` + ##### `enabled` Data type: `Optional[Variant[String[1], Boolean]]` @@ -1299,7 +1308,7 @@ Privileges for user ##### `table` -Valid values: `%r{.*\..*}`, `%r{^[0-9a-zA-Z$_]*@[\w%\.:\-/]*$}` +Valid values: `%r{.*\..*}`, `%r{^[0-9a-zA-Z$_]*@[\w%.:\-/]*$}` Table to apply privileges to. @@ -1662,7 +1671,7 @@ Plain text password. Data type: `Optional[Boolean]` - +If the mysql password hash should be of datatype Sensitive[String] ## Data types diff --git a/Rakefile b/Rakefile index 151f919c0..5ec5f1789 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,6 @@ require 'bundler' require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any? require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-syntax/tasks/puppet-syntax' -require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any? require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any? diff --git a/lib/facter/mysql_server_id.rb b/lib/facter/mysql_server_id.rb index 171b908d9..33482ba1e 100644 --- a/lib/facter/mysql_server_id.rb +++ b/lib/facter/mysql_server_id.rb @@ -16,7 +16,7 @@ def mysql_id_get Facter.add('mysql_server_id') do setcode do mysql_id_get - rescue + rescue StandardError nil end end diff --git a/lib/puppet/functions/mysql/normalise_and_deepmerge.rb b/lib/puppet/functions/mysql/normalise_and_deepmerge.rb index bb5f884f3..214ca800e 100644 --- a/lib/puppet/functions/mysql/normalise_and_deepmerge.rb +++ b/lib/puppet/functions/mysql/normalise_and_deepmerge.rb @@ -21,17 +21,13 @@ # The given hash normalised # def normalise_and_deepmerge(*args) - if args.length < 2 - raise Puppet::ParseError, _('mysql::normalise_and_deepmerge(): wrong number of arguments (%{args_length}; must be at least 2)') % { args_length: args.length } - end + raise Puppet::ParseError, _('mysql::normalise_and_deepmerge(): wrong number of arguments (%{args_length}; must be at least 2)') % { args_length: args.length } if args.length < 2 result = {} args.each do |arg| next if arg.is_a?(String) && arg.empty? # empty string is synonym for puppet's undef # If the argument was not a hash, skip it. - unless arg.is_a?(Hash) - raise Puppet::ParseError, _('mysql::normalise_and_deepmerge: unexpected argument type %{arg_class}, only expects hash arguments.') % { args_class: args.class } - end + raise Puppet::ParseError, _('mysql::normalise_and_deepmerge: unexpected argument type %{arg_class}, only expects hash arguments.') % { args_class: args.class } unless arg.is_a?(Hash) # We need to make a copy of the hash since it is frozen by puppet current = deep_copy(arg) @@ -47,8 +43,10 @@ def normalise_and_deepmerge(*args) def normalized?(hash, key) return true if hash.key?(key) return false unless %r{-|_}.match?(key) + other_key = key.include?('-') ? key.tr('-', '_') : key.tr('_', '-') return false unless hash.key?(other_key) + hash[key] = hash.delete(other_key) true end @@ -65,6 +63,7 @@ def overlay(hash1, hash2) def deep_copy(inputhash) return inputhash unless inputhash.is_a? Hash + hash = {} inputhash.each do |k, v| hash.store(k, deep_copy(v)) diff --git a/lib/puppet/functions/mysql/password.rb b/lib/puppet/functions/mysql/password.rb index 327c31726..98012c35a 100644 --- a/lib/puppet/functions/mysql/password.rb +++ b/lib/puppet/functions/mysql/password.rb @@ -19,17 +19,15 @@ return_type 'Variant[String, Sensitive[String]]' end - def password(password, sensitive = false) - if password.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) - password = password.unwrap - end + def password(password, sensitive: false) + password = password.unwrap if password.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) result_string = if %r{\*[A-F0-9]{40}$}.match?(password) password elsif password.empty? '' else - '*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(password)).upcase + "*#{Digest::SHA1.hexdigest(Digest::SHA1.digest(password)).upcase}" end if sensitive diff --git a/lib/puppet/functions/mysql_password.rb b/lib/puppet/functions/mysql_password.rb index 89cf313e3..987b7e3fe 100644 --- a/lib/puppet/functions/mysql_password.rb +++ b/lib/puppet/functions/mysql_password.rb @@ -4,6 +4,8 @@ Puppet::Functions.create_function(:mysql_password) do # @param password # Plain text password. + # @param sensitive + # If the mysql password hash should be of datatype Sensitive[String] # # @return # The mysql password hash from the 4.x function mysql::password. @@ -13,7 +15,7 @@ return_type 'Variant[String, Sensitive[String]]' end - def mysql_password(password, sensitive = false) + def mysql_password(password, sensitive: false) call_function('deprecation', 'mysql_password', "This method has been deprecated, please use the namespaced version 'mysql::password' instead.") call_function('mysql::password', password, sensitive) end diff --git a/lib/puppet/provider/mysql.rb b/lib/puppet/provider/mysql.rb index 2c572bb51..ef750039f 100644 --- a/lib/puppet/provider/mysql.rb +++ b/lib/puppet/provider/mysql.rb @@ -6,9 +6,9 @@ class Puppet::Provider::Mysql < Puppet::Provider initvars # Make sure we find mysql commands on CentOS and FreeBSD - ENV['PATH'] = ENV['PATH'] + ':/usr/libexec:/usr/local/libexec:/usr/local/bin' + ENV['PATH'] = "#{ENV.fetch('PATH', nil)}:/usr/libexec:/usr/local/libexec:/usr/local/bin" ENV['LD_LIBRARY_PATH'] = [ - ENV['LD_LIBRARY_PATH'], + ENV.fetch('LD_LIBRARY_PATH', nil), '/usr/lib', '/usr/lib64', '/opt/rh/rh-mysql56/root/usr/lib', @@ -90,7 +90,7 @@ def newer_than(forks_versions) end def self.older_than(forks_versions) - forks_versions.key?(mysqld_type) && Puppet::Util::Package.versioncmp(mysqld_version, forks_versions[mysqld_type]) < 0 + forks_versions.key?(mysqld_type) && Puppet::Util::Package.versioncmp(mysqld_version, forks_versions[mysqld_type]).negative? end def older_than(forks_versions) @@ -158,6 +158,7 @@ def self.cmd_table(table) def self.cmd_privs(privileges) return 'ALL PRIVILEGES' if privileges.include?('ALL') + priv_string = '' privileges.each do |priv| priv_string += "#{priv}, " diff --git a/lib/puppet/provider/mysql_datadir/mysql.rb b/lib/puppet/provider/mysql_datadir/mysql.rb index 31cae9d23..08d6bfa14 100644 --- a/lib/puppet/provider/mysql_datadir/mysql.rb +++ b/lib/puppet/provider/mysql_datadir/mysql.rb @@ -8,7 +8,7 @@ # Make sure we find mysqld on CentOS and mysql_install_db on Gentoo and Solaris 11 ENV['PATH'] = [ - ENV['PATH'], + ENV.fetch('PATH', nil), '/usr/libexec', '/usr/share/mysql/scripts', '/opt/rh/rh-mysql80/root/usr/bin', @@ -47,9 +47,8 @@ def create log_error = @resource.value(:log_error) || '/var/tmp/mysqld_initialize.log' # rubocop:enable Lint/UselessAssignment unless defaults_extra_file.nil? - unless File.exist?(defaults_extra_file) - raise ArgumentError, _('Defaults-extra-file %{file} is missing.') % { file: defaults_extra_file } - end + raise ArgumentError, _('Defaults-extra-file %{file} is missing.') % { file: defaults_extra_file } unless File.exist?(defaults_extra_file) + defaults_extra_file = "--defaults-extra-file=#{defaults_extra_file}" end @@ -65,10 +64,7 @@ def create opts << "--#{opt}=#{val}" unless val.nil? end - if mysqld_version.nil? - debug("Installing MySQL data directory with mysql_install_db #{opts.compact.join(' ')}") - mysql_install_db(opts.compact) - elsif newer_than('mysql' => '5.7.6', 'percona' => '5.7.6') + if !mysqld_version.nil? && newer_than('mysql' => '5.7.6', 'percona' => '5.7.6') opts << "--log-error=#{log_error}" opts << initialize.to_s debug("Initializing MySQL data directory >= 5.7.6 with mysqld: #{opts.compact.join(' ')}") diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb index 7f32e1d1f..de97a69c0 100644 --- a/lib/puppet/provider/mysql_grant/mysql.rb +++ b/lib/puppet/provider/mysql_grant/mysql.rb @@ -19,7 +19,8 @@ def self.instances # Default root user created by mysql_install_db on a host with fqdn # of myhost.mydomain.my: root@myhost.mydomain.my, when MySQL is started # with --skip-name-resolve. - next if %r{There is no such grant defined for user}.match?(e.inspect) + next if e.inspect.include?('There is no such grant defined for user') + raise Puppet::Error, _('#mysql had an error -> %{inspect}') % { inspect: e.inspect } end # Once we have the list of grants generate entries for each. @@ -28,6 +29,7 @@ def self.instances munged_grant = grant.delete("'").delete('`').delete('"') # Matching: GRANT (SELECT, UPDATE) PRIVILEGES ON (*.*) TO ('root')@('127.0.0.1') (WITH GRANT OPTION) next unless match = munged_grant.match(%r{^GRANT\s(.+)\sON\s(.+)\sTO\s(.*)@(.*?)(\s.*)?$}) # rubocop:disable Lint/AssignmentInCondition + privileges, table, user, host, rest = match.captures table.gsub!('\\\\', '\\') @@ -38,7 +40,7 @@ def self.instances # split and sort the column_privileges in the parentheses and rejoin if priv.include?('(') type, col = priv.strip.split(%r{\s+|\b}, 2) - type.upcase + ' (' + col.slice(1...-1).strip.split(%r{\s*,\s*}).sort.join(', ') + ')' + "#{type.upcase} (#{col.slice(1...-1).strip.split(%r{\s*,\s*}).sort.join(', ')})" else # Once we split privileges up on the , we need to make sure we # shortern ALL PRIVILEGES to just all. @@ -62,26 +64,24 @@ def self.instances end sorted_privileges = stripped_privileges.uniq.sort - if newer_than('mysql' => '8.0.0') && sorted_privileges == ['ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', - 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'EVENT', 'EXECUTE', 'FILE', 'INDEX', 'INSERT', 'LOCK TABLES', 'PROCESS', 'REFERENCES', - 'RELOAD', 'REPLICATION CLIENT', 'REPLICATION SLAVE', 'SELECT', 'SHOW DATABASES', 'SHOW VIEW', 'SHUTDOWN', 'SUPER', 'TRIGGER', - 'UPDATE'] - sorted_privileges = ['ALL'] - - # The following two elsif blocks of code are a workaround for issue #1474. - elsif sorted_privileges == ['ALL', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', - 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', - 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', - 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SERVICE_CONNECTION_ADMIN', - 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN'] - sorted_privileges = ['ALL'] - - elsif sorted_privileges == ['ALL', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', - 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', - 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', - 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SENSITIVE_VARIABLES_OBSERVER', - 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', - 'XA_RECOVER_ADMIN'] + mysql_v8_privileges = ['ALTER', 'ALTER ROUTINE', 'CREATE', 'CREATE ROLE', 'CREATE ROUTINE', 'CREATE TABLESPACE', 'CREATE TEMPORARY TABLES', 'CREATE USER', + 'CREATE VIEW', 'DELETE', 'DROP', 'DROP ROLE', 'EVENT', 'EXECUTE', 'FILE', 'INDEX', 'INSERT', 'LOCK TABLES', 'PROCESS', 'REFERENCES', + 'RELOAD', 'REPLICATION CLIENT', 'REPLICATION SLAVE', 'SELECT', 'SHOW DATABASES', 'SHOW VIEW', 'SHUTDOWN', 'SUPER', 'TRIGGER', + 'UPDATE'] + # The following two compare blocks are a workaround for issue #1474. + mysql_pre_v8_privileges_one = ['ALL', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', + 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', + 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', + 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', + 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', + 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN'] + mysql_pre_v8_privileges_two = ['ALL', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', + 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', + 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', + 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', + 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', + 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN'] + if (newer_than('mysql' => '8.0.0') && sorted_privileges == mysql_v8_privileges) || sorted_privileges == mysql_pre_v8_privileges_one || sorted_privileges == mysql_pre_v8_privileges_two sorted_privileges = ['ALL'] end @@ -89,7 +89,7 @@ def self.instances privileges: sorted_privileges, table: table, user: "#{user}@#{host}", - options: options.uniq, + options: options.uniq } end end @@ -198,12 +198,8 @@ def diff_privileges(privileges_old, privileges_new) def privileges=(privileges) diff = diff_privileges(@property_hash[:privileges], privileges) - unless diff[:revoke].empty? - revoke(@property_hash[:user], @property_hash[:table], diff[:revoke]) - end - unless diff[:grant].empty? - grant(@property_hash[:user], @property_hash[:table], diff[:grant], @property_hash[:options]) - end + revoke(@property_hash[:user], @property_hash[:table], diff[:revoke]) unless diff[:revoke].empty? + grant(@property_hash[:user], @property_hash[:table], diff[:grant], @property_hash[:options]) unless diff[:grant].empty? @property_hash[:privileges] = privileges self.privileges end diff --git a/lib/puppet/provider/mysql_login_path/inifile.rb b/lib/puppet/provider/mysql_login_path/inifile.rb index dde42371e..98d23f04e 100644 --- a/lib/puppet/provider/mysql_login_path/inifile.rb +++ b/lib/puppet/provider/mysql_login_path/inifile.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # frozen_string_literal: true # See: https://github.com/puppetlabs/puppet/blob/main/lib/puppet/util/inifile.rb @@ -30,6 +29,7 @@ class Error < StandardError; end # Returns an IniFile instance or nil if the file could not be opened. def self.load(filename, opts = {}) return unless File.file? filename + new(opts.merge(filename: filename)) end @@ -220,6 +220,7 @@ def merge!(other) # Returns this IniFile. def each return unless block_given? + @ini.each do |section, hash| hash.each do |param, val| yield section, param, val @@ -240,9 +241,10 @@ def each # end # # Returns this IniFile. - def each_section - return unless block_given? - @ini.each_key { |section| yield section } + def each_section(&block) + return unless block + + @ini.each_key(&block) self end @@ -268,6 +270,7 @@ def delete_section(section) # Returns the Hash of parameter/value pairs for this section. def [](section) return nil if section.nil? + @ini[section.to_s] end @@ -322,7 +325,7 @@ def sections # Returns this IniFile. def freeze super - @ini.each_value { |h| h.freeze } + @ini.each_value(&:freeze) @ini.freeze self end @@ -333,7 +336,7 @@ def freeze # Returns this IniFile. def taint super - @ini.each_value { |h| h.taint } + @ini.each_value(&:taint) @ini.taint self end @@ -373,6 +376,7 @@ def clone def eql?(other) return true if equal? other return false unless other.instance_of? self.class + @ini == other.instance_variable_get(:@ini) end alias == eql? @@ -411,8 +415,7 @@ def parse(content) # object. class Parser attr_writer :section - attr_accessor :property - attr_accessor :value + attr_accessor :property, :value # Create a new IniFile::Parser that can be used to parse the contents of # an .ini file. @@ -609,11 +612,11 @@ def typecast(value) else begin begin - Integer(value) - rescue + Integer(value) + rescue StandardError Float(value) - end - rescue + end + rescue StandardError unescape_value(value) end end @@ -640,4 +643,4 @@ def unescape_value(value) value end end -end # IniFile +end diff --git a/lib/puppet/provider/mysql_login_path/mysql_login_path.rb b/lib/puppet/provider/mysql_login_path/mysql_login_path.rb index a068fa496..76ac829c6 100644 --- a/lib/puppet/provider/mysql_login_path/mysql_login_path.rb +++ b/lib/puppet/provider/mysql_login_path/mysql_login_path.rb @@ -42,13 +42,13 @@ def mysql_config_editor_set_cmd(context, uid, password = nil, *args) output.puts password end end - rescue => e + rescue StandardError => e raise Puppet::ExecutionFailure, _( "Execution of '%{str}' returned %{exit_status}: %{output}", ) % { str: command_str, exit_status: $CHILD_STATUS.exitstatus, - output: e.message, + output: e.message } end end @@ -79,9 +79,7 @@ def get_password(context, uid, name) result = '' output = my_print_defaults_cmd(context, uid, '-s', name) output.split("\n").each do |line| - if %r{\-\-password}.match?(line) - result = line.sub(%r{\-\-password=}, '') - end + result = line.sub(%r{--password=}, '') if line.include?('--password') end result end @@ -107,8 +105,8 @@ def delete_login_path(context, name) mysql_config_editor_cmd(context, uid, 'remove', '-G', login_path) end - def gen_pw(pw) - Puppet::Provider::MysqlLoginPath::Sensitive.new(pw) + def gen_pw(password) + Puppet::Provider::MysqlLoginPath::Sensitive.new(password) end def extract_pw(sensitive) @@ -123,7 +121,7 @@ def list_login_paths(context, uid) result.push(ensure: 'present', name: section, owner: uid.to_s, - title: section + '-' + uid.to_s, + title: "#{section}-#{uid}", host: ini[section]['host'].nil? ? nil : ini[section]['host'], user: ini[section]['user'].nil? ? nil : ini[section]['user'], password: ini[section]['password'].nil? ? nil : gen_pw(get_password(context, uid, section)), @@ -135,7 +133,7 @@ def list_login_paths(context, uid) def get(context, name) result = [] - owner = name.empty? ? ['root'] : name.map { |item| item[:owner] }.compact.uniq + owner = name.empty? ? ['root'] : name.filter_map { |item| item[:owner] }.uniq owner.each do |uid| login_paths = list_login_paths(context, uid) result += login_paths @@ -158,9 +156,7 @@ def delete(context, name) def canonicalize(_context, resources) resources.each do |r| - if r.key?(:password) && r[:password].is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) - r[:password] = gen_pw(extract_pw(r[:password])) - end + r[:password] = gen_pw(extract_pw(r[:password])) if r.key?(:password) && r[:password].is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) end end end diff --git a/lib/puppet/provider/mysql_plugin/mysql.rb b/lib/puppet/provider/mysql_plugin/mysql.rb index 0a331f405..82db9f941 100644 --- a/lib/puppet/provider/mysql_plugin/mysql.rb +++ b/lib/puppet/provider/mysql_plugin/mysql.rb @@ -29,7 +29,7 @@ def self.prefetch(resources) def create # Use plugin_name.so as soname if it's not specified. This won't work on windows as # there it should be plugin_name.dll - @resource[:soname].nil? ? (soname = @resource[:name] + '.so') : (soname = @resource[:soname]) + @resource[:soname].nil? ? (soname = "#{@resource[:name]}.so") : (soname = @resource[:soname]) self.class.mysql_caller("install plugin #{@resource[:name]} soname '#{soname}'", 'regular') @property_hash[:ensure] = :present diff --git a/lib/puppet/provider/mysql_user/mysql.rb b/lib/puppet/provider/mysql_user/mysql.rb index b9c410cf6..a381d6898 100644 --- a/lib/puppet/provider/mysql_user/mysql.rb +++ b/lib/puppet/provider/mysql_user/mysql.rb @@ -12,32 +12,27 @@ def self.instances # To reduce the number of calls to MySQL we collect all the properties in # one big swoop. users.map do |name| - if mysqld_version.nil? - ## Default ... - # rubocop:disable Layout/LineLength - query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'" - elsif newer_than('mysql' => '5.7.6', 'percona' => '5.7.6') + # rubocop:disable Layout/LineLength + if !mysqld_version.nil? && newer_than('mysql' => '5.7.6', 'percona' => '5.7.6') query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, AUTHENTICATION_STRING, PLUGIN FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'" - elsif newer_than('mariadb' => '10.1.21') + elsif !mysqld_version.nil? && newer_than('mariadb' => '10.1.21') query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD, PLUGIN, AUTHENTICATION_STRING FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'" else query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'" end - @max_user_connections, @max_connections_per_hour, @max_queries_per_hour, - @max_updates_per_hour, ssl_type, ssl_cipher, x509_issuer, x509_subject, - @password, @plugin, @authentication_string = mysql_caller(query, 'regular').chomp.split(%r{\t}) + # rubocop:enable Layout/LineLength + @max_user_connections, @max_connections_per_hour, @max_queries_per_hour, @max_updates_per_hour, ssl_type, ssl_cipher, + x509_issuer, x509_subject, @password, @plugin, @authentication_string = mysql_caller(query, 'regular').chomp.split(%r{\t}) @tls_options = parse_tls_options(ssl_type, ssl_cipher, x509_issuer, x509_subject) - if newer_than('mariadb' => '10.1.21') && (@plugin == 'ed25519' || @plugin == 'mysql_native_password') + if (newer_than('mariadb' => '10.1.21') && (@plugin == 'ed25519' || @plugin == 'mysql_native_password')) || + (newer_than('mariadb' => '10.2.16') && older_than('mariadb' => '10.2.19')) || + (newer_than('mariadb' => '10.3.8') && older_than('mariadb' => '10.3.11')) # Some auth plugins (e.g. ed25519) use authentication_string # to store password hash or auth information - @password = @authentication_string - elsif (newer_than('mariadb' => '10.2.16') && older_than('mariadb' => '10.2.19')) || - (newer_than('mariadb' => '10.3.8') && older_than('mariadb' => '10.3.11')) # Old mariadb 10.2 or 10.3 store password hash in authentication_string # https://jira.mariadb.org/browse/MDEV-16238 https://jira.mariadb.org/browse/MDEV-16774 @password = @authentication_string end - # rubocop:enable Layout/LineLength new(name: name, ensure: :present, password_hash: @password, @@ -79,10 +74,10 @@ def create # Use CREATE USER to be compatible with NO_AUTO_CREATE_USER sql_mode # This is also required if you want to specify a authentication plugin if !plugin.nil? - if !password_hash.nil? - self.class.mysql_caller("CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}' AS '#{password_hash}'", 'system') - else + if password_hash.nil? self.class.mysql_caller("CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}'", 'system') + else + self.class.mysql_caller("CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}' AS '#{password_hash}'", 'system') end @property_hash[:ensure] = :present @property_hash[:plugin] = plugin @@ -149,11 +144,9 @@ def password_hash=(string) plugin = @resource.value(:plugin) # We have a fact for the mysql version ... - if mysqld_version.nil? - # default ... if mysqld_version does not work - self.class.mysql_caller("SET PASSWORD FOR #{merged_name} = '#{string}'", 'system') - elsif newer_than('mariadb' => '10.1.21') && plugin == 'ed25519' + if !mysqld_version.nil? && newer_than('mariadb' => '10.1.21') && plugin == 'ed25519' raise ArgumentError, _('ed25519 hash should be 43 bytes long.') unless string.length == 43 + # ALTER USER statement is only available upstream starting 10.2 # https://mariadb.com/kb/en/mariadb-1020-release-notes/ if newer_than('mariadb' => '10.2.0') @@ -165,10 +158,12 @@ def password_hash=(string) sql += " where CONCAT(user, '@', host) = '#{concat_name}'; FLUSH PRIVILEGES" end self.class.mysql_caller(sql, 'system') - elsif newer_than('mysql' => '5.7.6', 'percona' => '5.7.6', 'mariadb' => '10.2.0') + elsif !mysqld_version.nil? && newer_than('mysql' => '5.7.6', 'percona' => '5.7.6', 'mariadb' => '10.2.0') raise ArgumentError, _('Only mysql_native_password (*ABCD...XXX) hashes are supported.') unless %r{^\*|^$}.match?(string) + self.class.mysql_caller("ALTER USER #{merged_name} IDENTIFIED WITH mysql_native_password AS '#{string}'", 'system') else + # default ... if mysqld_version does not work self.class.mysql_caller("SET PASSWORD FOR #{merged_name} = '#{string}'", 'system') end @@ -254,11 +249,12 @@ def tls_options=(array) end def self.parse_tls_options(ssl_type, ssl_cipher, x509_issuer, x509_subject) - if ssl_type == 'ANY' + case ssl_type + when 'ANY' ['SSL'] - elsif ssl_type == 'X509' + when 'X509' ['X509'] - elsif ssl_type == 'SPECIFIED' + when 'SPECIFIED' options = [] options << "CIPHER '#{ssl_cipher}'" if !ssl_cipher.nil? && !ssl_cipher.empty? options << "ISSUER '#{x509_issuer}'" if !x509_issuer.nil? && !x509_issuer.empty? diff --git a/lib/puppet/type/mysql_datadir.rb b/lib/puppet/type/mysql_datadir.rb index 5f8e00988..f2bfe782d 100644 --- a/lib/puppet/type/mysql_datadir.rb +++ b/lib/puppet/type/mysql_datadir.rb @@ -6,7 +6,7 @@ Manage MySQL datadirs with mysql_install_db OR mysqld (5.7.6 and above). @api private - PUPPET + PUPPET ensurable diff --git a/lib/puppet/type/mysql_grant.rb b/lib/puppet/type/mysql_grant.rb index abaa33208..92db6d935 100644 --- a/lib/puppet/type/mysql_grant.rb +++ b/lib/puppet/type/mysql_grant.rb @@ -4,7 +4,7 @@ @doc = <<-PUPPET @summary Manage a MySQL user's rights. - PUPPET + PUPPET ensurable autorequire(:file) { '/root/.my.cnf' } @@ -16,9 +16,7 @@ def initialize(*args) # 'ALL'. This can't be done in the munge in the property as that iterates # over the array and there's no way to replace the entire array before it's # returned to the provider. - if self[:ensure] == :present && Array(self[:privileges]).size > 1 && self[:privileges].to_s.include?('ALL') - self[:privileges] = 'ALL' - end + self[:privileges] = 'ALL' if self[:ensure] == :present && Array(self[:privileges]).size > 1 && self[:privileges].to_s.include?('ALL') # Sort the privileges array in order to ensure the comparision in the provider # self.instances method match. Otherwise this causes it to keep resetting the # privileges. @@ -27,7 +25,7 @@ def initialize(*args) # split and sort the column_privileges in the parentheses and rejoin if priv.include?('(') type, col = priv.strip.split(%r{\s+|\b}, 2) - type.upcase + ' (' + col.slice(1...-1).strip.split(%r{\s*,\s*}).sort.join(', ') + ')' + "#{type.upcase} (#{col.slice(1...-1).strip.split(%r{\s*,\s*}).sort.join(', ')})" else priv.strip.upcase end @@ -39,9 +37,8 @@ def initialize(*args) raise(_('mysql_grant: `privileges` `parameter`: PROXY can only be specified by itself.')) if Array(self[:privileges]).size > 1 && Array(self[:privileges]).include?('PROXY') raise(_('mysql_grant: `table` `parameter` is required.')) if self[:ensure] == :present && self[:table].nil? raise(_('mysql_grant: `user` `parameter` is required.')) if self[:ensure] == :present && self[:user].nil? - if self[:user] && self[:table] - raise(_('mysql_grant: `name` `parameter` must match user@host/table format.')) if self[:name] != "#{self[:user]}/#{self[:table]}" - end + + raise(_('mysql_grant: `name` `parameter` must match user@host/table format.')) if self[:user] && self[:table] && (self[:name] != "#{self[:user]}/#{self[:table]}") end newparam(:name, namevar: true) do @@ -57,7 +54,7 @@ def initialize(*args) validate do |value| mysql_version = Facter.value(:mysql_version) - if value =~ %r{proxy}i && Puppet::Util::Package.versioncmp(mysql_version, '5.5.0') < 0 + if value =~ %r{proxy}i && Puppet::Util::Package.versioncmp(mysql_version, '5.5.0').negative? raise(ArgumentError, _('mysql_grant: PROXY user not supported on mysql versions < 5.5.0. Current version %{version}.') % { version: mysql_version }) end end @@ -67,7 +64,7 @@ def initialize(*args) desc 'Table to apply privileges to.' validate do |value| - if Array(@resource[:privileges]).include?('PROXY') && !%r{^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$}.match(value) + if Array(@resource[:privileges]).include?('PROXY') && !%r{^[0-9a-zA-Z$_]*@[\w%.:\-/]*$}.match(value) raise(ArgumentError, _('mysql_grant: `table` `property` for PROXY should be specified as proxy_user@proxy_host.')) end end @@ -76,7 +73,7 @@ def initialize(*args) value.delete('`') end - newvalues(%r{.*\..*}, %r{^[0-9a-zA-Z$_]*@[\w%\.:\-/]*$}) + newvalues(%r{.*\..*}, %r{^[0-9a-zA-Z$_]*@[\w%.:\-/]*$}) end newproperty(:user) do @@ -87,13 +84,10 @@ def initialize(*args) # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827 # rubocop:disable Lint/AssignmentInCondition # rubocop:disable Lint/UselessAssignment - if matches = %r{^(['`"])((?!\1).)*\1@([\w%\.:\-/]+)$}.match(value) + if matches = %r{^(['`"])((?!\1).)*\1@([\w%.:\-/]+)$}.match(value) user_part = matches[2] host_part = matches[3] - elsif matches = %r{^([0-9a-zA-Z$_]*)@([\w%\.:\-/]+)$}.match(value) - user_part = matches[1] - host_part = matches[2] - elsif matches = %r{^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$}.match(value) + elsif matches = %r{^([0-9a-zA-Z$_]*)@([\w%.:\-/]+)$}.match(value) || matches = %r{^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$}.match(value) user_part = matches[1] host_part = matches[2] else @@ -103,9 +97,9 @@ def initialize(*args) # rubocop:enable Lint/UselessAssignment mysql_version = Facter.value(:mysql_version) unless mysql_version.nil? - raise(ArgumentError, _('mysql_grant: MySQL usernames are limited to a maximum of 16 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '5.7.8') < 0 && user_part.size > 16 - raise(ArgumentError, _('mysql_grant: MySQL usernames are limited to a maximum of 32 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') < 0 && user_part.size > 32 - raise(ArgumentError, _('mysql_grant: MySQL usernames are limited to a maximum of 80 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') > 0 && user_part.size > 80 + raise(ArgumentError, _('mysql_grant: MySQL usernames are limited to a maximum of 16 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '5.7.8').negative? && user_part.size > 16 + raise(ArgumentError, _('mysql_grant: MySQL usernames are limited to a maximum of 32 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0').negative? && user_part.size > 32 + raise(ArgumentError, _('mysql_grant: MySQL usernames are limited to a maximum of 80 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0').positive? && user_part.size > 80 end end diff --git a/lib/puppet/type/mysql_login_path.rb b/lib/puppet/type/mysql_login_path.rb index c7dd24b8a..2fea37e03 100644 --- a/lib/puppet/type/mysql_login_path.rb +++ b/lib/puppet/type/mysql_login_path.rb @@ -5,7 +5,7 @@ Puppet::ResourceApi.register_type( name: 'mysql_login_path', - docs: <<-EOS, + docs: <<-DESCRIPTION, @summary Manage a MySQL login path. @see @@ -31,53 +31,53 @@ This type provides Puppet with the capabilities to store authentication credentials in an obfuscated login path file named .mylogin.cnf created with the mysql_config_editor utility. Supports only MySQL Community Edition > v5.6.6. -EOS + DESCRIPTION features: ['simple_get_filter', 'canonicalize'], title_patterns: [ { pattern: %r{^(?.*[^-])-(?.*)$}, - desc: 'Where the name of the and the owner are provided with a hyphen seperator', + desc: 'Where the name of the and the owner are provided with a hyphen seperator' }, { pattern: %r{^(?.*)$}, - desc: 'Where only the name is provided', + desc: 'Where only the name is provided' }, ], attributes: { ensure: { - type: 'Enum[present, absent]', - desc: 'Whether this resource should be present or absent on the target system.', + type: 'Enum[present, absent]', + desc: 'Whether this resource should be present or absent on the target system.' }, name: { - type: 'String', - desc: 'Name of the login path you want to manage.', - behaviour: :namevar, + type: 'String', + desc: 'Name of the login path you want to manage.', + behaviour: :namevar }, owner: { - type: 'String', - desc: 'The user to whom the logon path should belong.', + type: 'String', + desc: 'The user to whom the logon path should belong.', behaviour: :namevar, - default: 'root', + default: 'root' }, host: { - type: 'Optional[String]', - desc: 'Host name to be entered into the login path.', + type: 'Optional[String]', + desc: 'Host name to be entered into the login path.' }, user: { - type: 'Optional[String]', - desc: 'Username to be entered into the login path.', + type: 'Optional[String]', + desc: 'Username to be entered into the login path.' }, password: { - type: 'Optional[Sensitive[String[1]]]', - desc: 'Password to be entered into login path', + type: 'Optional[Sensitive[String[1]]]', + desc: 'Password to be entered into login path' }, socket: { - type: 'Optional[String]', - desc: 'Socket path to be entered into login path', + type: 'Optional[String]', + desc: 'Socket path to be entered into login path' }, port: { - type: 'Optional[Integer[0,65535]]', - desc: 'Port number to be entered into login path.', - }, + type: 'Optional[Integer[0,65535]]', + desc: 'Port number to be entered into login path.' + } }, ) diff --git a/lib/puppet/type/mysql_user.rb b/lib/puppet/type/mysql_user.rb index dafb9b2c6..6a69478e4 100644 --- a/lib/puppet/type/mysql_user.rb +++ b/lib/puppet/type/mysql_user.rb @@ -5,7 +5,7 @@ @doc = <<-PUPPET @summary Manage a MySQL user. This includes management of users password as well as privileges. - PUPPET + PUPPET ensurable @@ -21,13 +21,10 @@ mysql_version = Facter.value(:mysql_version) # rubocop:disable Lint/AssignmentInCondition # rubocop:disable Lint/UselessAssignment - if matches = %r{^(['`"])((?:(?!\1).)*)\1@([\w%\.:\-/]+)$}.match(value) + if matches = %r{^(['`"])((?:(?!\1).)*)\1@([\w%.:\-/]+)$}.match(value) user_part = matches[2] host_part = matches[3] - elsif matches = %r{^([0-9a-zA-Z$_]*)@([\w%\.:\-/]+)$}.match(value) - user_part = matches[1] - host_part = matches[2] - elsif matches = %r{^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$}.match(value) + elsif matches = %r{^([0-9a-zA-Z$_]*)@([\w%.:\-/]+)$}.match(value) || matches = %r{^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$}.match(value) user_part = matches[1] host_part = matches[2] else @@ -36,9 +33,9 @@ # rubocop:enable Lint/AssignmentInCondition # rubocop:enable Lint/UselessAssignment unless mysql_version.nil? - raise(ArgumentError, _('MySQL usernames are limited to a maximum of 16 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '5.7.8') < 0 && user_part.size > 16 - raise(ArgumentError, _('MySQL usernames are limited to a maximum of 32 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') < 0 && user_part.size > 32 - raise(ArgumentError, _('MySQL usernames are limited to a maximum of 80 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') > 0 && user_part.size > 80 + raise(ArgumentError, _('MySQL usernames are limited to a maximum of 16 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '5.7.8').negative? && user_part.size > 16 + raise(ArgumentError, _('MySQL usernames are limited to a maximum of 32 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0').negative? && user_part.size > 32 + raise(ArgumentError, _('MySQL usernames are limited to a maximum of 80 characters.')) if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0').positive? && user_part.size > 80 end end @@ -97,9 +94,7 @@ def should_to_s(_newvalue) validate do |value| value = [value] unless value.is_a?(Array) if value.include?('NONE') || value.include?('SSL') || value.include?('X509') - if value.length > 1 - raise(ArgumentError, _('`tls_options` `property`: The values NONE, SSL and X509 cannot be used with other options, you may only pick one of them.')) - end + raise(ArgumentError, _('`tls_options` `property`: The values NONE, SSL and X509 cannot be used with other options, you may only pick one of them.')) if value.length > 1 else value.each do |opt| o = opt.match(%r{^(CIPHER|ISSUER|SUBJECT)}i) @@ -107,13 +102,13 @@ def should_to_s(_newvalue) end end end - def insync?(is) + def insync?(insync) # The current value may be nil and we don't # want to call sort on it so make sure we have arrays - if is.is_a?(Array) && @should.is_a?(Array) - is.sort == @should.sort + if insync.is_a?(Array) && @should.is_a?(Array) + insync.sort == @should.sort else - is == @should + insync == @should end end end diff --git a/metadata.json b/metadata.json index 33f8be95f..be9be2d0c 100644 --- a/metadata.json +++ b/metadata.json @@ -79,11 +79,11 @@ "requirements": [ { "name": "puppet", - "version_requirement": ">= 6.24.0 < 8.0.0" + "version_requirement": ">= 7.0.0 < 9.0.0" } ], "description": "MySQL module", "template-url": "https://github.com/puppetlabs/pdk-templates#main", - "template-ref": "2.7.1-0-g9a16c87", - "pdk-version": "2.5.0" + "template-ref": "heads/main-0-ge5b0114", + "pdk-version": "2.7.1" } diff --git a/spec/acceptance/00_mysql_server_spec.rb b/spec/acceptance/00_mysql_server_spec.rb index 69d5bb2ee..5681b6952 100644 --- a/spec/acceptance/00_mysql_server_spec.rb +++ b/spec/acceptance/00_mysql_server_spec.rb @@ -38,8 +38,8 @@ class { 'mysql::server': databases => { 'somedb' => { ensure => 'present', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', }, } } @@ -59,7 +59,7 @@ class { '::mysql::server': 'log-bin' => '/var/log/mariadb/mariadb-bin.log',} } } - MANIFEST + MANIFEST end it 'can be set' do diff --git a/spec/acceptance/01_mysql_db_spec.rb b/spec/acceptance/01_mysql_db_spec.rb index 5f6146656..c21b7be97 100644 --- a/spec/acceptance/01_mysql_db_spec.rb +++ b/spec/acceptance/01_mysql_db_spec.rb @@ -14,8 +14,8 @@ class { 'mysql::server': mysql::db { 'spec1': user => 'root1', password => 'password', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } MANIFEST end @@ -43,8 +43,8 @@ class { 'mysql::server': override_options => { 'root_password' => 'password' } } mysql::db { 'spec2': user => 'root1', password => 'password', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', sql => ['/tmp/spec.sql'], } MANIFEST @@ -70,8 +70,8 @@ class { 'mysql::server': override_options => { 'root_password' => 'password' } } user => 'root1', password => 'password', dbname => 'realdb', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } MANIFEST end diff --git a/spec/acceptance/02_mysql_mariadb_spec.rb b/spec/acceptance/02_mysql_mariadb_spec.rb index bb5cc4646..8eb7e8469 100644 --- a/spec/acceptance/02_mysql_mariadb_spec.rb +++ b/spec/acceptance/02_mysql_mariadb_spec.rb @@ -37,6 +37,7 @@ class { '::mysql::server': it 'apply manifest' do apply_manifest(pp) end + it 'mariadb connection' do result = run_shell('mysql --user="root" --password="strongpassword" -e "status"') expect(result.stdout).to match(%r{MariaDB}) diff --git a/spec/acceptance/04_mysql_backup_spec.rb b/spec/acceptance/04_mysql_backup_spec.rb index d2f55920a..2381693d5 100644 --- a/spec/acceptance/04_mysql_backup_spec.rb +++ b/spec/acceptance/04_mysql_backup_spec.rb @@ -12,8 +12,8 @@ class { 'mysql::server': root_password => 'password' } ]: user => 'backup', password => 'secret', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } class { 'mysql::server::backup': @@ -74,8 +74,8 @@ class { 'mysql::server': root_password => 'password' } ]: user => 'backup', password => 'secret', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } class { 'mysql::server::backup': diff --git a/spec/acceptance/05_mysql_xtrabackup_spec.rb b/spec/acceptance/05_mysql_xtrabackup_spec.rb index 1d6d6cef0..4245c2d6c 100644 --- a/spec/acceptance/05_mysql_xtrabackup_spec.rb +++ b/spec/acceptance/05_mysql_xtrabackup_spec.rb @@ -12,8 +12,8 @@ class { 'mysql::server': root_password => 'password' } ]: user => 'backup', password => 'secret', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } case $facts['os']['family'] { /Debian/: { @@ -130,8 +130,8 @@ class { 'mysql::server': root_password => 'password' } ]: user => 'backup', password => 'secret', - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } case $facts['os']['family'] { /Debian/: { diff --git a/spec/acceptance/types/mysql_database_spec.rb b/spec/acceptance/types/mysql_database_spec.rb index 4f2485703..eb10136fc 100644 --- a/spec/acceptance/types/mysql_database_spec.rb +++ b/spec/acceptance/types/mysql_database_spec.rb @@ -16,8 +16,8 @@ class { 'mysql::server': } pp = <<-MANIFEST mysql_database { 'spec_db': ensure => present, - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } MANIFEST it 'works without errors' do @@ -39,8 +39,8 @@ class { 'mysql::server': } collate => 'latin1_swedish_ci', } mysql_database { 'spec_utf8': - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } MANIFEST it 'creates two db of different types idempotently' do diff --git a/spec/acceptance/types/mysql_grant_spec.rb b/spec/acceptance/types/mysql_grant_spec.rb index 942eb938d..f5ab590c2 100644 --- a/spec/acceptance/types/mysql_grant_spec.rb +++ b/spec/acceptance/types/mysql_grant_spec.rb @@ -262,7 +262,7 @@ class { 'mysql::server': it 'finds short ipv6 #stdout' do run_shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'::1/128'\"") do |r| - expect(r.stdout).to match(%r{GRANT ALL PRIVILEGES ON ['|`]test['|`].* TO ['|`]test['|`]@['|`]::1\/128['|`]}) + expect(r.stdout).to match(%r{GRANT ALL PRIVILEGES ON ['|`]test['|`].* TO ['|`]test['|`]@['|`]::1/128['|`]}) expect(r.stderr).to be_empty end end @@ -274,8 +274,8 @@ class { 'mysql::server': mysql_database { 'foo': ensure => present, - charset => '#{fetch_charset}', - collate => '#{fetch_charset}_general_ci', + charset => '#{charset}', + collate => '#{charset}_general_ci', } exec { 'mysql-create-table': @@ -415,7 +415,7 @@ class { 'mysql::server': describe 'adding function privileges' do it 'works without errors' do - pp = <<-EOS + pp = <<-MANIFEST exec { 'simplefunc-create': command => '/usr/bin/mysql --user="root" --password="password" --database=mysql -NBe "CREATE FUNCTION simplefunc (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN CONCAT(\\'Hello, \\', s, \\'!\\')"', before => Mysql_user['test3@tester'], @@ -432,17 +432,16 @@ class { 'mysql::server': privileges => ['EXECUTE'], require => Mysql_user['test3@tester'], } - EOS + MANIFEST apply_manifest(pp, catch_failures: true) end - # rubocop:enable RSpec/ExampleLength + it 'finds the user' do result = run_shell('mysql -NBe "SHOW GRANTS FOR test3@tester"') expect(result.stdout).to match(%r{GRANT EXECUTE ON FUNCTION `mysql`.`simplefunc` TO ['|`]test3['|`]@['|`]tester['|`]}) expect(result.stderr).to be_empty end - # rubocop:enable RSpec/MultipleExpectations end describe 'proxy privilieges' do @@ -686,7 +685,7 @@ class { 'mysql::server': override_options => { 'root_password' => 'password' } } mysql::db { 'grant_spec_db': user => 'root1', password => 'password', - charset => '#{fetch_charset}', + charset => '#{charset}', sql => ['/tmp/grant_spec_table.sql'], } MANIFEST diff --git a/spec/acceptance/types/mysql_login_path_spec.rb b/spec/acceptance/types/mysql_login_path_spec.rb index d069dbcb2..9c60a4018 100644 --- a/spec/acceptance/types/mysql_login_path_spec.rb +++ b/spec/acceptance/types/mysql_login_path_spec.rb @@ -2,15 +2,14 @@ require 'spec_helper_acceptance' -mysql_version = '5.6' support_bin_dir = '/root/mysql_login_path' -if os[:family] == 'redhat' && os[:release].to_i == 8 - mysql_version = '8.0' -elsif os[:family] == 'debian' && os[:release] =~ %r{9|10|11} - mysql_version = '8.0' -elsif os[:family] == 'ubuntu' && os[:release] =~ %r{18\.04|20\.04} - mysql_version = '5.7' -end +mysql_version = if (os[:family] == 'redhat' && os[:release].to_i == 8) || (os[:family] == 'debian' && os[:release] =~ %r{9|10|11}) + '8.0' + elsif os[:family] == 'ubuntu' && os[:release] =~ %r{18\.04|20\.04} + '5.7' + else + '5.6' + end describe 'mysql_login_path', unless: "#{os[:family]}-#{os[:release].to_i}".include?('suse') do before(:all) do @@ -43,11 +42,13 @@ it 'works with no errors' do apply_manifest(pp, catch_failures: true) end + it 'finds mysql_config_editor binary for the provider' do run_shell('mysql_config_editor -V') do |r| expect(r.stdout).to match(%r{Ver.*#{mysql_version}.*x86_64}) end end + it 'finds my_print_defaults binary for the provider' do run_shell('my_print_defaults -V') do |r| expect(r.exit_status).to eq(0) @@ -78,20 +79,18 @@ it 'works without errors' do apply_manifest(pp, catch_failures: true) end + it 'finds the login path #stdout' do run_shell('mysql_config_editor print --all') do |r| - expect(r.stdout).to match(%r{^\[local_socket\]\n}) - expect(r.stdout).to match(%r{host = localhost\n}) - expect(r.stdout).to match(%r{user = root\n}) - expect(r.stdout).to match(%r{socket = /var/run/mysql/mysql.sock\n}) - - expect(r.stdout).to match(%r{^\[local_tcp\]\n}) - expect(r.stdout).to match(%r{host = 127.0.0.1\n}) - expect(r.stdout).to match(%r{user = network\n}) - expect(r.stdout).to match(%r{port = 3306\n}) + regex_match = [%r{^\[local_socket\]\n}, %r{host = localhost\n}, %r{user = root\n}, %r{socket = /var/run/mysql/mysql.sock\n}, + %r{^\[local_tcp\]\n}, %r{host = 127.0.0.1\n}, %r{user = network\n}, %r{port = 3306\n}] + regex_match.each do |reg| + expect(r.stdout).to match(reg) + end expect(r.stderr).to be_empty end end + it 'finds the login path password #stdout' do run_shell('my_print_defaults -s local_socket') do |r| expect(r.stdout).to match(%r{--password=secure\n}) @@ -122,15 +121,17 @@ it 'works without errors' do apply_manifest(pp, catch_failures: true) end + it 'finds the login path #stdout' do run_shell('mysql_config_editor print -G local_tcp') do |r| - expect(r.stdout).to match(%r{^\[local_tcp\]\n}) - expect(r.stdout).to match(%r{host = 10.0.0.1\n}) - expect(r.stdout).to match(%r{user = network2\n}) - expect(r.stdout).to match(%r{port = 3307\n}) + regex_match = [%r{^\[local_tcp\]\n}, %r{host = 10.0.0.1\n}, %r{user = network2\n}, %r{port = 3307\n}] + regex_match.each do |reg| + expect(r.stdout).to match(reg) + end expect(r.stderr).to be_empty end end + it 'finds the login path password #stdout' do run_shell('my_print_defaults -s local_tcp') do |r| expect(r.stdout).to match(%r{--password=Fort_kn0X\n}) @@ -144,16 +145,21 @@ it 'removes values' do apply_manifest(pp2, catch_failures: true) end + it 'ensure values are removed #stdout' do run_shell('mysql_config_editor print -G local_tcp') do |r| - expect(r.stdout).to match(%r{^\[local_tcp\]\n}) - expect(r.stdout).to match(%r{host = 192.168.0.1\n}) - expect(r.stdout).not_to match(%r{host = 10.0.0.1\n}) - expect(r.stdout).not_to match(%r{user = network2\n}) - expect(r.stdout).not_to match(%r{port = 3307\n}) + regex_match = [%r{^\[local_tcp\]\n}, %r{host = 192.168.0.1\n}] + regex_match.each do |reg| + expect(r.stdout).to match(reg) + end + regex_no_match = [%r{host = 10.0.0.1\n}, %r{user = network2\n}, %r{port = 3307\n}] + regex_no_match.each do |reg| + expect(r.stdout).not_to match(reg) + end expect(r.stderr).to be_empty end end + it 'ensure password removed from the login path #stdout' do run_shell('my_print_defaults -s local_tcp') do |r| expect(r.stdout).not_to match(%r{--password=Fort_kn0X\n}) @@ -174,6 +180,7 @@ it 'works without errors' do apply_manifest(pp, catch_failures: true) end + it 'finds the login path #stdout' do run_shell('mysql_config_editor print --all') do |r| expect(r.stdout).not_to match(%r{^\[local_socket\]\n}) @@ -199,15 +206,17 @@ it 'works without errors' do apply_manifest(pp, catch_failures: true) end + it 'finds the login path #stdout' do run_shell('MYSQL_TEST_LOGIN_FILE=/home/loginpath_test/.mylogin.cnf mysql_config_editor print -G local_tcp') do |r| - expect(r.stdout).to match(%r{^\[local_tcp\]\n}) - expect(r.stdout).to match(%r{host = 10.0.0.2\n}) - expect(r.stdout).to match(%r{user = other\n}) - expect(r.stdout).to match(%r{port = 3306\n}) + regex_match = [%r{^\[local_tcp\]\n}, %r{host = 10.0.0.2\n}, %r{user = other\n}, %r{port = 3306\n}] + regex_match.each do |reg| + expect(r.stdout).to match(reg) + end expect(r.stderr).to be_empty end end + it 'finds the login path password #stdout' do run_shell('MYSQL_TEST_LOGIN_FILE=/home/loginpath_test/.mylogin.cnf my_print_defaults print -s local_tcp') do |r| expect(r.stdout).to match(%r{--password=sensitive\n}) @@ -228,15 +237,17 @@ it 'works without errors' do apply_manifest(pp, catch_failures: true) end + it 'finds the login path #stdout' do run_shell('MYSQL_TEST_LOGIN_FILE=/home/loginpath_test/.mylogin.cnf mysql_config_editor print -G local_tcp') do |r| - expect(r.stdout).to match(%r{^\[local_tcp\]\n}) - expect(r.stdout).to match(%r{host = 10.0.0.3\n}) - expect(r.stdout).to match(%r{user = other2\n}) - expect(r.stdout).to match(%r{port = 3307\n}) + regex_match = [%r{^\[local_tcp\]\n}, %r{host = 10.0.0.3\n}, %r{user = other2\n}, %r{port = 3307\n}] + regex_match.each do |reg| + expect(r.stdout).to match(reg) + end expect(r.stderr).to be_empty end end + it 'finds the login path password #stdout' do run_shell('MYSQL_TEST_LOGIN_FILE=/home/loginpath_test/.mylogin.cnf my_print_defaults -s local_tcp') do |r| expect(r.stdout).to match(%r{--password=password\n}) @@ -254,6 +265,7 @@ it 'works without errors' do apply_manifest(pp, catch_failures: true) end + it 'finds the login path #stdout' do run_shell('MYSQL_TEST_LOGIN_FILE=/home/loginpath_test/.mylogin.cnf mysql_config_editor print --all') do |r| expect(r.stdout).not_to match(%r{^\[local_tcp\]\n}) diff --git a/spec/acceptance/types/mysql_plugin_spec.rb b/spec/acceptance/types/mysql_plugin_spec.rb index 7780241d9..1cf074a89 100644 --- a/spec/acceptance/types/mysql_plugin_spec.rb +++ b/spec/acceptance/types/mysql_plugin_spec.rb @@ -6,17 +6,19 @@ # of mysql) have varying levels of support for plugins and have # different plugins available. Choose a plugin that works or don't try # to test plugins if not available. -if os[:family] == 'redhat' - if os[:release].to_i == 5 +case os[:family] +when 'redhat' + case os[:release].to_i + when 5 plugin = nil # Plugins not supported on mysql on RHEL 5 - elsif os[:release].to_i == 6 + when 6 plugin = 'example' plugin_lib = 'ha_example.so' - elsif os[:release].to_i == 7 + when 7 plugin = 'pam' plugin_lib = 'auth_pam.so' end -elsif os[:family] == 'debian' +when 'debian' if os[:family] == 'ubuntu' if %r{^16\.04|^18\.04}.match?(os[:release]) # On Xenial running 5.7.12, the example plugin does not appear to be available. @@ -27,7 +29,7 @@ plugin_lib = 'ha_example.so' end end -elsif os[:family] == 'suse' +when 'suse' plugin = nil # Plugin library path is broken on Suse http://lists.opensuse.org/opensuse-bugs/2013-08/msg01123.html end diff --git a/spec/acceptance/types/mysql_user_spec.rb b/spec/acceptance/types/mysql_user_spec.rb index 5b54b6a42..2d7412175 100644 --- a/spec/acceptance/types/mysql_user_spec.rb +++ b/spec/acceptance/types/mysql_user_spec.rb @@ -47,11 +47,11 @@ class { 'mysql::server': * => $ed25519_opts } describe 'changing authentication plugin', if: (Gem::Version.new(mysql_version) > Gem::Version.new('5.5.0') && os[:release] !~ %r{^16\.04}) do it 'works without errors', if: (os[:family] != 'sles' && os[:release].to_i == 15) do - pp = <<-EOS + pp = <<-MANIFEST mysql_user { 'ashp@localhost': plugin => 'auth_socket', } - EOS + MANIFEST idempotent_apply(pp) end @@ -78,12 +78,12 @@ class { 'mysql::server': * => $ed25519_opts } describe 'using ed25519 authentication plugin', if: Gem::Version.new(mysql_version) > Gem::Version.new('10.1.21') do it 'works without errors' do - pp = <<-EOS + pp = <<-MANIFEST mysql_user { 'ashp@localhost': plugin => 'ed25519', password_hash => 'z0pjExBYbzbupUByZRrQvC6kRCcE8n/tC7kUdUD11fU', } - EOS + MANIFEST idempotent_apply(pp) end @@ -95,7 +95,6 @@ class { 'mysql::server': * => $ed25519_opts } end end end - # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations end context 'using ashp-dash@localhost' do @@ -137,6 +136,7 @@ class { 'mysql::server': * => $ed25519_opts } end end end + context 'using resource should throw no errors' do describe 'find users' do it do @@ -146,6 +146,7 @@ class { 'mysql::server': * => $ed25519_opts } end end end + context 'using user-w-ssl@localhost with SSL' do describe 'adding user' do pp_five = <<-MANIFEST @@ -173,6 +174,7 @@ class { 'mysql::server': * => $ed25519_opts } end end end + context 'using user-w-x509@localhost with X509' do describe 'adding user' do pp_six = <<-MANIFEST @@ -200,6 +202,7 @@ class { 'mysql::server': * => $ed25519_opts } end end end + context 'using user-w-subject@localhost with ISSUER and SUBJECT' do describe 'adding user' do it 'works without errors' do diff --git a/spec/classes/graceful_failures_spec.rb b/spec/classes/graceful_failures_spec.rb index 4b68868d4..bba9d4ad1 100644 --- a/spec/classes/graceful_failures_spec.rb +++ b/spec/classes/graceful_failures_spec.rb @@ -7,12 +7,12 @@ let(:facts) do { os: { family: 'UNSUPPORTED', - name: 'UNSUPPORTED' }, + name: 'UNSUPPORTED' } } end it 'gracefully fails' do - is_expected.to compile.and_raise_error(%r{Unsupported platform:}) + expect(subject).to compile.and_raise_error(%r{Unsupported platform:}) end end end diff --git a/spec/classes/mycnf_template_spec.rb b/spec/classes/mycnf_template_spec.rb index 277711067..8be85579f 100644 --- a/spec/classes/mycnf_template_spec.rb +++ b/spec/classes/mycnf_template_spec.rb @@ -13,8 +13,8 @@ let(:params) { { override_options: { 'mysqld' => { 'socket' => '/var/lib/mysql/mysql.sock' } } } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0644', - selinux_ignore_defaults: true).with_content(%r{socket = \/var\/lib\/mysql\/mysql.sock}) + expect(subject).to contain_file('mysql-config-file').with(mode: '0644', + selinux_ignore_defaults: true).with_content(%r{socket = /var/lib/mysql/mysql.sock}) end end @@ -22,7 +22,7 @@ let(:params) { { override_options: { 'mysqld' => { 'replicate-do-db' => ['base1', 'base2'] } } } } it do - is_expected.to contain_file('mysql-config-file').with_content( + expect(subject).to contain_file('mysql-config-file').with_content( %r{.*replicate-do-db = base1\nreplicate-do-db = base2.*}, ) end @@ -80,8 +80,8 @@ let(:params) { { includedir: '/etc/my.cnf.d' } } it 'makes the directory' do - is_expected.to contain_file('/etc/my.cnf.d').with(ensure: :directory, - mode: '0755') + expect(subject).to contain_file('/etc/my.cnf.d').with(ensure: :directory, + mode: '0755') end it { is_expected.to contain_file('mysql-config-file').with_content(%r{!includedir}) } @@ -91,8 +91,8 @@ let(:params) { { includedir: '' } } it 'shouldnt contain the directory' do - is_expected.not_to contain_file('mysql-config-file').with(ensure: :directory, - mode: '0755') + expect(subject).not_to contain_file('mysql-config-file').with(ensure: :directory, + mode: '0755') end it { is_expected.to contain_file('mysql-config-file').without_content(%r{!includedir}) } @@ -102,7 +102,7 @@ let(:params) { { 'config_file_mode' => '0644' } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0644') + expect(subject).to contain_file('mysql-config-file').with(mode: '0644') end end @@ -110,7 +110,7 @@ let(:params) { { 'config_file_mode' => '0664' } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0664') + expect(subject).to contain_file('mysql-config-file').with(mode: '0664') end end @@ -118,7 +118,7 @@ let(:params) { { 'config_file_mode' => '0660' } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0660') + expect(subject).to contain_file('mysql-config-file').with(mode: '0660') end end @@ -126,7 +126,7 @@ let(:params) { { 'config_file_mode' => '0641' } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0641') + expect(subject).to contain_file('mysql-config-file').with(mode: '0641') end end @@ -134,7 +134,7 @@ let(:params) { { 'config_file_mode' => '0610' } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0610') + expect(subject).to contain_file('mysql-config-file').with(mode: '0610') end end @@ -142,7 +142,7 @@ let(:params) { { 'config_file_mode' => '0600' } } it do - is_expected.to contain_file('mysql-config-file').with(mode: '0600') + expect(subject).to contain_file('mysql-config-file').with(mode: '0600') end end @@ -150,7 +150,7 @@ let(:params) { { 'mycnf_owner' => '12345' } } it do - is_expected.to contain_file('mysql-config-file').with( + expect(subject).to contain_file('mysql-config-file').with( owner: '12345', ) end @@ -160,7 +160,7 @@ let(:params) { { 'mycnf_group' => '12345' } } it do - is_expected.to contain_file('mysql-config-file').with( + expect(subject).to contain_file('mysql-config-file').with( group: '12345', ) end @@ -170,7 +170,7 @@ let(:params) { { 'mycnf_owner' => '12345', 'mycnf_group' => '12345' } } it do - is_expected.to contain_file('mysql-config-file').with( + expect(subject).to contain_file('mysql-config-file').with( owner: '12345', group: '12345', ) diff --git a/spec/classes/mysql_backup_mysqldump_spec.rb b/spec/classes/mysql_backup_mysqldump_spec.rb index 6fa75697d..6389e580a 100644 --- a/spec/classes/mysql_backup_mysqldump_spec.rb +++ b/spec/classes/mysql_backup_mysqldump_spec.rb @@ -6,22 +6,22 @@ on_supported_os.each do |os, facts| context "on #{os}" do let(:pre_condition) do - <<-EOF + <<-MANIFEST class { 'mysql::server': } - EOF + MANIFEST end let(:facts) do facts.merge(root_home: '/root') end let(:default_params) do - { 'backupuser' => 'testuser', - 'backuppassword' => 'testpass', - 'backupdir' => '/tmp/mysql-backup', - 'backuprotate' => '25', + { 'backupuser' => 'testuser', + 'backuppassword' => 'testpass', + 'backupdir' => '/tmp/mysql-backup', + 'backuprotate' => '25', 'delete_before_dump' => true, - 'execpath' => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin', - 'maxallowedpacket' => '1M' } + 'execpath' => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin', + 'maxallowedpacket' => '1M' } end context 'with time included' do @@ -30,7 +30,7 @@ class { 'mysql::server': } end it { - is_expected.to contain_cron('mysql-backup').with( + expect(subject).to contain_cron('mysql-backup').with( hour: 23, minute: 59, monthday: 30, @@ -44,7 +44,7 @@ class { 'mysql::server': } let(:params) { default_params } it { - is_expected.to contain_cron('mysql-backup').with( + expect(subject).to contain_cron('mysql-backup').with( command: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', hour: 23, @@ -62,13 +62,13 @@ class { 'mysql::server': } end it { - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{(\| TEST -TEST)}, ) - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{(\.TEST)}, ) - is_expected.not_to contain_package('bzip2') + expect(subject).not_to contain_package('bzip2') } end @@ -76,17 +76,16 @@ class { 'mysql::server': } let(:params) do { 'file_per_database' => true, - 'excludedatabases' => [ 'information_schema' ], + 'excludedatabases' => ['information_schema'] }.merge(default_params) end it { - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{information_schema}, ) } end end end - # rubocop:enable RSpec/NestedGroups end diff --git a/spec/classes/mysql_backup_xtrabackup_spec.rb b/spec/classes/mysql_backup_xtrabackup_spec.rb index 70ac710cf..7463d5c56 100644 --- a/spec/classes/mysql_backup_xtrabackup_spec.rb +++ b/spec/classes/mysql_backup_xtrabackup_spec.rb @@ -6,9 +6,9 @@ on_supported_os.each do |os, facts| context "on #{os}" do let(:pre_condition) do - <<-EOF + <<-MANIFEST class { 'mysql::server': } - EOF + MANIFEST end let(:facts) do facts.merge(root_home: '/root', @@ -26,13 +26,13 @@ class { 'mysql::server': } end it 'does not contain the touch command' do - is_expected.to contain_file('xtrabackup.sh').without_content( + expect(subject).to contain_file('xtrabackup.sh').without_content( %r{(^\s+touch\s+$)}, ) end it 'contains the wrapper script' do - is_expected.to contain_file('xtrabackup.sh').with_content( + expect(subject).to contain_file('xtrabackup.sh').with_content( %r{(\n*^xtrabackup\s+.*\$@)}, ) end @@ -48,9 +48,8 @@ class { 'mysql::server': } elsif facts[:os]['name'] == 'Debian' 'percona-xtrabackup-24' elsif facts[:os]['name'] == 'Ubuntu' - if Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '20') >= 0 - 'percona-xtrabackup-24' - elsif Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '16') >= 0 + if Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '20') < 0 && + Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '16') >= 0 'percona-xtrabackup' else 'percona-xtrabackup-24' @@ -62,7 +61,7 @@ class { 'mysql::server': } end it 'contains the weekly cronjob' do - is_expected.to contain_cron('xtrabackup-weekly') + expect(subject).to contain_cron('xtrabackup-weekly') .with( ensure: 'present', command: '/usr/local/sbin/xtrabackup.sh --target-dir=/tmp/$(date +\%F)_full --backup', @@ -81,10 +80,10 @@ class { 'mysql::server': } else '$(date -d "last sunday" +\%F)_full' end - is_expected.to contain_cron('xtrabackup-daily') + expect(subject).to contain_cron('xtrabackup-daily') .with( ensure: 'present', - command: "/usr/local/sbin/xtrabackup.sh --incremental-basedir=/tmp/#{dateformat} --target-dir=/tmp/$(date +\\\%F_\\\%H-\\\%M-\\\%S) --backup", + command: "/usr/local/sbin/xtrabackup.sh --incremental-basedir=/tmp/#{dateformat} --target-dir=/tmp/$(date +\\%F_\\%H-\\%M-\\%S) --backup", user: 'root', hour: '23', minute: '5', @@ -101,14 +100,14 @@ class { 'mysql::server': } end it 'contains the defined mysql user' do - is_expected.to contain_mysql_user('backupuser@localhost') + expect(subject).to contain_mysql_user('backupuser@localhost') .with( ensure: 'present', password_hash: '*4110E08DF51E70A4BA1D4E33A84205E38CF3FE58', ) .that_requires('Class[mysql::server::root_password]') - is_expected.to contain_mysql_grant('backupuser@localhost/*.*') + expect(subject).to contain_mysql_grant('backupuser@localhost/*.*') .with( ensure: 'present', user: 'backupuser@localhost', @@ -130,9 +129,9 @@ class { 'mysql::server': } end it { - is_expected.not_to contain_mysql_grant('backupuser@localhost/performance_schema.keyring_component_status') - is_expected.not_to contain_mysql_grant('backupuser@localhost/performance_schema.log_status') - is_expected.not_to contain_mysql_grant('backupuser@localhost/*.*') + expect(subject).not_to contain_mysql_grant('backupuser@localhost/performance_schema.keyring_component_status') + expect(subject).not_to contain_mysql_grant('backupuser@localhost/performance_schema.log_status') + expect(subject).not_to contain_mysql_grant('backupuser@localhost/*.*') .with( ensure: 'present', user: 'backupuser@localhost', @@ -151,7 +150,7 @@ class { 'mysql::server': } end it { - is_expected.to contain_mysql_grant('backupuser@localhost/*.*') + expect(subject).to contain_mysql_grant('backupuser@localhost/*.*') .with( ensure: 'present', user: 'backupuser@localhost', @@ -165,7 +164,7 @@ class { 'mysql::server': } end, ) .that_requires('Mysql_user[backupuser@localhost]') - is_expected.to contain_mysql_grant('backupuser@localhost/performance_schema.keyring_component_status') + expect(subject).to contain_mysql_grant('backupuser@localhost/performance_schema.keyring_component_status') .with( ensure: 'present', user: 'backupuser@localhost', @@ -175,7 +174,7 @@ class { 'mysql::server': } ) .that_requires('Mysql_user[backupuser@localhost]') - is_expected.to contain_mysql_grant('backupuser@localhost/performance_schema.log_status') + expect(subject).to contain_mysql_grant('backupuser@localhost/performance_schema.log_status') .with( ensure: 'present', user: 'backupuser@localhost', @@ -204,9 +203,8 @@ class { 'mysql::server': } elsif facts[:os]['name'] == 'Debian' 'percona-xtrabackup-24' elsif facts[:os]['name'] == 'Ubuntu' - if Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '20') >= 0 - 'percona-xtrabackup-24' - elsif Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '16') >= 0 + if Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '20') < 0 && + Puppet::Util::Package.versioncmp(facts[:os]['release']['major'], '16') >= 0 'percona-xtrabackup' else 'percona-xtrabackup-24' @@ -225,7 +223,7 @@ class { 'mysql::server': } end it 'contains the weekly cronjob' do - is_expected.to contain_cron('xtrabackup-weekly') + expect(subject).to contain_cron('xtrabackup-weekly') .with( ensure: 'present', command: '/usr/local/sbin/xtrabackup.sh --target-dir=/tmp/$(date +\%F)_full --backup --skip-ssl', @@ -238,10 +236,10 @@ class { 'mysql::server': } end it 'contains the daily cronjob for weekdays 1-6' do - is_expected.to contain_cron('xtrabackup-daily') + expect(subject).to contain_cron('xtrabackup-daily') .with( ensure: 'present', - command: "/usr/local/sbin/xtrabackup.sh --incremental-basedir=/tmp/#{dateformat} --target-dir=/tmp/$(date +\\\%F_\\\%H-\\\%M-\\\%S) --backup --skip-ssl", + command: "/usr/local/sbin/xtrabackup.sh --incremental-basedir=/tmp/#{dateformat} --target-dir=/tmp/$(date +\\%F_\\%H-\\%M-\\%S) --backup --skip-ssl", user: 'root', hour: '23', minute: '5', @@ -257,11 +255,11 @@ class { 'mysql::server': } end it 'not contains the weekly cronjob' do - is_expected.not_to contain_cron('xtrabackup-weekly') + expect(subject).not_to contain_cron('xtrabackup-weekly') end it 'contains the daily cronjob with all weekdays' do - is_expected.to contain_cron('xtrabackup-daily').with( + expect(subject).to contain_cron('xtrabackup-daily').with( ensure: 'present', command: '/usr/local/sbin/xtrabackup.sh --target-dir=/tmp/$(date +\%F_\%H-\%M-\%S) --backup', user: 'root', @@ -279,8 +277,8 @@ class { 'mysql::server': } end it 'contains the prescript' do - is_expected.to contain_file('xtrabackup.sh').with_content( - %r{.*rsync -a \/tmp backup01.local-lan:\n\nrsync -a \/tmp backup02.local-lan:.*}, + expect(subject).to contain_file('xtrabackup.sh').with_content( + %r{.*rsync -a /tmp backup01.local-lan:\n\nrsync -a /tmp backup02.local-lan:.*}, ) end end @@ -292,8 +290,8 @@ class { 'mysql::server': } end it 'contains the prostscript' do - is_expected.to contain_file('xtrabackup.sh').with_content( - %r{.*rsync -a \/tmp backup01.local-lan:\n\nrsync -a \/tmp backup02.local-lan:.*}, + expect(subject).to contain_file('xtrabackup.sh').with_content( + %r{.*rsync -a /tmp backup01.local-lan:\n\nrsync -a /tmp backup02.local-lan:.*}, ) end end @@ -305,7 +303,7 @@ class { 'mysql::server': } end it 'contain the mariabackup executor' do - is_expected.to contain_file('xtrabackup.sh').with_content( + expect(subject).to contain_file('xtrabackup.sh').with_content( %r{(\n*^mariabackup\s+.*\$@)}, ) end @@ -317,12 +315,11 @@ class { 'mysql::server': } end it 'contain the touch /tmp/backup_success command' do - is_expected.to contain_file('xtrabackup.sh').with_content( + expect(subject).to contain_file('xtrabackup.sh').with_content( %r{(^\s+touch /tmp/backup_success$)}, ) end end end end - # rubocop:enable RSpec/NestedGroups end diff --git a/spec/classes/mysql_bindings_spec.rb b/spec/classes/mysql_bindings_spec.rb index 4b76554cd..bce58cc97 100644 --- a/spec/classes/mysql_bindings_spec.rb +++ b/spec/classes/mysql_bindings_spec.rb @@ -5,6 +5,7 @@ describe 'mysql::bindings' do on_supported_os.each do |os, facts| next if facts[:os]['family'] == 'Archlinux' + context "on #{os}" do let(:facts) do facts.merge(root_home: '/root') @@ -13,14 +14,14 @@ let(:params) do { 'java_enable' => true, - 'perl_enable' => true, - 'php_enable' => true, - 'python_enable' => true, - 'ruby_enable' => true, - 'client_dev' => true, - 'daemon_dev' => true, + 'perl_enable' => true, + 'php_enable' => true, + 'python_enable' => true, + 'ruby_enable' => true, + 'client_dev' => true, + 'daemon_dev' => true, 'client_dev_package_name' => 'libmysqlclient-devel', - 'daemon_dev_package_name' => 'mysql-devel', + 'daemon_dev_package_name' => 'mysql-devel' } end diff --git a/spec/classes/mysql_client_spec.rb b/spec/classes/mysql_client_spec.rb index 18c145058..839d30bb5 100644 --- a/spec/classes/mysql_client_spec.rb +++ b/spec/classes/mysql_client_spec.rb @@ -37,12 +37,12 @@ let(:params) do { package_provider: 'dpkg', - package_source: '/somewhere', + package_source: '/somewhere' } end it do - is_expected.to contain_package('mysql_client').with( + expect(subject).to contain_package('mysql_client').with( provider: 'dpkg', source: '/somewhere', ) diff --git a/spec/classes/mysql_server_account_security_spec.rb b/spec/classes/mysql_server_account_security_spec.rb index dc137d537..238124f8d 100644 --- a/spec/classes/mysql_server_account_security_spec.rb +++ b/spec/classes/mysql_server_account_security_spec.rb @@ -6,9 +6,9 @@ on_supported_os.each do |os, facts| context "on #{os}" do let(:pre_condition) do - <<-EOF + <<-MANIFEST anchor {'mysql::server::end': } - EOF + MANIFEST end context 'with fqdn==myhost.mydomain' do @@ -27,7 +27,7 @@ '@localhost', '@%'].each do |user| it "removes Mysql_User[#{user}]" do # rubocop:disable RSpec/RepeatedExample,RSpec/RepeatedDescription - is_expected.to contain_mysql_user(user).with_ensure('absent') + expect(subject).to contain_mysql_user(user).with_ensure('absent') end end @@ -36,12 +36,12 @@ # covered by the above list. ['root@myhost', '@myhost'].each do |user| it "removes Mysql_User[#{user}]" do # rubocop:disable RSpec/RepeatedExample,RSpec/RepeatedDescription - is_expected.to contain_mysql_user(user).with_ensure('absent') + expect(subject).to contain_mysql_user(user).with_ensure('absent') end end it 'removes Mysql_database[test]' do - is_expected.to contain_mysql_database('test').with_ensure('absent') + expect(subject).to contain_mysql_database('test').with_ensure('absent') end end @@ -61,7 +61,7 @@ '@localhost.localdomain', '@%'].each do |user| it "removes Mysql_User[#{user}] for fqdn==localhost" do - is_expected.to contain_mysql_user(user).with_ensure('absent') + expect(subject).to contain_mysql_user(user).with_ensure('absent') end end end @@ -82,7 +82,7 @@ '@localhost.localdomain', '@%'].each do |user| it "removes Mysql_User[#{user}] for fqdn==localhost.localdomain" do - is_expected.to contain_mysql_user(user).with_ensure('absent') + expect(subject).to contain_mysql_user(user).with_ensure('absent') end end end diff --git a/spec/classes/mysql_server_backup_spec.rb b/spec/classes/mysql_server_backup_spec.rb index 217f1bc02..b1af7b1f1 100644 --- a/spec/classes/mysql_server_backup_spec.rb +++ b/spec/classes/mysql_server_backup_spec.rb @@ -6,22 +6,22 @@ on_supported_os.each do |os, facts| context "on #{os}" do let(:pre_condition) do - <<-EOF + <<-MANIFEST class { 'mysql::server': } - EOF + MANIFEST end let(:facts) do facts.merge(root_home: '/root') end let(:default_params) do - { 'backupuser' => 'testuser', - 'backuppassword' => 'testpass', - 'backupdir' => '/tmp/mysql-backup', - 'backuprotate' => '25', + { 'backupuser' => 'testuser', + 'backuppassword' => 'testpass', + 'backupdir' => '/tmp/mysql-backup', + 'backuprotate' => '25', 'delete_before_dump' => true, - 'execpath' => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin', - 'maxallowedpacket' => '1M' } + 'execpath' => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin', + 'maxallowedpacket' => '1M' } end context 'standard conditions' do @@ -29,13 +29,13 @@ class { 'mysql::server': } # Cannot use that_requires here, doesn't work on classes. it { - is_expected.to contain_mysql_user('testuser@localhost').with( + expect(subject).to contain_mysql_user('testuser@localhost').with( require: 'Class[Mysql::Server::Root_password]', ) } it { - is_expected.to contain_mysql_grant('testuser@localhost/*.*').with( + expect(subject).to contain_mysql_grant('testuser@localhost/*.*').with( privileges: ['SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS'], ).that_requires('Mysql_user[testuser@localhost]') } @@ -46,70 +46,70 @@ class { 'mysql::server': } end it { - is_expected.to contain_mysql_grant('testuser@localhost/*.*').with( + expect(subject).to contain_mysql_grant('testuser@localhost/*.*').with( privileges: ['SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS', 'TRIGGER'], ).that_requires('Mysql_user[testuser@localhost]') } end it { - is_expected.to contain_cron('mysql-backup').with( + expect(subject).to contain_cron('mysql-backup').with( command: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', ) } it { - is_expected.to contain_file('mysqlbackup.sh').with( + expect(subject).to contain_file('mysqlbackup.sh').with( path: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', ) } it { - is_expected.to contain_file('/tmp/mysql-backup').with( + expect(subject).to contain_file('/tmp/mysql-backup').with( ensure: 'directory', ) } it 'has compression by default' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{bzcat -zc}, ) end it 'skips backing up events table by default' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="--ignore-table=mysql.event"}, ) end it 'does not mention triggers by default because file_per_database is false' do - is_expected.to contain_file('mysqlbackup.sh').without_content( + expect(subject).to contain_file('mysqlbackup.sh').without_content( %r{.*triggers.*}, ) end it 'does not mention routines by default because file_per_database is false' do - is_expected.to contain_file('mysqlbackup.sh').without_content( + expect(subject).to contain_file('mysqlbackup.sh').without_content( %r{.*routines.*}, ) end it 'has 25 days of rotation' do # MySQL counts from 0 - is_expected.to contain_file('mysqlbackup.sh').with_content(%r{.*ROTATE=24.*}) + expect(subject).to contain_file('mysqlbackup.sh').with_content(%r{.*ROTATE=24.*}) end it 'has a standard PATH' do - is_expected.to contain_file('mysqlbackup.sh').with_content(%r{PATH=/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin}) + expect(subject).to contain_file('mysqlbackup.sh').with_content(%r{PATH=/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin}) end end context 'with delete after dump' do let(:custom_params) do { - 'delete_before_dump' => false, + 'delete_before_dump' => false } end let(:params) do @@ -122,8 +122,8 @@ class { 'mysql::server': } context 'with delete after dump and custom success file path' do let(:custom_params) do { - 'delete_before_dump' => false, - 'backup_success_file_path' => '/opt/mysqlbackup_success', + 'delete_before_dump' => false, + 'backup_success_file_path' => '/opt/mysqlbackup_success' } end let(:params) do @@ -141,7 +141,7 @@ class { 'mysql::server': } end it { - is_expected.to contain_file('/tmp/mysql-backup').with( + expect(subject).to contain_file('/tmp/mysql-backup').with( ensure: 'directory', mode: '0750', owner: 'testuser', @@ -156,14 +156,14 @@ class { 'mysql::server': } end it { - is_expected.to contain_file('mysqlbackup.sh').with( + expect(subject).to contain_file('mysqlbackup.sh').with( path: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', ) } it 'is able to disable compression' do - is_expected.to contain_file('mysqlbackup.sh').without_content( + expect(subject).to contain_file('mysqlbackup.sh').without_content( %r{.*bzcat -zc.*}, ) end @@ -175,14 +175,14 @@ class { 'mysql::server': } end it { - is_expected.to contain_file('mysqlbackup.sh').with( + expect(subject).to contain_file('mysqlbackup.sh').with( path: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', ) } it 'is able to backup events table' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="--events"}, ) end @@ -194,26 +194,26 @@ class { 'mysql::server': } end it { - is_expected.to contain_file('mysqlbackup.sh').with( + expect(subject).to contain_file('mysqlbackup.sh').with( path: '/usr/local/sbin/mysqlbackup.sh', ensure: 'present', ) } it 'has a backup file for each database' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{mysql | bzcat -zc \${DIR}\\\${PREFIX}mysql_`date'}, ) end it 'skips backup triggers by default' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"}, ) end it 'skips backing up routines by default' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"}, ) end @@ -225,7 +225,7 @@ class { 'mysql::server': } end it 'backups triggers when asked' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --triggers"}, ) end @@ -238,7 +238,7 @@ class { 'mysql::server': } end it 'skips backing up triggers when asked to skip' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"}, ) end @@ -251,7 +251,7 @@ class { 'mysql::server': } end it 'backups routines when asked' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --routines"}, ) end @@ -264,7 +264,7 @@ class { 'mysql::server': } end it 'skips backing up routines when asked to skip' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"}, ) end @@ -277,7 +277,7 @@ class { 'mysql::server': } end it 'loops through backup all databases' do - is_expected.to contain_file('mysqlbackup.sh').with_content(%r{.*SHOW DATABASES.*}) + expect(subject).to contain_file('mysqlbackup.sh').with_content(%r{.*SHOW DATABASES.*}) end context 'with compression disabled' do @@ -286,21 +286,22 @@ class { 'mysql::server': } end it 'loops through backup all databases without compression #show databases' do - is_expected.to contain_file('mysqlbackup.sh').with_content(%r{.*SHOW DATABASES.*}) + expect(subject).to contain_file('mysqlbackup.sh').with_content(%r{.*SHOW DATABASES.*}) end + it 'loops through backup all databases without compression #bzcat' do - is_expected.to contain_file('mysqlbackup.sh').without_content(%r{.*bzcat -zc.*}) + expect(subject).to contain_file('mysqlbackup.sh').without_content(%r{.*bzcat -zc.*}) end end it 'skips backup triggers by default' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"}, ) end it 'skips backing up routines by default' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"}, ) end @@ -312,7 +313,7 @@ class { 'mysql::server': } end it 'backups triggers when asked' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --triggers"}, ) end @@ -325,7 +326,7 @@ class { 'mysql::server': } end it 'skips backing up triggers when asked to skip' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"}, ) end @@ -338,7 +339,7 @@ class { 'mysql::server': } end it 'backups routines when asked' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --routines"}, ) end @@ -351,7 +352,7 @@ class { 'mysql::server': } end it 'skips backing up routines when asked to skip' do - is_expected.to contain_file('mysqlbackup.sh').with_content( + expect(subject).to contain_file('mysqlbackup.sh').with_content( %r{ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"}, ) end @@ -364,8 +365,8 @@ class { 'mysql::server': } end it 'is add postscript' do - is_expected.to contain_file('mysqlbackup.sh').with_content( - %r{rsync -a \/tmp backup01.local-lan:}, + expect(subject).to contain_file('mysqlbackup.sh').with_content( + %r{rsync -a /tmp backup01.local-lan:}, ) end end @@ -379,12 +380,11 @@ class { 'mysql::server': } end it 'is add postscript' do - is_expected.to contain_file('mysqlbackup.sh').with_content( - %r{.*rsync -a \/tmp backup01.local-lan:\n\nrsync -a \/tmp backup02.local-lan:.*}, + expect(subject).to contain_file('mysqlbackup.sh').with_content( + %r{.*rsync -a /tmp backup01.local-lan:\n\nrsync -a /tmp backup02.local-lan:.*}, ) end end end end - # rubocop:enable RSpec/NestedGroups end diff --git a/spec/classes/mysql_server_spec.rb b/spec/classes/mysql_server_spec.rb index 6d7c93985..3ff307b71 100644 --- a/spec/classes/mysql_server_spec.rb +++ b/spec/classes/mysql_server_spec.rb @@ -43,7 +43,7 @@ let(:params) do { override_options: { 'mysqld' => { 'datadir' => '/tmp' } }, - options: { 'mysqld' => { 'max_allowed_packet' => '12M' } }, + options: { 'mysqld' => { 'max_allowed_packet' => '12M' } } } end @@ -53,7 +53,7 @@ context 'when specifying $options' do let(:params) do { - options: { 'mysqld' => { 'datadir' => '/tmp' } }, + options: { 'mysqld' => { 'datadir' => '/tmp' } } } end @@ -65,33 +65,37 @@ context 'mysql::server::install' do it 'contains the package by default' do - is_expected.to contain_package('mysql-server').with(ensure: :present) + expect(subject).to contain_package('mysql-server').with(ensure: :present) end + context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_package('mysql-server') } end + context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.not_to contain_package('mysql-server') } end + context 'with datadir overridden' do let(:params) { { override_options: { 'mysqld' => { 'datadir' => '/tmp' } } } } it { is_expected.to contain_mysql_datadir('/tmp') } end + context 'with package provider' do let(:params) do { package_provider: 'dpkg', - package_source: '/somewhere', + package_source: '/somewhere' } end it do - is_expected.to contain_package('mysql-server').with( + expect(subject).to contain_package('mysql-server').with( provider: 'dpkg', source: '/somewhere', ) @@ -103,57 +107,68 @@ context 'with defaults' do it { is_expected.to contain_service('mysqld') } end + context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_service('mysqld').that_requires('Package[mysql-server]') } end + context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.to contain_service('mysqld') } it { is_expected.not_to contain_service('mysqld').that_requires('Package[mysql-server]') } end + context 'service_enabled set to false' do let(:params) { { service_enabled: false } } it do - is_expected.to contain_service('mysqld').with(ensure: :stopped) + expect(subject).to contain_service('mysqld').with(ensure: :stopped) end + context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_package('mysql-server') } end + context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.not_to contain_package('mysql-server') } end + context 'with datadir overridden' do let(:params) { { override_options: { 'mysqld' => { 'datadir' => '/tmp' } } } } it { is_expected.to contain_mysql_datadir('/tmp') } end end + context 'with log-error overridden' do let(:params) { { override_options: { 'mysqld' => { 'log-error' => '/tmp/error.log' } } } } it { is_expected.to contain_file('/tmp/error.log') } end + context 'default bind-address' do it { is_expected.to contain_file('mysql-config-file').with_content(%r{^bind-address = 127.0.0.1}) } end + context 'with defined bind-address' do let(:params) { { override_options: { 'mysqld' => { 'bind-address' => '1.1.1.1' } } } } it { is_expected.to contain_file('mysql-config-file').with_content(%r{^bind-address = 1.1.1.1}) } end + context 'without bind-address' do let(:params) { { override_options: { 'mysqld' => { 'bind-address' => :undef } } } } it { is_expected.to contain_file('mysql-config-file').without_content(%r{^bind-address}) } end + context 'with reload_on_config_change' do let(:params) { { 'reload_on_config_change' => true } } @@ -164,41 +179,48 @@ context 'mysql::server::root_password' do describe 'when defaults' do it { - is_expected.to contain_exec('remove install pass').with( - command: "mysqladmin -u root --password=\$(grep -o '[^ ]\\+\$' /.mysql_secret) password && (rm -f /.mysql_secret; exit 0) || (rm -f /.mysql_secret; exit 1)", + expect(subject).to contain_exec('remove install pass').with( + command: "mysqladmin -u root --password=$(grep -o '[^ ]\\+$' /.mysql_secret) password && (rm -f /.mysql_secret; exit 0) || (rm -f /.mysql_secret; exit 1)", onlyif: [['test', '-f', '/.mysql_secret']], path: '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin', ) } + it { is_expected.not_to contain_mysql_user('root@localhost') } it { is_expected.not_to contain_file('/root/.my.cnf') } end + describe 'when root_password set' do let(:params) { { root_password: 'SET' } } it { is_expected.to contain_mysql_user('root@localhost') } + if Puppet.version.to_f >= 3.0 it { is_expected.to contain_file('/root/.my.cnf').with(show_diff: false).that_requires('Mysql_user[root@localhost]') } else it { is_expected.to contain_file('/root/.my.cnf').that_requires('Mysql_user[root@localhost]') } end end + describe 'when root_password set, create_root_user set to false' do let(:params) { { root_password: 'SET', create_root_user: false } } it { is_expected.not_to contain_mysql_user('root@localhost') } + if Puppet.version.to_f >= 3.0 it { is_expected.to contain_file('/root/.my.cnf').with(show_diff: false) } else it { is_expected.to contain_file('/root/.my.cnf') } end end + describe 'when root_password set, create_root_my_cnf set to false' do let(:params) { { root_password: 'SET', create_root_my_cnf: false } } it { is_expected.to contain_mysql_user('root@localhost') } it { is_expected.not_to contain_file('/root/.my.cnf') } end + describe 'when root_password set, create_root_user and create_root_my_cnf set to false' do let(:params) { { root_password: 'SET', create_root_user: false, create_root_my_cnf: false } } @@ -213,24 +235,25 @@ { users: { 'foo@localhost' => { 'max_connections_per_hour' => '1', - 'max_queries_per_hour' => '2', - 'max_updates_per_hour' => '3', - 'max_user_connections' => '4', - 'password_hash' => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF', + 'max_queries_per_hour' => '2', + 'max_updates_per_hour' => '3', + 'max_user_connections' => '4', + 'password_hash' => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' }, - 'foo2@localhost' => {}, + 'foo2@localhost' => {} } } end it { - is_expected.to contain_mysql_user('foo@localhost').with( + expect(subject).to contain_mysql_user('foo@localhost').with( max_connections_per_hour: '1', max_queries_per_hour: '2', max_updates_per_hour: '3', max_user_connections: '4', password_hash: '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' ) } + it { - is_expected.to contain_mysql_user('foo2@localhost').with( + expect(subject).to contain_mysql_user('foo2@localhost').with( max_connections_per_hour: nil, max_queries_per_hour: nil, max_updates_per_hour: nil, max_user_connections: nil, password_hash: nil @@ -243,17 +266,17 @@ { users: { 'foo@localhost' => { 'max_connections_per_hour' => '1', - 'max_queries_per_hour' => '2', - 'max_updates_per_hour' => '3', - 'max_user_connections' => '4', - 'password_hash' => sensitive('*F3A2A51A9B0F2BE2468926B4132313728C250DBF'), + 'max_queries_per_hour' => '2', + 'max_updates_per_hour' => '3', + 'max_user_connections' => '4', + 'password_hash' => sensitive('*F3A2A51A9B0F2BE2468926B4132313728C250DBF') }, - 'foo2@localhost' => {}, + 'foo2@localhost' => {} } } end it { - is_expected.to contain_mysql_user('foo@localhost').with( + expect(subject).to contain_mysql_user('foo@localhost').with( max_connections_per_hour: '1', max_queries_per_hour: '2', max_updates_per_hour: '3', max_user_connections: '4', password_hash: 'Sensitive [value redacted]' @@ -265,27 +288,28 @@ let(:params) do { grants: { 'foo@localhost/somedb.*' => { - 'user' => 'foo@localhost', - 'table' => 'somedb.*', + 'user' => 'foo@localhost', + 'table' => 'somedb.*', 'privileges' => ['SELECT', 'UPDATE'], - 'options' => ['GRANT'], + 'options' => ['GRANT'] }, 'foo2@localhost/*.*' => { - 'user' => 'foo2@localhost', - 'table' => '*.*', - 'privileges' => ['SELECT'], - }, + 'user' => 'foo2@localhost', + 'table' => '*.*', + 'privileges' => ['SELECT'] + } } } end it { - is_expected.to contain_mysql_grant('foo@localhost/somedb.*').with( + expect(subject).to contain_mysql_grant('foo@localhost/somedb.*').with( user: 'foo@localhost', table: 'somedb.*', privileges: ['SELECT', 'UPDATE'], options: ['GRANT'] ) } + it { - is_expected.to contain_mysql_grant('foo2@localhost/*.*').with( + expect(subject).to contain_mysql_grant('foo2@localhost/*.*').with( user: 'foo2@localhost', table: '*.*', privileges: ['SELECT'], options: nil ) @@ -297,22 +321,22 @@ { databases: { 'somedb' => { 'charset' => 'latin1', - 'collate' => 'latin1', + 'collate' => 'latin1' }, - 'somedb2' => {}, + 'somedb2' => {} } } end it { - is_expected.to contain_mysql_database('somedb').with( + expect(subject).to contain_mysql_database('somedb').with( charset: 'latin1', collate: 'latin1', ) } + it { is_expected.to contain_mysql_database('somedb2') } end end end end - # rubocop:enable RSpec/NestedGroups end diff --git a/spec/defines/mysql_db_spec.rb b/spec/defines/mysql_db_spec.rb index cd96dcdd0..ce4e524a4 100644 --- a/spec/defines/mysql_db_spec.rb +++ b/spec/defines/mysql_db_spec.rb @@ -12,74 +12,74 @@ let(:title) { 'test_db' } let(:params) do - { 'user' => 'testuser', - 'password' => 'testpass', + { 'user' => 'testuser', + 'password' => 'testpass', 'mysql_exec_path' => '' } end - let(:sql) { [ '/tmp/test.sql' ] } + let(:sql) { ['/tmp/test.sql'] } it 'does not notify the import sql exec if no sql script was provided' do - is_expected.to contain_mysql_database('test_db').without_notify + expect(subject).to contain_mysql_database('test_db').without_notify end it 'subscribes to database if sql script is given' do params['sql'] = sql - is_expected.to contain_mysql_database('test_db') - is_expected.to contain_exec('test_db-import').with_subscribe('Mysql_database[test_db]') + expect(subject).to contain_mysql_database('test_db') + expect(subject).to contain_exec('test_db-import').with_subscribe('Mysql_database[test_db]') end it 'onlies import sql script on creation if not enforcing' do params.merge!('sql' => sql, 'enforce_sql' => false) - is_expected.to contain_exec('test_db-import').with_refreshonly(true) + expect(subject).to contain_exec('test_db-import').with_refreshonly(true) end it 'imports sql script on creation' do params.merge!('sql' => sql, 'enforce_sql' => true) # ' if enforcing #refreshonly' - is_expected.to contain_exec('test_db-import').with_refreshonly(false) + expect(subject).to contain_exec('test_db-import').with_refreshonly(false) # 'if enforcing #command' - is_expected.to contain_exec('test_db-import').with_command('cat /tmp/test.sql | mysql test_db') + expect(subject).to contain_exec('test_db-import').with_command('cat /tmp/test.sql | mysql test_db') end it 'imports sql script with custom command on creation' do params.merge!('sql' => sql, 'enforce_sql' => true, 'import_cat_cmd' => 'zcat') # if enforcing #refreshonly - is_expected.to contain_exec('test_db-import').with_refreshonly(false) + expect(subject).to contain_exec('test_db-import').with_refreshonly(false) # if enforcing #command - is_expected.to contain_exec('test_db-import').with_command('zcat /tmp/test.sql | mysql test_db') + expect(subject).to contain_exec('test_db-import').with_command('zcat /tmp/test.sql | mysql test_db') end it 'imports sql scripts when more than one is specified' do params['sql'] = ['/tmp/test.sql', '/tmp/test_2.sql'] - is_expected.to contain_exec('test_db-import').with_command('cat /tmp/test.sql /tmp/test_2.sql | mysql test_db') + expect(subject).to contain_exec('test_db-import').with_command('cat /tmp/test.sql /tmp/test_2.sql | mysql test_db') end it 'does not create database' do params.merge!('ensure' => 'absent', 'host' => 'localhost') - is_expected.to contain_mysql_database('test_db').with_ensure('absent') - is_expected.to contain_mysql_user('testuser@localhost').with_ensure('absent') + expect(subject).to contain_mysql_database('test_db').with_ensure('absent') + expect(subject).to contain_mysql_user('testuser@localhost').with_ensure('absent') end it 'creates with an appropriate collate and charset' do params.merge!('charset' => 'utf8', 'collate' => 'utf8_danish_ci') - is_expected.to contain_mysql_database('test_db').with('charset' => 'utf8', - 'collate' => 'utf8_danish_ci') + expect(subject).to contain_mysql_database('test_db').with('charset' => 'utf8', + 'collate' => 'utf8_danish_ci') end it 'uses dbname parameter as database name instead of name' do params['dbname'] = 'real_db' - is_expected.to contain_mysql_database('real_db') + expect(subject).to contain_mysql_database('real_db') end it 'uses tls_options for user when set' do params['tls_options'] = ['SSL'] - is_expected.to contain_mysql_user('testuser@localhost').with_tls_options(['SSL']) + expect(subject).to contain_mysql_user('testuser@localhost').with_tls_options(['SSL']) end it 'uses grant_options for grant when set' do params['grant_options'] = ['GRANT'] - is_expected.to contain_mysql_grant('testuser@localhost/test_db.*').with_options(['GRANT']) + expect(subject).to contain_mysql_grant('testuser@localhost/test_db.*').with_options(['GRANT']) end # Invalid file paths @@ -94,7 +94,7 @@ ].each do |path| it "fails when provided '#{path}' as a value to the 'sql' parameter" do params['sql'] = [path] - is_expected.to raise_error(Puppet::PreformattedError, %r{The file '#{Regexp.escape(path)}' is invalid. A valid file path is expected.}) + expect(subject).to raise_error(Puppet::PreformattedError, %r{The file '#{Regexp.escape(path)}' is invalid. A valid file path is expected.}) end end @@ -111,7 +111,7 @@ ].each do |path| it "succeeds when provided '#{path}' as a value to the 'sql' parameter" do params['sql'] = [path] - is_expected.to contain_exec('test_db-import').with_command("cat #{path} | mysql test_db") + expect(subject).to contain_exec('test_db-import').with_command("cat #{path} | mysql test_db") end end @@ -125,7 +125,7 @@ ].each do |name| it "fails when provided '#{name}' as a value to the 'name' parameter" do params['name'] = name - is_expected.to raise_error(Puppet::PreformattedError, %r{The database name '#{name}' is invalid.}) + expect(subject).to raise_error(Puppet::PreformattedError, %r{The database name '#{name}' is invalid.}) end end @@ -138,7 +138,7 @@ ].each do |name| it "succeeds when the provided '#{name}' as a value to the 'dbname' parameter" do params['dbname'] = name - is_expected.to contain_mysql_database(name) + expect(subject).to contain_mysql_database(name) end end end diff --git a/spec/functions/mysql_normalise_and_deepmerge_spec.rb b/spec/functions/mysql_normalise_and_deepmerge_spec.rb index 67cabfac9..c4f9cd651 100644 --- a/spec/functions/mysql_normalise_and_deepmerge_spec.rb +++ b/spec/functions/mysql_normalise_and_deepmerge_spec.rb @@ -4,22 +4,21 @@ describe 'mysql::normalise_and_deepmerge' do it 'exists' do - is_expected.not_to eq(nil) + expect(subject).not_to be_nil end it 'throws error with no arguments' do - is_expected.to run.with_params.and_raise_error(Puppet::ParseError) + expect(subject).to run.with_params.and_raise_error(Puppet::ParseError) end it 'throws error with only one argument' do - is_expected.to run.with_params('one' => 1).and_raise_error(Puppet::ParseError) + expect(subject).to run.with_params('one' => 1).and_raise_error(Puppet::ParseError) end it 'accepts empty strings as puppet undef' do - is_expected.to run.with_params({}, '') + expect(subject).to run.with_params({}, '') end - # rubocop:disable RSpec/NamedSubject index_values = ['one', 'two', 'three'] expected_values_one = ['1', '2', '2'] it 'merge two hashes' do @@ -35,10 +34,10 @@ end it 'accepts empty hashes' do - is_expected.to run.with_params({}, {}, {}).and_return({}) + expect(subject).to run.with_params({}, {}, {}).and_return({}) end - expected_values_two = [1, 2, 'four' => 4] + expected_values_two = [1, 2, { 'four' => 4 }] it 'merges subhashes' do hash = subject.execute({ 'one' => 1 }, 'two' => 2, 'three' => { 'four' => 4 }) index_values.each_with_index do |index, expected| @@ -72,6 +71,7 @@ hash = subject.execute({ 'a-b-c' => 1 }, 'a_b_c' => 10) expect(hash['a_b_c']).to eq(10) end + it 'equates keys mod dash and underscore #not' do hash = subject.execute({ 'a-b-c' => 1 }, 'a_b_c' => 10) expect(hash).not_to have_key('a-b-c') @@ -85,10 +85,10 @@ hash = subject.execute({ 'a-b-c' => 1, 'b_c_d' => { 'c-d-e' => 2, 'e-f-g' => 3 } }, 'a_b_c' => 10, 'b-c-d' => { 'c_d_e' => 12 }) expect(hash[index]).to eq(expected_values_five[expected]) end + it 'keeps style of the last when keys are equal mod dash and underscore #not' do hash = subject.execute({ 'a-b-c' => 1, 'b_c_d' => { 'c-d-e' => 2, 'e-f-g' => 3 } }, 'a_b_c' => 10, 'b-c-d' => { 'c_d_e' => 12 }) expect(hash).not_to have_key(index_values_error[expected]) end end - # rubocop:enable RSpec/NamedSubject end diff --git a/spec/functions/mysql_password_spec.rb b/spec/functions/mysql_password_spec.rb index efbc3d3b9..9ec5bc9f8 100644 --- a/spec/functions/mysql_password_spec.rb +++ b/spec/functions/mysql_password_spec.rb @@ -4,41 +4,41 @@ shared_examples 'mysql::password function' do it 'exists' do - is_expected.not_to eq(nil) + expect(subject).not_to be_nil end it 'raises a ArgumentError if there is less than 1 arguments' do - is_expected.to run.with_params.and_raise_error(ArgumentError) + expect(subject).to run.with_params.and_raise_error(ArgumentError) end it 'raises a ArgumentError if there is more than 2 arguments' do - is_expected.to run.with_params('foo', false, 'bar').and_raise_error(ArgumentError) + expect(subject).to run.with_params('foo', false, 'bar').and_raise_error(ArgumentError) end it 'converts password into a hash' do - is_expected.to run.with_params('password').and_return('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19') + expect(subject).to run.with_params('password').and_return('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19') end it 'accept password as Sensitive' do - is_expected.to run.with_params(sensitive('password')).and_return('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19') + expect(subject).to run.with_params(sensitive('password')).and_return('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19') end # Test of a Returnvalue of Datatype Sensitive does not work it 'returns Sensitive with sensitive=true' do skip 'should have a Returnvalue of Datatype Sensitive' - is_expected.to run.with_params('password', true).and_return(sensitive('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19')) + expect(subject).to run.with_params('password', true).and_return(sensitive('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19')) end it 'password should be String' do - is_expected.to run.with_params(123).and_raise_error(ArgumentError) + expect(subject).to run.with_params(123).and_raise_error(ArgumentError) end it 'converts an empty password into a empty string' do - is_expected.to run.with_params('').and_return('') + expect(subject).to run.with_params('').and_return('') end it 'does not convert a password that is already a hash' do - is_expected.to run.with_params('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19').and_return('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19') + expect(subject).to run.with_params('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19').and_return('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19') end end diff --git a/spec/functions/mysql_strip_hash_spec.rb b/spec/functions/mysql_strip_hash_spec.rb index 1bc60b6e6..2f6778340 100644 --- a/spec/functions/mysql_strip_hash_spec.rb +++ b/spec/functions/mysql_strip_hash_spec.rb @@ -4,26 +4,26 @@ describe 'mysql::strip_hash' do it 'exists' do - is_expected.not_to eq(nil) + expect(subject).not_to be_nil end it 'raises a ArgumentError if there is less than 1 arguments' do - is_expected.to run.with_params.and_raise_error(ArgumentError) + expect(subject).to run.with_params.and_raise_error(ArgumentError) end it 'raises a ArgumentError if there is more than 1 arguments' do - is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(ArgumentError) + expect(subject).to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(ArgumentError) end it 'raises a ArgumentError if argument is not a hash' do - is_expected.to run.with_params('foo').and_raise_error(ArgumentError) + expect(subject).to run.with_params('foo').and_raise_error(ArgumentError) end it 'passes a hash without blanks through' do - is_expected.to run.with_params('one' => 1, 'two' => 2, 'three' => 3).and_return('one' => 1, 'two' => 2, 'three' => 3) + expect(subject).to run.with_params('one' => 1, 'two' => 2, 'three' => 3).and_return('one' => 1, 'two' => 2, 'three' => 3) end it 'removes blank hash elements' do - is_expected.to run.with_params('one' => 1, 'two' => '', 'three' => nil, 'four' => 4).and_return('one' => 1, 'three' => nil, 'four' => 4) + expect(subject).to run.with_params('one' => 1, 'two' => '', 'three' => nil, 'four' => 4).and_return('one' => 1, 'three' => nil, 'four' => 4) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fb5b4d971..f96e1efa5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,7 +13,7 @@ default_facts = { puppetversion: Puppet.version, - facterversion: Facter.version, + facterversion: Facter.version } default_fact_files = [ @@ -26,7 +26,7 @@ begin default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) - rescue => e + rescue StandardError => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end end diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb index 4c9042aa4..1896fc458 100644 --- a/spec/spec_helper_acceptance_local.rb +++ b/spec/spec_helper_acceptance_local.rb @@ -15,8 +15,7 @@ def mysql_version shell_output = LitmusHelper.instance.run_shell('mysql --version') raise _('unable to get mysql version') if shell_output.stdout.match(%r{\d+\.\d+\.\d+}).nil? end - mysql_version = shell_output.stdout.match(%r{\d+\.\d+\.\d+})[0] - mysql_version + shell_output.stdout.match(%r{\d+\.\d+\.\d+})[0] end def supports_xtrabackup? @@ -37,8 +36,8 @@ def sles_15? os[:family] == 'sles' && os[:release].to_i == 15 end -def fetch_charset - @charset ||= ubuntu_2204? || sles_15? ? 'utf8mb3' : 'utf8' +def charset + @charset ||= (ubuntu_2204? || sles_15?) ? 'utf8mb3' : 'utf8' end RSpec.configure do |c| diff --git a/spec/unit/facter/mysql_server_id_spec.rb b/spec/unit/facter/mysql_server_id_spec.rb index ee8b75ce3..fb914a9d4 100644 --- a/spec/unit/facter/mysql_server_id_spec.rb +++ b/spec/unit/facter/mysql_server_id_spec.rb @@ -12,6 +12,7 @@ before :each do allow(Facter.fact(:macaddress)).to receive(:value).and_return('3c:97:0e:69:fb:e1') end + it do Facter.fact(:mysql_server_id).value.to_s.should == '241857808' end @@ -21,6 +22,7 @@ before :each do allow(Facter.fact(:macaddress)).to receive(:value).and_return('00:00:00:00:00:00') end + it do Facter.fact(:mysql_server_id).value.to_s.should == '1' end @@ -30,6 +32,7 @@ before :each do allow(Facter.fact(:macaddress)).to receive(:value).and_return(nil) end + it do Facter.fact(:mysql_server_id).value.to_s.should == '' end diff --git a/spec/unit/facter/mysql_version_spec.rb b/spec/unit/facter/mysql_version_spec.rb index a29783d05..2b6ef7fcd 100644 --- a/spec/unit/facter/mysql_version_spec.rb +++ b/spec/unit/facter/mysql_version_spec.rb @@ -13,6 +13,7 @@ allow(Facter::Core::Execution).to receive(:which).and_return('fake_mysql_path') allow(Facter::Core::Execution).to receive(:execute).with('mysql --version').and_return('mysql Ver 14.12 Distrib 5.0.95, for redhat-linux-gnu (x86_64) using readline 5.1') end + it { expect(Facter.fact(:mysql_version).value).to eq('5.0.95') } diff --git a/spec/unit/facter/mysqld_version_spec.rb b/spec/unit/facter/mysqld_version_spec.rb index 7b1067483..6b3330f08 100644 --- a/spec/unit/facter/mysqld_version_spec.rb +++ b/spec/unit/facter/mysqld_version_spec.rb @@ -14,6 +14,7 @@ allow(Facter::Core::Execution).to receive(:execute).with('env PATH=$PATH:/usr/libexec mysqld --no-defaults -V 2>/dev/null') .and_return('mysqld Ver 5.5.49-37.9 for Linux on x86_64 (Percona Server (GPL), Release 37.9, Revision efa0073)') end + it { expect(Facter.fact(:mysqld_version).value).to eq('mysqld Ver 5.5.49-37.9 for Linux on x86_64 (Percona Server (GPL), Release 37.9, Revision efa0073)') } diff --git a/spec/unit/puppet/provider/mysql_database/mysql_spec.rb b/spec/unit/puppet/provider/mysql_database/mysql_spec.rb index cd974c418..fd4c07e7a 100644 --- a/spec/unit/puppet/provider/mysql_database/mysql_spec.rb +++ b/spec/unit/puppet/provider/mysql_database/mysql_spec.rb @@ -15,14 +15,13 @@ ) end let(:raw_databases) do - <<-SQL_OUTPUT -information_schema -mydb -mysql -performance_schema -test + <<~SQL_OUTPUT + information_schema + mydb + mysql + performance_schema + test SQL_OUTPUT - # rubocop:enable Layout/IndentHeredoc end before :each do @@ -39,7 +38,7 @@ raw_databases.each_line do |db| allow(provider.class).to receive(:mysql_caller).with(["show variables like '%_database'", db.chomp], 'regular').and_return("character_set_database latin1\ncollation_database latin1_swedish_ci\nskip_show_database OFF") # rubocop:disable Layout/LineLength end - databases = provider.class.instances.map { |x| x.name } + databases = provider.class.instances.map(&:name) expect(parsed_databases).to match_array(databases) end end @@ -77,10 +76,12 @@ before :each do allow(Facter).to receive(:value).with(:root_home).and_return('/root') end + it 'sets --defaults-extra-file' do allow(File).to receive(:file?).with('/root/.my.cnf').and_return(true) expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf' end + it 'fails if file missing' do allow(File).to receive(:file?).with('/root/.my.cnf').and_return(false) expect(provider.defaults_file).to be_nil diff --git a/spec/unit/puppet/provider/mysql_login_path/mysql_login_path_spec.rb b/spec/unit/puppet/provider/mysql_login_path/mysql_login_path_spec.rb index 97927d39d..48f0a6afe 100644 --- a/spec/unit/puppet/provider/mysql_login_path/mysql_login_path_spec.rb +++ b/spec/unit/puppet/provider/mysql_login_path/mysql_login_path_spec.rb @@ -8,33 +8,33 @@ RSpec.describe Puppet::Provider::MysqlLoginPath::MysqlLoginPath do subject(:provider) { described_class.new } - let(:context) { instance_double('Puppet::ResourceApi::BaseContext') } - let(:wait_thr) { instance_double('wait_thr') } - let(:wait_thr_value) { instance_double('wait_thr_value') } + let(:context) { instance_double(Puppet::ResourceApi::BaseContext) } + let(:wait_thr) { instance_double(wait_thr) } + let(:wait_thr_value) { instance_double(wait_thr_value) } let(:sensitive_secure) { Puppet::Provider::MysqlLoginPath::Sensitive.new('secure') } let(:sensitive_more_secure) { Puppet::Provider::MysqlLoginPath::Sensitive.new('more_secure') } before :each do # Puppet::Util::Execution.stubs(:execute).with(['/usr/bin/getent', 'passwd', 'root'], failonfail: true).returns('root:x:0:0:root:/root:/bin/bash') allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/getent', 'passwd', 'root'], failonfail: true).and_return('root:x:0:0:root:/root:/bin/bash') - allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/mysql_config_editor', 'print', '--all'], failonfail: true, uid: 'root', - custom_environment: { 'HOME' => '/root' }).and_return("[local_tcp]\nuser = root\npassword = *****\nhost = 127.0.0.1\nport = 3306") + allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/mysql_config_editor', 'print', '--all'], failonfail: true, uid: 'root', custom_environment: { 'HOME' => '/root' }) + .and_return("[local_tcp]\nuser = root\npassword = *****\nhost = 127.0.0.1\nport = 3306") allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/mysql_config_editor', 'remove', '-G', 'local_socket'], failonfail: true, uid: 'root', custom_environment: { 'HOME' => '/root' }) - allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/my_print_defaults', '-s', 'local_tcp'], failonfail: true, uid: 'root', - custom_environment: { 'HOME' => '/root' }).and_return("--user=root\n--password=secure\n--host=127.0.0.1\n--port=3306") + allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/my_print_defaults', '-s', 'local_tcp'], failonfail: true, uid: 'root', custom_environment: { 'HOME' => '/root' }) + .and_return("--user=root\n--password=secure\n--host=127.0.0.1\n--port=3306") allow(Puppet::Util::Execution).to receive(:execute).with(['/usr/bin/my_print_defaults', '-s', 'local_socket'], failonfail: true, uid: 'root', custom_environment: { 'HOME' => '/root' }) .and_return("--user=root\n--password=more_secure\n--host=localhost\n--socket=/var/run/mysql.sock") allow(Puppet::Util::SUIDManager).to receive(:asuser).with('root').and_return(`(exit 0)`) allow(PTY).to receive(:spawn) .with({ 'HOME' => '/root' }, - '/usr/bin/mysql_config_editor set --skip-warn -G local_socket -h localhost -u root ' \ - '-S /var/run/mysql/mysql.sock -p') + '/usr/bin/mysql_config_editor set --skip-warn -G local_socket -h localhost -u root ' \ + '-S /var/run/mysql/mysql.sock -p') .and_return(`(exit 0)`) allow(PTY).to receive(:spawn) .with({ 'HOME' => '/root' }, - '/usr/bin/mysql_config_editor set --skip-warn -G local_socket -h 127.0.0.1 -u root -P 3306 -p') + '/usr/bin/mysql_config_editor set --skip-warn -G local_socket -h 127.0.0.1 -u root -P 3306 -p') .and_return(`(exit 0)`) end @@ -50,7 +50,7 @@ port: 3306, socket: nil, title: 'local_tcp-root', - user: 'root', + user: 'root' }, ] end diff --git a/spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb b/spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb index a7ad0eb24..887f86c6d 100644 --- a/spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb +++ b/spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb @@ -56,6 +56,7 @@ allow(File).to receive(:file?).with('/root/.my.cnf').and_return(true) expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf' end + it 'fails if file missing' do allow(File).to receive(:file?).with('/root/.my.cnf').and_return(false) expect(provider.defaults_file).to be_nil diff --git a/spec/unit/puppet/provider/mysql_user/mysql_spec.rb b/spec/unit/puppet/provider/mysql_user/mysql_spec.rb index 36a547114..6a900f8ae 100644 --- a/spec/unit/puppet/provider/mysql_user/mysql_spec.rb +++ b/spec/unit/puppet/provider/mysql_user/mysql_spec.rb @@ -9,56 +9,56 @@ { version: '5.5.46', string: '/usr/sbin/mysqld Ver 5.5.46-log for Linux on x86_64 (MySQL Community Server (GPL))', - mysql_type: 'mysql', + mysql_type: 'mysql' }, 'mysql-5.6' => { version: '5.6.27', string: '/usr/sbin/mysqld Ver 5.6.27 for Linux on x86_64 (MySQL Community Server (GPL))', - mysql_type: 'mysql', + mysql_type: 'mysql' }, 'mysql-5.7.1' => { version: '5.7.1', string: '/usr/sbin/mysqld Ver 5.7.1 for Linux on x86_64 (MySQL Community Server (GPL))', - mysql_type: 'mysql', + mysql_type: 'mysql' }, 'mysql-5.7.6' => { version: '5.7.8', string: '/usr/sbin/mysqld Ver 5.7.8-rc for Linux on x86_64 (MySQL Community Server (GPL))', - mysql_type: 'mysql', + mysql_type: 'mysql' }, 'mariadb-10.0' => { version: '10.0.21', string: '/usr/sbin/mysqld Ver 10.0.21-MariaDB for Linux on x86_64 (MariaDB Server)', - mysql_type: 'mariadb', + mysql_type: 'mariadb' }, 'mariadb-10.0-deb8' => { version: '10.0.23', string: '/usr/sbin/mysqld (mysqld 10.0.23-MariaDB-0+deb8u1)', - mysql_type: 'mariadb', + mysql_type: 'mariadb' }, 'mariadb-10.1.44' => { version: '10.1.44', string: '/usr/sbin/mysqld (mysqld 10.1.44-MariaDB-1~bionic)', - mysql_type: 'mariadb', + mysql_type: 'mariadb' }, 'mariadb-10.3.22' => { version: '10.3.22', string: '/usr/sbin/mysqld (mysqld 10.3.22-MariaDB-0+deb10u1)', - mysql_type: 'mariadb', + mysql_type: 'mariadb' }, 'percona-5.5' => { version: '5.5.39', string: 'mysqld Ver 5.5.39-36.0-55 for Linux on x86_64 (Percona XtraDB Cluster (GPL), Release rel36.0, Revision 824, WSREP version 25.11, wsrep_25.11.r4023)', - mysql_type: 'percona', - }, + mysql_type: 'percona' + } } let(:defaults_file) { '--defaults-extra-file=/root/.my.cnf' } @@ -66,16 +66,15 @@ let(:newhash) { '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' } let(:raw_users) do - <<-SQL_OUTPUT -root@127.0.0.1 -root@::1 -@localhost -debian-sys-maint@localhost -root@localhost -usvn_user@localhost -@vagrant-ubuntu-raring-64 + <<~SQL_OUTPUT + root@127.0.0.1 + root@::1 + @localhost + debian-sys-maint@localhost + root@localhost + usvn_user@localhost + @vagrant-ubuntu-raring-64 SQL_OUTPUT - # rubocop:enable Layout/IndentHeredoc end let(:parsed_users) { ['root@127.0.0.1', 'root@::1', '@localhost', 'debian-sys-maint@localhost', 'root@localhost', 'usvn_user@localhost', '@vagrant-ubuntu-raring-64'] } @@ -112,55 +111,61 @@ allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end + it 'returns an array of users MySQL 5.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.6'][:string]) allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end + it 'returns an array of users MySQL >= 5.7.0 < 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.1'][:string]) allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end + it 'returns an array of users MySQL >= 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.6'][:string]) allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, AUTHENTICATION_STRING, PLUGIN FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end + it 'returns an array of users mariadb 10.0' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.0'][:string]) allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end + it 'returns an array of users mariadb >= 10.1.21' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.1.44'][:string]) allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD, PLUGIN, AUTHENTICATION_STRING FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end + it 'returns an array of users percona 5.5' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['percona-5.5'][:string]) allow(provider.class).to receive(:mysql_caller).with("SELECT CONCAT(User, '@',Host) AS User FROM mysql.user", 'regular').and_return(raw_users) parsed_users.each { |user| allow(provider.class).to receive(:mysql_caller).with("SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'", 'regular').and_return('10 10 10 10 ') } # rubocop:disable Layout/LineLength - usernames = provider.class.instances.map { |x| x.name } + usernames = provider.class.instances.map(&:name) expect(parsed_users).to match_array(usernames) end end @@ -174,6 +179,7 @@ provider.class.instance_variable_set(:@mysqld_version_string, string) expect(provider.mysqld_version).to eq(version) end + it "detects type '#{mysql_type}'" do provider.class.instance_variable_set(:@mysqld_version_string, string) expect(provider.mysqld_type).to eq(mysql_type) @@ -190,19 +196,25 @@ describe 'create' do it 'makes a user' do - expect(provider.class).to receive(:mysql_caller).with("CREATE USER 'joe'@'localhost' IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'", 'system') - expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10", 'system') # rubocop:disable Layout/LineLength - expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE NONE", 'system') + output = ["CREATE USER 'joe'@'localhost' IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'", + "GRANT USAGE ON *.* TO 'joe'@'localhost' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10", + "GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE NONE"] + output.each do |out| + expect(provider.class).to receive(:mysql_caller).with(out, 'system') + end expect(provider).to receive(:exists?).and_return(true) expect(provider.create).to be_truthy end + it 'creates a user using IF NOT EXISTS' do provider.class.instance_variable_set(:@mysqld_version_string, '5.7.6') - expect(provider.class).to receive(:mysql_caller).with("CREATE USER IF NOT EXISTS 'joe'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'", -'system') - expect(provider.class).to receive(:mysql_caller).with("ALTER USER IF EXISTS 'joe'@'localhost' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10", 'system') # rubocop:disable Layout/LineLength - expect(provider.class).to receive(:mysql_caller).with("ALTER USER 'joe'@'localhost' REQUIRE NONE", 'system') + output = ["CREATE USER IF NOT EXISTS 'joe'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'", + "ALTER USER IF EXISTS 'joe'@'localhost' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10", + "ALTER USER 'joe'@'localhost' REQUIRE NONE"] + output.each do |out| + expect(provider.class).to receive(:mysql_caller).with(out, 'system') + end expect(provider).to receive(:exists?).and_return(true) expect(provider.create).to be_truthy end @@ -214,6 +226,7 @@ expect(provider).to receive(:exists?).and_return(false) expect(provider.destroy).to be_truthy end + it 'removes a user using IF EXISTS' do provider.class.instance_variable_set(:@mysqld_version_string, '5.7.1') @@ -234,18 +247,22 @@ allow(Facter).to receive(:value).with(:mysqld_version).and_return('5.6.24') expect(provider.mysqld_version).to eq '5.6.24' end - it 'returns 5.7.6 for "mysqld Ver 5.7.6 for Linux on x86_64 (MySQL Community Server (GPL))"' do + + it 'returns 5.7.6 for "mysqld Ver 5.7.6 for Linux on x86_64 (MySQL Community Server (GPL))"' do provider.class.instance_variable_set(:@mysqld_version_string, 'mysqld Ver 5.7.6 for Linux on x86_64 (MySQL Community Server (GPL))') expect(provider.mysqld_version).to eq '5.7.6' end - it 'returns 5.7.6 for "mysqld Ver 5.7.6-rc for Linux on x86_64 (MySQL Community Server (GPL))"' do + + it 'returns 5.7.6 for "mysqld Ver 5.7.6-rc for Linux on x86_64 (MySQL Community Server (GPL))"' do provider.class.instance_variable_set(:@mysqld_version_string, 'mysqld Ver 5.7.6-rc for Linux on x86_64 (MySQL Community Server (GPL))') expect(provider.mysqld_version).to eq '5.7.6' end + it 'detects >= 5.7.6 for 5.7.7-log' do provider.class.instance_variable_set(:@mysqld_version_string, 'mysqld Ver 5.7.7-log for Linux on x86_64 (MySQL Community Server (GPL))') expect(Puppet::Util::Package.versioncmp(provider.mysqld_version, '5.7.6')).to be >= 0 end + it 'detects < 5.7.6 for 5.7.5-log' do provider.class.instance_variable_set(:@mysqld_version_string, 'mysqld Ver 5.7.5-log for Linux on x86_64 (MySQL Community Server (GPL))') expect(Puppet::Util::Package.versioncmp(provider.mysqld_version, '5.7.6')).to be < 0 @@ -257,6 +274,7 @@ allow(File).to receive(:file?).with('/root/.my.cnf').and_return(true) expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf' end + it 'fails if file missing' do expect(File).to receive(:file?).with('/root/.my.cnf').and_return(false) expect(provider.defaults_file).to be_nil @@ -277,6 +295,7 @@ expect(provider).to receive(:password_hash).and_return('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5') provider.password_hash = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' end + it 'changes the hash mysql 5.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("SET PASSWORD FOR 'joe'@'localhost' = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5'", 'system').and_return('0') @@ -284,6 +303,7 @@ expect(provider).to receive(:password_hash).and_return('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5') provider.password_hash = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' end + it 'changes the hash mysql < 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.1'][:string]) expect(provider.class).to receive(:mysql_caller).with("SET PASSWORD FOR 'joe'@'localhost' = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5'", 'system').and_return('0') @@ -291,14 +311,16 @@ expect(provider).to receive(:password_hash).and_return('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5') provider.password_hash = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' end + it 'changes the hash MySQL >= 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("ALTER USER 'joe'@'localhost' IDENTIFIED WITH mysql_native_password AS '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:password_hash).and_return('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5') provider.password_hash = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' end + it 'changes the hash mariadb-10.0' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.0'][:string]) expect(provider.class).to receive(:mysql_caller).with("SET PASSWORD FOR 'joe'@'localhost' = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5'", 'system').and_return('0') @@ -306,6 +328,7 @@ expect(provider).to receive(:password_hash).and_return('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5') provider.password_hash = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' end + it 'changes the hash to an ed25519 hash mariadb >= 10.1.21 and < 10.2.0' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.1.44'][:string]) allow(resource).to receive(:value).with(:plugin).and_return('ed25519') @@ -313,6 +336,7 @@ expect(provider).to receive(:password_hash).and_return('z0pjExBYbzbupUByZRrQvC6kRCcE8n/tC7kUdUD11fU') provider.password_hash = 'z0pjExBYbzbupUByZRrQvC6kRCcE8n/tC7kUdUD11fU' end + it 'changes the hash to an ed25519 hash mariadb >= 10.2.0' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.3.22'][:string]) allow(resource).to receive(:value).with(:plugin).and_return('ed25519') @@ -320,11 +344,13 @@ expect(provider).to receive(:password_hash).and_return('z0pjExBYbzbupUByZRrQvC6kRCcE8n/tC7kUdUD11fU') provider.password_hash = 'z0pjExBYbzbupUByZRrQvC6kRCcE8n/tC7kUdUD11fU' end + it 'changes the hash to an invalid ed25519 hash mariadb >= 10.1.21' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.1.44'][:string]) allow(resource).to receive(:value).with(:plugin).and_return('ed25519') expect { provider.password_hash = 'invalid' }.to raise_error(ArgumentError, 'ed25519 hash should be 43 bytes long.') end + it 'changes the hash percona-5.5' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['percona-5.5'][:string]) expect(provider.class).to receive(:mysql_caller).with("SET PASSWORD FOR 'joe'@'localhost' = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5'", 'system').and_return('0') @@ -339,7 +365,8 @@ context 'MySQL < 5.7.6' do it 'changes the authentication plugin' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.1'][:string]) - expect(provider.class).to receive(:mysql_caller).with("UPDATE mysql.user SET plugin = 'auth_socket', password = '' WHERE CONCAT(user, '@', host) = 'joe@localhost'", 'system').and_return('0') + expect(provider.class).to receive(:mysql_caller).with("UPDATE mysql.user SET plugin = 'auth_socket', password = '' WHERE CONCAT(user, '@', host) = 'joe@localhost'", + 'system').and_return('0') expect(provider).to receive(:plugin).and_return('auth_socket') provider.plugin = 'auth_socket' @@ -372,7 +399,7 @@ it 'changes the authentication plugin' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("ALTER USER 'joe'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:plugin).and_return('mysql_native_password') provider.plugin = 'mysql_native_password' @@ -403,7 +430,6 @@ end end end - # rubocop:enable RSpec/NestedGroups end describe 'tls_options=' do @@ -414,6 +440,7 @@ expect(provider).to receive(:tls_options).and_return(['NONE']) provider.tls_options = ['NONE'] end + it 'adds SSL option grant in mysql 5.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE NONE", 'system').and_return('0') @@ -421,6 +448,7 @@ expect(provider).to receive(:tls_options).and_return(['NONE']) provider.tls_options = ['NONE'] end + it 'adds SSL option grant in mysql < 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.1'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE NONE", 'system').and_return('0') @@ -428,6 +456,7 @@ expect(provider).to receive(:tls_options).and_return(['NONE']) provider.tls_options = ['NONE'] end + it 'adds SSL option grant in mysql >= 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("ALTER USER 'joe'@'localhost' REQUIRE NONE", 'system').and_return('0') @@ -435,6 +464,7 @@ expect(provider).to receive(:tls_options).and_return(['NONE']) provider.tls_options = ['NONE'] end + it 'adds SSL option grant in mariadb-10.0' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.0'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE NONE", 'system').and_return('0') @@ -448,39 +478,43 @@ it 'adds mTLS option grant in mysql 5.5' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.5'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE ISSUER '/CN=Certificate Authority' AND SUBJECT '/OU=MySQL Users/CN=Username'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:tls_options).and_return(['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\'']) provider.tls_options = ['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\''] end + it 'adds mTLS option grant in mysql 5.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE ISSUER '/CN=Certificate Authority' AND SUBJECT '/OU=MySQL Users/CN=Username'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:tls_options).and_return(['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\'']) provider.tls_options = ['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\''] end + it 'adds mTLS option grant in mysql < 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.1'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE ISSUER '/CN=Certificate Authority' AND SUBJECT '/OU=MySQL Users/CN=Username'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:tls_options).and_return(['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\'']) provider.tls_options = ['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\''] end + it 'adds mTLS option grant in mysql >= 5.7.6' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mysql-5.7.6'][:string]) expect(provider.class).to receive(:mysql_caller).with("ALTER USER 'joe'@'localhost' REQUIRE ISSUER '/CN=Certificate Authority' AND SUBJECT '/OU=MySQL Users/CN=Username'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:tls_options).and_return(['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\'']) provider.tls_options = ['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\''] end + it 'adds mTLS option grant in mariadb-10.0' do provider.class.instance_variable_set(:@mysqld_version_string, mysql_version_string_hash['mariadb-10.0'][:string]) expect(provider.class).to receive(:mysql_caller).with("GRANT USAGE ON *.* TO 'joe'@'localhost' REQUIRE ISSUER '/CN=Certificate Authority' AND SUBJECT '/OU=MySQL Users/CN=Username'", -'system').and_return('0') + 'system').and_return('0') expect(provider).to receive(:tls_options).and_return(['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\'']) provider.tls_options = ['ISSUER \'/CN=Certificate Authority\'', 'SUBJECT \'/OU=MySQL Users/CN=Username\''] diff --git a/spec/unit/puppet/type/mysql_grant_spec.rb b/spec/unit/puppet/type/mysql_grant_spec.rb index c90d66081..1ef62928b 100644 --- a/spec/unit/puppet/type/mysql_grant_spec.rb +++ b/spec/unit/puppet/type/mysql_grant_spec.rb @@ -70,10 +70,11 @@ Puppet::Type.type(:mysql_grant).new(name: 'foo@localhost/*.*', privileges: ['ALL'], table: ['*.*'], user: 'foo@localhost') }.not_to raise_error end + it 'requires the name to match the user and table #specific' do expect { Puppet::Type.type(:mysql_grant).new(name: 'foo', privileges: ['ALL'], table: ['*.*'], user: 'foo@localhost') - }.to raise_error %r{mysql_grant: `name` `parameter` must match user@host\/table format} + }.to raise_error %r{mysql_grant: `name` `parameter` must match user@host/table format} end describe 'it should munge privileges' do diff --git a/spec/unit/puppet/type/mysql_user_spec.rb b/spec/unit/puppet/type/mysql_user_spec.rb index a19359653..cd1698f53 100644 --- a/spec/unit/puppet/type/mysql_user_spec.rb +++ b/spec/unit/puppet/type/mysql_user_spec.rb @@ -92,7 +92,7 @@ end end - context 'using a quoted username that is too long ' do + context 'using a quoted username that is too long' do before :each do allow(Facter).to receive(:value).with(:mysql_version).and_return('5.6.24') end diff --git a/tasks/export.rb b/tasks/export.rb index 6bf3e836c..7688633ae 100755 --- a/tasks/export.rb +++ b/tasks/export.rb @@ -13,10 +13,11 @@ def get(file, database, user, password) cmd_string << " > #{file}" unless file.nil? stdout, stderr, status = Open3.capture3(cmd_string) raise Puppet::Error, _("stderr: '%{stderr}'" % { stderr: stderr }) if status != 0 + { status: stdout.strip } end -params = JSON.parse(STDIN.read) +params = JSON.parse($stdin.read) database = params['database'] user = params['user'] password = params['password'] diff --git a/tasks/sql.rb b/tasks/sql.rb index 13e323485..aeeec5bea 100755 --- a/tasks/sql.rb +++ b/tasks/sql.rb @@ -12,10 +12,11 @@ def get(sql, database, user, password) cmd << "--password=#{password}" unless password.nil? stdout, stderr, status = Open3.capture3(*cmd) raise Puppet::Error, _("stderr: '%{stderr}'" % { stderr: stderr }) if status != 0 + { status: stdout.strip } end -params = JSON.parse(STDIN.read) +params = JSON.parse($stdin.read) database = params['database'] user = params['user'] password = params['password']