diff --git a/.rubocop.yml b/.rubocop.yml index 5aadd1b64..d66cbd686 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,508 +1,96 @@ +--- require: rubocop-rspec AllCops: - TargetRubyVersion: 1.9 + TargetRubyVersion: '2.1' Include: - - ./**/*.rb + - "./**/*.rb" Exclude: - - vendor/**/* - - .vendor/**/* - - pkg/**/* - - spec/fixtures/**/* -Lint/ConditionPosition: - Enabled: True - -Lint/ElseLayout: - Enabled: True - -Lint/UnreachableCode: - Enabled: True - -Lint/UselessComparison: - Enabled: True - -Lint/EnsureReturn: - Enabled: True - -Lint/HandleExceptions: - Enabled: True - -Lint/LiteralInCondition: - Enabled: True - -Lint/ShadowingOuterLocalVariable: - Enabled: True - -Lint/LiteralInInterpolation: - Enabled: True - -Style/HashSyntax: - Enabled: True - -Style/RedundantReturn: - Enabled: True - -Lint/AmbiguousOperator: - Enabled: True - -Lint/AssignmentInCondition: - Enabled: True - -Style/SpaceBeforeComment: - Enabled: True - -Style/AndOr: - Enabled: True - -Style/RedundantSelf: - Enabled: True - -# Method length is not necessarily an indicator of code quality -Metrics/MethodLength: - Enabled: False - -# Module length is not necessarily an indicator of code quality -Metrics/ModuleLength: - Enabled: False - -Style/WhileUntilModifier: - Enabled: True - -Lint/AmbiguousRegexpLiteral: - Enabled: True - -Lint/Eval: - Enabled: True - -Lint/BlockAlignment: - Enabled: True - -Lint/DefEndAlignment: - Enabled: True - -Lint/EndAlignment: - Enabled: True - -Lint/DeprecatedClassMethods: - Enabled: True - -Lint/Loop: - Enabled: True - -Lint/ParenthesesAsGroupedExpression: - Enabled: True - -Lint/RescueException: - Enabled: True - -Lint/StringConversionInInterpolation: - Enabled: True - -Lint/UnusedBlockArgument: - Enabled: True - -Lint/UnusedMethodArgument: - Enabled: True - -Lint/UselessAccessModifier: - Enabled: True - -Lint/UselessAssignment: - Enabled: True - -Lint/Void: - Enabled: True - -Style/AccessModifierIndentation: - Enabled: True - -Style/AccessorMethodName: - Enabled: True - -Style/Alias: - Enabled: True - -Style/AlignArray: - Enabled: True - -Style/AlignHash: - Enabled: True - -Style/AlignParameters: - Enabled: True - -Metrics/BlockNesting: - Enabled: True - -Style/AsciiComments: - Enabled: True - -Style/Attr: - Enabled: True - -Style/BracesAroundHashParameters: - Enabled: True - -Style/CaseEquality: - Enabled: True - -Style/CaseIndentation: - Enabled: True - -Style/CharacterLiteral: - Enabled: True - -Style/ClassAndModuleCamelCase: - Enabled: True - -Style/ClassAndModuleChildren: - Enabled: False - -Style/ClassCheck: - Enabled: True - -# Class length is not necessarily an indicator of code quality -Metrics/ClassLength: - Enabled: False - -Style/ClassMethods: - Enabled: True - -Style/ClassVars: - Enabled: True - -Style/WhenThen: - Enabled: True - -Style/WordArray: - Enabled: True - -Style/UnneededPercentQ: - Enabled: True - -Style/Tab: - Enabled: True - -Style/SpaceBeforeSemicolon: - Enabled: True - -Style/TrailingBlankLines: - Enabled: True - -Style/SpaceInsideBlockBraces: - Enabled: True - -Style/SpaceInsideBrackets: - Enabled: True - -Style/SpaceInsideHashLiteralBraces: - Enabled: True - -Style/SpaceInsideParens: - Enabled: True - -Style/LeadingCommentSpace: - Enabled: True - -Style/SpaceBeforeFirstArg: - Enabled: True - -Style/SpaceAfterColon: - Enabled: True - -Style/SpaceAfterComma: - Enabled: True - -Style/SpaceAfterMethodName: - Enabled: True - -Style/SpaceAfterNot: - Enabled: True - -Style/SpaceAfterSemicolon: - Enabled: True - -Style/SpaceAroundEqualsInParameterDefault: - Enabled: True - -Style/SpaceAroundOperators: - Enabled: True - -Style/SpaceBeforeBlockBraces: - Enabled: True - -Style/SpaceBeforeComma: - Enabled: True - -Style/CollectionMethods: - Enabled: True - -Style/CommentIndentation: - Enabled: True - -Style/ColonMethodCall: - Enabled: True - -Style/CommentAnnotation: - Enabled: True - -# 'Complexity' is very relative -Metrics/CyclomaticComplexity: - Enabled: False - -Style/ConstantName: - Enabled: True - -Style/Documentation: - Enabled: False - -Style/DefWithParentheses: - Enabled: True - -Style/PreferredHashMethods: - Enabled: True - -Style/DotPosition: - EnforcedStyle: trailing - -Style/DoubleNegation: - Enabled: True - -Style/EachWithObject: - Enabled: True - -Style/EmptyLineBetweenDefs: - Enabled: True - -Style/IndentArray: - Enabled: True - -Style/IndentHash: - Enabled: True - -Style/IndentationConsistency: - Enabled: True - -Style/IndentationWidth: - Enabled: True - -Style/EmptyLines: - Enabled: True - -Style/EmptyLinesAroundAccessModifier: - Enabled: True - -Style/EmptyLiteral: - Enabled: True - -# Configuration parameters: AllowURI, URISchemes. + - bin/* + - ".vendor/**/*" + - Gemfile + - Rakefile + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* Metrics/LineLength: - Enabled: False - -Style/MethodCallParentheses: - Enabled: True - -Style/MethodDefParentheses: - Enabled: True - -Style/LineEndConcatenation: - Enabled: True - -Style/TrailingWhitespace: - Enabled: True - -Style/StringLiterals: - Enabled: True - -Style/TrailingCommaInArguments: - Enabled: True - -Style/TrailingCommaInLiteral: - Enabled: True - -Style/GlobalVars: - Enabled: True - -Style/GuardClause: - Enabled: True - -Style/IfUnlessModifier: - Enabled: True - -Style/MultilineIfThen: - Enabled: True - -Style/NegatedIf: - Enabled: True - -Style/NegatedWhile: - Enabled: True - -Style/Next: - Enabled: True - -Style/SingleLineBlockParams: - Enabled: True - -Style/SingleLineMethods: - Enabled: True - -Style/SpecialGlobalVars: - Enabled: True - -Style/TrivialAccessors: - Enabled: True - -Style/UnlessElse: - Enabled: True - -Style/VariableInterpolation: - Enabled: True - -Style/VariableName: - Enabled: True - -Style/WhileUntilDo: - Enabled: True - -Style/EvenOdd: - Enabled: True - -Style/FileName: - Enabled: True - -Style/For: - Enabled: True - -Style/Lambda: - Enabled: True - -Style/MethodName: - Enabled: True - -Style/MultilineTernaryOperator: - Enabled: True - -Style/NestedTernaryOperator: - Enabled: True - -Style/NilComparison: - Enabled: True - + Description: People have wide screens, use them. + Max: 200 +RSpec/BeforeAfterAll: + Description: Beware of using after(:all) as it may cause state to leak between tests. + A necessary evil in acceptance testing. + Exclude: + - spec/acceptance/**/*.rb +RSpec/HookArgument: + Description: Prefer explicit :each argument, matching existing module's style + EnforcedStyle: each +Style/BlockDelimiters: + Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to + be consistent then. + EnforcedStyle: braces_for_chaining +Style/ClassAndModuleChildren: + Description: Compact style reduces the required amount of indentation. + EnforcedStyle: compact +Style/EmptyElse: + Description: Enforce against empty else clauses, but allow `nil` for clarity. + EnforcedStyle: empty Style/FormatString: - Enabled: True - -Style/MultilineBlockChain: - Enabled: True - -Style/Semicolon: - Enabled: True - -Style/SignalException: - Enabled: True - -Style/NonNilCheck: - Enabled: True - -Style/Not: - Enabled: True - -Style/NumericLiterals: - Enabled: True - -Style/OneLineConditional: - Enabled: True - -Style/OpMethod: - Enabled: True - -Style/ParenthesesAroundCondition: - Enabled: True - -Style/PercentLiteralDelimiters: - Enabled: True - -Style/PerlBackrefs: - Enabled: True - -Style/PredicateName: - Enabled: True - -Style/RedundantException: - Enabled: True - -Style/SelfAssignment: - Enabled: True - -Style/Proc: - Enabled: True - -Style/RaiseArgs: - Enabled: True - -Style/RedundantBegin: - Enabled: True - -Style/RescueModifier: - Enabled: True - -# based on https://github.com/voxpupuli/modulesync_config/issues/168 + Description: Following the main puppet project's style, prefer the % format format. + EnforcedStyle: percent +Style/FormatStringToken: + Description: Following the main puppet project's style, prefer the simpler template + tokens over annotated ones. + EnforcedStyle: template +Style/Lambda: + Description: Prefer the keyword for easier discoverability. + EnforcedStyle: literal Style/RegexpLiteral: + Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 EnforcedStyle: percent_r - Enabled: True - -Lint/UnderscorePrefixedVariableName: - Enabled: True - -Metrics/ParameterLists: - Enabled: False - -Lint/RequireParentheses: - Enabled: True - -Style/SpaceBeforeFirstArg: - Enabled: True - -Style/ModuleFunction: - Enabled: True - -Lint/Debugger: - Enabled: True - -Style/IfWithSemicolon: - Enabled: True - -Style/Encoding: - Enabled: True - -Style/BlockDelimiters: - Enabled: True - -Style/MultilineBlockLayout: - Enabled: True - -# 'Complexity' is very relative +Style/TernaryParentheses: + Description: Checks for use of parentheses around ternary conditions. Enforce parentheses + on complex expressions for better readability, but seriously consider breaking + it up. + EnforcedStyle: require_parentheses_when_complex +Style/TrailingCommaInArguments: + Description: Prefer always trailing comma on multiline argument lists. This makes + diffs, and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/TrailingCommaInLiteral: + Description: Prefer always trailing comma on multiline literals. This makes diffs, + and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/SymbolArray: + Description: Using percent style obscures symbolic intent of array's contents. + EnforcedStyle: brackets +Style/CollectionMethods: + Enabled: true +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true Metrics/AbcSize: - Enabled: False - -# 'Complexity' is very relative + Enabled: false +Metrics/BlockLength: + 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 - -Lint/UselessAssignment: - Enabled: True - -Style/ClosingParenthesisIndentation: - Enabled: False - -# RSpec - -# We don't use rspec in this way + Enabled: false RSpec/DescribeClass: - Enabled: False - -# Example length is not necessarily an indicator of code quality -RSpec/ExampleLength: - Enabled: False - -RSpec/NamedSubject: - Enabled: False + Enabled: false +RSpec/MessageExpectation: + Enabled: false +Style/AsciiComments: + Enabled: false +Style/IfUnlessModifier: + Enabled: false +Style/SymbolProc: + Enabled: false diff --git a/.sync.yml b/.sync.yml index c1cd868fa..e31be44e9 100644 --- a/.sync.yml +++ b/.sync.yml @@ -3,3 +3,8 @@ appveyor.yml: delete: true spec/spec_helper.rb: allow_deprecations: true +.travis.yml: + extras: + - rvm: 2.1.9 + bundler_args: --without system_tests + script: bundle exec rubocop lib diff --git a/.travis.yml b/.travis.yml index 0c6f904c3..67294f4de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,5 +28,8 @@ matrix: - rvm: 2.1.9 bundler_args: --without system_tests env: PUPPET_GEM_VERSION="~> 4.0" + - rvm: 2.1.9 + bundler_args: --without system_tests + script: bundle exec rubocop lib notifications: email: false diff --git a/lib/facter/mysql_server_id.rb b/lib/facter/mysql_server_id.rb index 3cb39e535..b658dca23 100644 --- a/lib/facter/mysql_server_id.rb +++ b/lib/facter/mysql_server_id.rb @@ -1,9 +1,13 @@ -def get_mysql_id - Facter.value(:macaddress).split(':')[2..-1].inject(0) { |total,value| (total << 6) + value.hex } +def mysql_id_get + Facter.value(:macaddress).split(':')[2..-1].reduce(0) { |total, value| (total << 6) + value.hex } end -Facter.add("mysql_server_id") do +Facter.add('mysql_server_id') do setcode do - get_mysql_id rescue nil + begin + mysql_id_get + rescue + nil + end end end diff --git a/lib/facter/mysql_version.rb b/lib/facter/mysql_version.rb index 62fba6156..1046f4588 100644 --- a/lib/facter/mysql_version.rb +++ b/lib/facter/mysql_version.rb @@ -1,8 +1,6 @@ -Facter.add("mysql_version") do +Facter.add('mysql_version') do setcode do mysql_ver = Facter::Util::Resolution.exec('mysql --version') - if mysql_ver - mysql_ver.match(/\d+\.\d+\.\d+/)[0] - end + mysql_ver.match(%r{\d+\.\d+\.\d+})[0] if mysql_ver end end diff --git a/lib/facter/mysqld_version.rb b/lib/facter/mysqld_version.rb index c3711cc5e..61e2acf9a 100644 --- a/lib/facter/mysqld_version.rb +++ b/lib/facter/mysqld_version.rb @@ -1,4 +1,4 @@ -Facter.add("mysqld_version") do +Facter.add('mysqld_version') do setcode do Facter::Util::Resolution.exec('mysqld -V 2>/dev/null') end diff --git a/lib/puppet/parser/functions/mysql_deepmerge.rb b/lib/puppet/parser/functions/mysql_deepmerge.rb index aca9c7a3d..19d8e0283 100644 --- a/lib/puppet/parser/functions/mysql_deepmerge.rb +++ b/lib/puppet/parser/functions/mysql_deepmerge.rb @@ -1,5 +1,6 @@ +# Recursively merges two or more hashes together and returns the resulting hash. module Puppet::Parser::Functions - newfunction(:mysql_deepmerge, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args| + newfunction(:mysql_deepmerge, type: :rvalue, doc: <<-'ENDHEREDOC') do |args| Recursively merges two or more hashes together and returns the resulting hash. For example: @@ -18,12 +19,12 @@ module Puppet::Parser::Functions ENDHEREDOC if args.length < 2 - raise Puppet::ParseError, ("mysql_deepmerge(): wrong number of arguments (#{args.length}; must be at least 2)") + raise Puppet::ParseError, "mysql_deepmerge(): wrong number of arguments (#{args.length}; must be at least 2)" end - result = Hash.new + result = {} args.each do |arg| - next if arg.is_a? String and arg.empty? # empty string is synonym for puppet's undef + 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_deepmerge: unexpected argument type #{arg.class}, only expects hash arguments" @@ -32,25 +33,25 @@ module Puppet::Parser::Functions # Now we have to traverse our hash assigning our non-hash values # to the matching keys in our result while following our hash values # and repeating the process. - overlay( result, arg ) + overlay(result, arg) end - return( result ) + return(result) end end -def has_normalized!(hash, key) - return true if hash.has_key?( key ) - return false unless key.match(/-|_/) - other_key = key.include?('-') ? key.gsub( '-', '_' ) : key.gsub( '_', '-' ) - return false unless hash.has_key?( other_key ) - hash[key] = hash.delete( other_key ) - return true; +def normalized!(hash, key) + return true if hash.key?(key) + return false unless key =~ %r{-|_} + other_key = key.include?('-') ? key.tr('-', '_') : key.tr('_', '-') + return false unless hash.key?(other_key) + hash[key] = hash.delete(other_key) + true end -def overlay( hash1, hash2 ) +def overlay(hash1, hash2) hash2.each do |key, value| - if(has_normalized!( hash1, key ) and value.is_a?(Hash) and hash1[key].is_a?(Hash)) - overlay( hash1[key], value ) + if normalized!(hash1, key) && value.is_a?(Hash) && hash1[key].is_a?(Hash) + overlay(hash1[key], value) else hash1[key] = value end diff --git a/lib/puppet/parser/functions/mysql_dirname.rb b/lib/puppet/parser/functions/mysql_dirname.rb index 5d0ef5557..33680a7dd 100644 --- a/lib/puppet/parser/functions/mysql_dirname.rb +++ b/lib/puppet/parser/functions/mysql_dirname.rb @@ -1,11 +1,14 @@ +# Returns the dirname of a path. module Puppet::Parser::Functions - newfunction(:mysql_dirname, :type => :rvalue, :doc => <<-EOS + newfunction(:mysql_dirname, type: :rvalue, doc: <<-EOS Returns the dirname of a path. EOS - ) do |arguments| + ) do |arguments| - raise(Puppet::ParseError, "mysql_dirname(): Wrong number of arguments " + - "given (#{arguments.size} for 1)") if arguments.size < 1 + if arguments.empty? + raise(Puppet::ParseError, 'mysql_dirname(): Wrong number of arguments ' \ + "given (#{arguments.size} for 1)") + end path = arguments[0] return File.dirname(path) diff --git a/lib/puppet/parser/functions/mysql_password.rb b/lib/puppet/parser/functions/mysql_password.rb index 74d7fa8cc..3d3f4f841 100644 --- a/lib/puppet/parser/functions/mysql_password.rb +++ b/lib/puppet/parser/functions/mysql_password.rb @@ -1,17 +1,19 @@ -# hash a string as mysql's "PASSWORD()" function would do it require 'digest/sha1' - +# Returns the mysql password hash from the clear text password. +# Hash a string as mysql's "PASSWORD()" function would do it module Puppet::Parser::Functions - newfunction(:mysql_password, :type => :rvalue, :doc => <<-EOS + newfunction(:mysql_password, type: :rvalue, doc: <<-EOS Returns the mysql password hash from the clear text password. EOS - ) do |args| + ) do |args| - raise(Puppet::ParseError, 'mysql_password(): Wrong number of arguments ' + - "given (#{args.size} for 1)") if args.size != 1 + if args.size != 1 + raise(Puppet::ParseError, 'mysql_password(): Wrong number of arguments ' \ + "given (#{args.size} for 1)") + end return '' if args[0].empty? - return args[0] if args[0] =~ /\*[A-F0-9]{40}$/ + return args[0] if args[0] =~ %r{\*[A-F0-9]{40}$} '*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(args[0])).upcase end end diff --git a/lib/puppet/parser/functions/mysql_strip_hash.rb b/lib/puppet/parser/functions/mysql_strip_hash.rb index 8e850d02a..e4a71c285 100644 --- a/lib/puppet/parser/functions/mysql_strip_hash.rb +++ b/lib/puppet/parser/functions/mysql_strip_hash.rb @@ -1,9 +1,10 @@ +# When given a hash this function strips out all blank entries. module Puppet::Parser::Functions - newfunction(:mysql_strip_hash, :type => :rvalue, :arity => 1, :doc => <<-EOS -TEMPORARY FUNCTION: EXPIRES 2014-03-10 -When given a hash this function strips out all blank entries. + newfunction(:mysql_strip_hash, type: :rvalue, arity: 1, doc: <<-EOS + TEMPORARY FUNCTION: EXPIRES 2014-03-10 + When given a hash this function strips out all blank entries. EOS - ) do |args| + ) do |args| hash = args[0] unless hash.is_a?(Hash) @@ -11,11 +12,8 @@ module Puppet::Parser::Functions end # Filter out all the top level blanks. - hash.reject{|k,v| v == ''}.each do |k,v| - if v.is_a?(Hash) - v.reject!{|ki,vi| vi == '' } - end + hash.reject { |_k, v| v == '' }.each do |_k, v| + v.reject! { |_ki, vi| vi == '' } if v.is_a?(Hash) end - end end diff --git a/lib/puppet/provider/mysql.rb b/lib/puppet/provider/mysql.rb index 181d788bf..43f0964fd 100644 --- a/lib/puppet/provider/mysql.rb +++ b/lib/puppet/provider/mysql.rb @@ -1,29 +1,25 @@ +# Puppet provider for mysql class Puppet::Provider::Mysql < Puppet::Provider - # Without initvars commands won't work. 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['PATH'] + ':/usr/libexec:/usr/local/libexec:/usr/local/bin' - commands :mysql => 'mysql' - commands :mysqld => 'mysqld' - commands :mysqladmin => 'mysqladmin' + commands mysql: 'mysql' + commands mysqld: 'mysqld' + commands mysqladmin: 'mysqladmin' # Optional defaults file def self.defaults_file - if File.file?("#{Facter.value(:root_home)}/.my.cnf") - "--defaults-extra-file=#{Facter.value(:root_home)}/.my.cnf" - else - nil - end + "--defaults-extra-file=#{Facter.value(:root_home)}/.my.cnf" if File.file?("#{Facter.value(:root_home)}/.my.cnf") end def self.mysqld_type # find the mysql "dialect" like mariadb / mysql etc. - mysqld_version_string.scan(/mariadb/i) { return "mariadb" } - mysqld_version_string.scan(/\s\(percona/i) { return "percona" } - return "mysql" + mysqld_version_string.scan(%r{mariadb}i) { return 'mariadb' } + mysqld_version_string.scan(%r{\s\(percona}i) { return 'percona' } + 'mysql' end def mysqld_type @@ -31,7 +27,9 @@ def mysqld_type end def self.mysqld_version_string - # As the possibility of the mysqld being remote we need to allow the version string to be overridden, this can be done by facter.value as seen below. In the case that it has not been set and the facter value is nil we use the mysql -v command to ensure we report the correct version of mysql for later use cases. + # As the possibility of the mysqld being remote we need to allow the version string to be overridden, + # this can be done by facter.value as seen below. In the case that it has not been set and the facter + # value is nil we use the mysql -v command to ensure we report the correct version of mysql for later use cases. @mysqld_version_string ||= Facter.value(:mysqld_version) || mysqld('-V') end @@ -43,7 +41,7 @@ def self.mysqld_version # note: be prepared for '5.7.6-rc-log' etc results # versioncmp detects 5.7.6-log to be newer then 5.7.6 # this is why we need the trimming. - mysqld_version_string.scan(/\d+\.\d+\.\d+/).first unless mysqld_version_string.nil? + mysqld_version_string.scan(%r{\d+\.\d+\.\d+}).first unless mysqld_version_string.nil? end def mysqld_version @@ -77,39 +75,33 @@ def self.cmd_table(table) table_string = '' # We can't escape *.* so special case this. - if table == '*.*' - table_string << '*.*' - # Special case also for PROCEDURES - elsif table.start_with?('PROCEDURE ') - table_string << table.sub(/^PROCEDURE (.*)(\..*)/, 'PROCEDURE `\1`\2') - else - table_string << table.sub(/^(.*)(\..*)/, '`\1`\2') - end + table_string << if table == '*.*' + '*.*' + # Special case also for PROCEDURES + elsif table.start_with?('PROCEDURE ') + table.sub(%r{^PROCEDURE (.*)(\..*)}, 'PROCEDURE `\1`\2') + else + table.sub(%r{^(.*)(\..*)}, '`\1`\2') + end table_string end def self.cmd_privs(privileges) - if privileges.include?('ALL') - return 'ALL PRIVILEGES' - else - priv_string = '' - privileges.each do |priv| - priv_string << "#{priv}, " - end + return 'ALL PRIVILEGES' if privileges.include?('ALL') + priv_string = '' + privileges.each do |priv| + priv_string << "#{priv}, " end # Remove trailing , from the last element. - priv_string.sub(/, $/, '') + priv_string.sub(%r{, $}, '') end # Take in potential options and build up a query string with them. def self.cmd_options(options) option_string = '' options.each do |opt| - if opt == 'GRANT' - option_string << ' WITH GRANT OPTION' - end + option_string << ' WITH GRANT OPTION' if opt == 'GRANT' end option_string end - end diff --git a/lib/puppet/provider/mysql_database/mysql.rb b/lib/puppet/provider/mysql_database/mysql.rb index 4587c1882..623aac736 100644 --- a/lib/puppet/provider/mysql_database/mysql.rb +++ b/lib/puppet/provider/mysql_database/mysql.rb @@ -1,21 +1,20 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql')) -Puppet::Type.type(:mysql_database).provide(:mysql, :parent => Puppet::Provider::Mysql) do +Puppet::Type.type(:mysql_database).provide(:mysql, parent: Puppet::Provider::Mysql) do desc 'Manages MySQL databases.' - commands :mysql => 'mysql' + commands mysql: 'mysql' def self.instances - mysql([defaults_file, '-NBe', 'show databases'].compact).split("\n").collect do |name| + mysql([defaults_file, '-NBe', 'show databases'].compact).split("\n").map do |name| attributes = {} mysql([defaults_file, '-NBe', "show variables like '%_database'", name].compact).split("\n").each do |line| - k,v = line.split(/\s/) + k, v = line.split(%r{\s}) attributes[k] = v end - new(:name => name, - :ensure => :present, - :charset => attributes['character_set_database'], - :collate => attributes['collation_database'] - ) + new(name: name, + ensure: :present, + charset: attributes['character_set_database'], + collate: attributes['collation_database']) end end @@ -24,9 +23,8 @@ def self.instances def self.prefetch(resources) databases = instances resources.keys.each do |database| - if provider = databases.find { |db| db.name == database } - resources[database].provider = provider - end + provider = databases.find { |db| db.name == database } + resources[database].provider = provider if provider end end @@ -56,13 +54,12 @@ def exists? def charset=(value) mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` CHARACTER SET #{value}"].compact) @property_hash[:charset] = value - charset == value ? (return true) : (return false) + (charset == value) ? (return true) : (return false) end def collate=(value) mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` COLLATE #{value}"].compact) @property_hash[:collate] = value - collate == value ? (return true) : (return false) + (collate == value) ? (return true) : (return false) end - end diff --git a/lib/puppet/provider/mysql_datadir/mysql.rb b/lib/puppet/provider/mysql_datadir/mysql.rb index f451511c5..2d821f1e0 100644 --- a/lib/puppet/provider/mysql_datadir/mysql.rb +++ b/lib/puppet/provider/mysql_datadir/mysql.rb @@ -1,71 +1,71 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql')) -Puppet::Type.type(:mysql_datadir).provide(:mysql, :parent => Puppet::Provider::Mysql) do - +Puppet::Type.type(:mysql_datadir).provide(:mysql, parent: Puppet::Provider::Mysql) do desc 'manage data directories for mysql instances' initvars # Make sure we find mysqld on CentOS and mysql_install_db on Gentoo and Solaris 11 - ENV['PATH']=ENV['PATH'] + ':/usr/libexec:/usr/share/mysql/scripts:/opt/rh/mysql55/root/usr/bin:/opt/rh/mysql55/root/usr/libexec:/usr/mysql/5.5/bin:/usr/mysql/5.6/bin:/usr/mysql/5.7/bin' - - commands :mysqld => 'mysqld' - commands :mysql_install_db => 'mysql_install_db' + ENV['PATH'] = ENV['PATH'] + ':/usr/libexec:/usr/share/mysql/scripts:/opt/rh/mysql55/root/usr/bin:/opt/rh/mysql55/root/usr/libexec:/usr/mysql/5.5/bin:/usr/mysql/5.6/bin:/usr/mysql/5.7/bin' + commands mysqld: 'mysqld' + commands mysql_install_db: 'mysql_install_db' + # rubocop:disable Lint/UselessAssignment def create - name = @resource[:name] + name = @resource[:name] insecure = @resource.value(:insecure) || true defaults_extra_file = @resource.value(:defaults_extra_file) - user = @resource.value(:user) || "mysql" + user = @resource.value(:user) || 'mysql' basedir = @resource.value(:basedir) datadir = @resource.value(:datadir) || @resource[:name] - log_error = @resource.value(:log_error) || "/var/tmp/mysqld_initialize.log" - + log_error = @resource.value(:log_error) || '/var/tmp/mysqld_initialize.log' + # rubocop:enable Lint/UselessAssignment unless defaults_extra_file.nil? - if File.exist?(defaults_extra_file) - defaults_extra_file="--defaults-extra-file=#{defaults_extra_file}" - else + unless File.exist?(defaults_extra_file) raise ArgumentError, "Defaults-extra-file #{defaults_extra_file} is missing" end + defaults_extra_file = "--defaults-extra-file=#{defaults_extra_file}" end - if insecure == true - initialize="--initialize-insecure" - else - initialize="--initialize" - end + initialize = if insecure == true + '--initialize-insecure' + else + '--initialize' + end - opts = [ defaults_extra_file ] - %w(basedir datadir user).each do |opt| + opts = [defaults_extra_file] + %w[basedir datadir user].each do |opt| + # rubocop:disable Security/Eval val = eval(opt) - opts<<"--#{opt}=#{val}" unless val.nil? + # rubocop:enable Security/Eval + opts << "--#{opt}=#{val}" unless val.nil? end if mysqld_version.nil? - debug("Installing MySQL data directory with mysql_install_db #{opts.compact.join(" ")}") + debug("Installing MySQL data directory with mysql_install_db #{opts.compact.join(' ')}") mysql_install_db(opts.compact) + elsif (mysqld_type == 'mysql' || mysqld_type == 'percona') && Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0 + opts << "--log-error=#{log_error}" + opts << initialize.to_s + debug("Initializing MySQL data directory >= 5.7.6 with mysqld: #{opts.compact.join(' ')}") + mysqld(opts.compact) else - if (mysqld_type == "mysql" or mysqld_type == "percona") and Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0 - opts<<"--log-error=#{log_error}" - opts<<"#{initialize}" - debug("Initializing MySQL data directory >= 5.7.6 with mysqld: #{opts.compact.join(" ")}") - mysqld(opts.compact) - else - debug("Installing MySQL data directory with mysql_install_db #{opts.compact.join(" ")}") - mysql_install_db(opts.compact) - end + debug("Installing MySQL data directory with mysql_install_db #{opts.compact.join(' ')}") + mysql_install_db(opts.compact) end - exists? + exists? end def destroy + # rubocop:disable Lint/UselessAssignment name = @resource[:name] - raise ArgumentError, "ERROR: Resource can not be removed" + # rubocop:enable Lint/UselessAssignment + raise ArgumentError, 'ERROR: Resource can not be removed' end def exists? datadir = @resource[:datadir] - (File.directory?("#{datadir}/mysql")) && (Dir.entries("#{datadir}/mysql") - %w{ . .. }).any? + File.directory?("#{datadir}/mysql") && (Dir.entries("#{datadir}/mysql") - %w[. ..]).any? end ## @@ -74,5 +74,4 @@ def exists? # Generates method for all properties of the property_hash mk_resource_methods - end diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb index e3e3630b0..16e988f89 100644 --- a/lib/puppet/provider/mysql_grant/mysql.rb +++ b/lib/puppet/provider/mysql_grant/mysql.rb @@ -1,79 +1,78 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql')) -Puppet::Type.type(:mysql_grant).provide(:mysql, :parent => Puppet::Provider::Mysql) do - +Puppet::Type.type(:mysql_grant).provide(:mysql, parent: Puppet::Provider::Mysql) do desc 'Set grants for users in MySQL.' def self.instances instances = [] - users.collect do |user| - user_string = self.cmd_user(user) + users.map do |user| + user_string = cmd_user(user) query = "SHOW GRANTS FOR #{user_string};" begin - grants = mysql([defaults_file, "-NBe", query].compact) + grants = mysql([defaults_file, '-NBe', query].compact) rescue Puppet::ExecutionFailure => e # Silently ignore users with no grants. Can happen e.g. if user is # defined with fqdn and server is run with skip-name-resolve. Example: # 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. - if e.inspect =~ /There is no such grant defined for user/ - next - else - raise Puppet::Error, "#mysql had an error -> #{e.inspect}" - end + next if e.inspect =~ %r{There is no such grant defined for user} + raise Puppet::Error, "#mysql had an error -> #{e.inspect}" end # Once we have the list of grants generate entries for each. grants.each_line do |grant| # Match the munges we do in the type. - munged_grant = grant.delete("'").delete("`").delete('"') + munged_grant = grant.delete("'").delete('`').delete('"') # Matching: GRANT (SELECT, UPDATE) PRIVILEGES ON (*.*) TO ('root')@('127.0.0.1') (WITH GRANT OPTION) - if match = munged_grant.match(/^GRANT\s(.+)\sON\s(.+)\sTO\s(.*)@(.*?)(\s.*)?$/) - privileges, table, user, host, rest = match.captures - table.gsub!('\\\\', '\\') - - # split on ',' if it is not a non-'('-containing string followed by a - # closing parenthesis ')'-char - e.g. only split comma separated elements not in - # parentheses - stripped_privileges = privileges.strip.split(/\s*,\s*(?![^(]*\))/).map do |priv| - # split and sort the column_privileges in the parentheses and rejoin - if priv.include?('(') - type, col=priv.strip.split(/\s+|\b/,2) - type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")" - else - # Once we split privileges up on the , we need to make sure we - # shortern ALL PRIVILEGES to just all. - priv == 'ALL PRIVILEGES' ? 'ALL' : priv.strip - end - end - # Same here, but to remove OPTION leaving just GRANT. - if rest.match(/WITH\sGRANT\sOPTION/) - options = ['GRANT'] + # rubocop:disable Lint/AssignmentInCondition + next unless match = munged_grant.match(%r{^GRANT\s(.+)\sON\s(.+)\sTO\s(.*)@(.*?)(\s.*)?$}) + # rubocop:enable Lint/AssignmentInCondition + privileges, table, user, host, rest = match.captures + table.gsub!('\\\\', '\\') + + # split on ',' if it is not a non-'('-containing string followed by a + # closing parenthesis ')'-char - e.g. only split comma separated elements not in + # parentheses + stripped_privileges = privileges.strip.split(%r{\s*,\s*(?![^(]*\))}).map do |priv| + # 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(', ') + ')' else - options = ['NONE'] + # Once we split privileges up on the , we need to make sure we + # shortern ALL PRIVILEGES to just all. + (priv == 'ALL PRIVILEGES') ? 'ALL' : priv.strip end - # fix double backslash that MySQL prints, so resources match - table.gsub!("\\\\", "\\") - # We need to return an array of instances so capture these - instances << new( - :name => "#{user}@#{host}/#{table}", - :ensure => :present, - :privileges => stripped_privileges.sort, - :table => table, - :user => "#{user}@#{host}", - :options => options - ) end + # Same here, but to remove OPTION leaving just GRANT. + options = if rest =~ %r{WITH\sGRANT\sOPTION} + ['GRANT'] + else + ['NONE'] + end + # fix double backslash that MySQL prints, so resources match + table.gsub!('\\\\', '\\') + # We need to return an array of instances so capture these + instances << new( + name: "#{user}@#{host}/#{table}", + ensure: :present, + privileges: stripped_privileges.sort, + table: table, + user: "#{user}@#{host}", + options: options, + ) end end - return instances + instances end def self.prefetch(resources) users = instances resources.keys.each do |name| + # rubocop:disable Lint/AssignmentInCondition if provider = users.find { |user| user.name == name } resources[name].provider = provider end + # rubocop:enable Lint/AssignmentInCondition end end @@ -109,7 +108,7 @@ def revoke(user, table, revoke_privileges = ['ALL']) # if no ON clause is used. # It hast to be executed before "REVOKE ALL [..]" since a GRANT has to # exist to be executed successfully - if revoke_privileges.include? 'ALL' and !revoke_privileges.include?('PROXY') + if revoke_privileges.include?('ALL') && !revoke_privileges.include?('PROXY') query = "REVOKE GRANT OPTION ON #{table_string} FROM #{user_string}" mysql([defaults_file, system_database, '-e', query].compact) end @@ -144,7 +143,7 @@ def flush mk_resource_methods def diff_privileges(privileges_old, privileges_new) - diff = {:revoke => Array.new, :grant => Array.new} + diff = { revoke: [], grant: [] } if privileges_old.include? 'ALL' diff[:revoke] = privileges_old diff[:grant] = privileges_new @@ -154,15 +153,15 @@ def diff_privileges(privileges_old, privileges_new) diff[:revoke] = privileges_old - privileges_new diff[:grant] = privileges_new - privileges_old end - return diff + diff end def privileges=(privileges) diff = diff_privileges(@property_hash[:privileges], privileges) - if not diff[:revoke].empty? + unless diff[:revoke].empty? revoke(@property_hash[:user], @property_hash[:table], diff[:revoke]) end - if not diff[:grant].empty? + unless diff[:grant].empty? grant(@property_hash[:user], @property_hash[:table], diff[:grant], @property_hash[:options]) end @property_hash[:privileges] = privileges @@ -176,5 +175,4 @@ def options=(options) self.options end - end diff --git a/lib/puppet/provider/mysql_plugin/mysql.rb b/lib/puppet/provider/mysql_plugin/mysql.rb index 2cb640bd8..febdd436c 100644 --- a/lib/puppet/provider/mysql_plugin/mysql.rb +++ b/lib/puppet/provider/mysql_plugin/mysql.rb @@ -1,16 +1,15 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql')) -Puppet::Type.type(:mysql_plugin).provide(:mysql, :parent => Puppet::Provider::Mysql) do +Puppet::Type.type(:mysql_plugin).provide(:mysql, parent: Puppet::Provider::Mysql) do desc 'Manages MySQL plugins.' - commands :mysql => 'mysql' + commands mysql: 'mysql' def self.instances - mysql([defaults_file, '-NBe', 'show plugins'].compact).split("\n").collect do |line| - name, status, type, library, license = line.split(/\t/) - new(:name => name, - :ensure => :present, - :soname => library - ) + mysql([defaults_file, '-NBe', 'show plugins'].compact).split("\n").map do |line| + name, _status, _type, library, _license = line.split(%r{\t}) + new(name: name, + ensure: :present, + soname: library) end end @@ -19,19 +18,21 @@ def self.instances def self.prefetch(resources) plugins = instances resources.keys.each do |plugin| + # rubocop:disable Lint/AssignmentInCondition if provider = plugins.find { |pl| pl.name == plugin } resources[plugin].provider = provider end + # rubocop:enable Lint/AssignmentInCondition end end 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]) mysql([defaults_file, '-NBe', "install plugin #{@resource[:name]} soname '#{soname}'"].compact) - @property_hash[:ensure] = :present + @property_hash[:ensure] = :present @property_hash[:soname] = @resource[:soname] exists? ? (return true) : (return false) @@ -49,5 +50,4 @@ def exists? end mk_resource_methods - end diff --git a/lib/puppet/provider/mysql_user/mysql.rb b/lib/puppet/provider/mysql_user/mysql.rb index 6b12af517..70181d486 100644 --- a/lib/puppet/provider/mysql_user/mysql.rb +++ b/lib/puppet/provider/mysql_user/mysql.rb @@ -1,42 +1,39 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql')) -Puppet::Type.type(:mysql_user).provide(:mysql, :parent => Puppet::Provider::Mysql) do - +Puppet::Type.type(:mysql_user).provide(:mysql, parent: Puppet::Provider::Mysql) do desc 'manage users for a mysql database.' - commands :mysql => 'mysql' + commands mysql: 'mysql' # Build a property_hash containing all the discovered information about MySQL # users. def self.instances users = mysql([defaults_file, '-NBe', - "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"].compact).split("\n") + "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"].compact).split("\n") # To reduce the number of calls to MySQL we collect all the properties in # one big swoop. - users.collect do |name| + users.map do |name| if mysqld_version.nil? ## Default ... + # rubocop:disable Metrics/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 (mysqld_type == 'mysql' || mysqld_type == 'percona') && Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0 + 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}'" else - if (mysqld_type == "mysql" or mysqld_type == "percona") and Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0 - 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}'" - 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 + 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 = mysql([defaults_file, "-NBe", query].compact).split(/\s/) + @password, @plugin = mysql([defaults_file, '-NBe', query].compact).split(%r{\s}) @tls_options = parse_tls_options(ssl_type, ssl_cipher, x509_issuer, x509_subject) - - new(:name => name, - :ensure => :present, - :password_hash => @password, - :plugin => @plugin, - :max_user_connections => @max_user_connections, - :max_connections_per_hour => @max_connections_per_hour, - :max_queries_per_hour => @max_queries_per_hour, - :max_updates_per_hour => @max_updates_per_hour, - :tls_options => @tls_options - ) + # rubocop:enable Metrics/LineLength + new(name: name, + ensure: :present, + password_hash: @password, + plugin: @plugin, + max_user_connections: @max_user_connections, + max_connections_per_hour: @max_connections_per_hour, + max_queries_per_hour: @max_queries_per_hour, + max_updates_per_hour: @max_updates_per_hour, + tls_options: @tls_options) end end @@ -44,11 +41,13 @@ def self.instances # the contents of the property_hash generated by self.instances def self.prefetch(resources) users = instances + # rubocop:disable Lint/AssignmentInCondition resources.keys.each do |name| if provider = users.find { |user| user.name == name } resources[name].provider = provider end end + # rubocop:enable Lint/AssignmentInCondition end def create @@ -64,7 +63,7 @@ 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 plugin == 'sha256_password' and !password_hash.nil? + if plugin == 'sha256_password' && !password_hash.nil? mysql([defaults_file, system_database, '-e', "CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}' AS '#{password_hash}'"].compact) else mysql([defaults_file, system_database, '-e', "CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}'"].compact) @@ -76,15 +75,17 @@ def create @property_hash[:ensure] = :present @property_hash[:password_hash] = password_hash end + # rubocop:disable Metrics/LineLength mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO '#{merged_name}' WITH MAX_USER_CONNECTIONS #{max_user_connections} MAX_CONNECTIONS_PER_HOUR #{max_connections_per_hour} MAX_QUERIES_PER_HOUR #{max_queries_per_hour} MAX_UPDATES_PER_HOUR #{max_updates_per_hour}"].compact) + # rubocop:enable Metrics/LineLength @property_hash[:max_user_connections] = max_user_connections @property_hash[:max_connections_per_hour] = max_connections_per_hour @property_hash[:max_queries_per_hour] = max_queries_per_hour @property_hash[:max_updates_per_hour] = max_updates_per_hour merged_tls_options = tls_options.join(' AND ') - if (((mysqld_type == "mysql" or mysqld_type == "percona") and Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0) or - (mysqld_type == 'mariadb' and Puppet::Util::Package.versioncmp(mysqld_version, '10.2.0') >= 0)) + if ((mysqld_type == 'mysql' || mysqld_type == 'percona') && Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0) || + (mysqld_type == 'mariadb' && Puppet::Util::Package.versioncmp(mysqld_version, '10.2.0') >= 0) mysql([defaults_file, system_database, '-e', "ALTER USER '#{merged_name}' REQUIRE #{merged_tls_options}"].compact) else mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO '#{merged_name}' REQUIRE #{merged_tls_options}"].compact) @@ -120,78 +121,70 @@ def password_hash=(string) if mysqld_version.nil? # default ... if mysqld_version does not work mysql([defaults_file, system_database, '-e', "SET PASSWORD FOR #{merged_name} = '#{string}'"].compact) + elsif (mysqld_type == 'mysql' || mysqld_type == 'percona') && Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0 + raise ArgumentError, 'Only mysql_native_password (*ABCD...XXX) hashes are supported' unless string =~ %r{^\*} + mysql([defaults_file, system_database, '-e', "ALTER USER #{merged_name} IDENTIFIED WITH mysql_native_password AS '#{string}'"].compact) else - # Version >= 5.7.6 (many password related changes) - if (mysqld_type == "mysql" or mysqld_type == "percona") and Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0 - if string.match(/^\*/) - mysql([defaults_file, system_database, '-e', "ALTER USER #{merged_name} IDENTIFIED WITH mysql_native_password AS '#{string}'"].compact) - else - raise ArgumentError, "Only mysql_native_password (*ABCD...XXX) hashes are supported" - end - else - # older versions - mysql([defaults_file, system_database, '-e', "SET PASSWORD FOR #{merged_name} = '#{string}'"].compact) - end + mysql([defaults_file, system_database, '-e', "SET PASSWORD FOR #{merged_name} = '#{string}'"].compact) end - password_hash == string ? (return true) : (return false) + (password_hash == string) ? (return true) : (return false) end def max_user_connections=(int) merged_name = self.class.cmd_user(@resource[:name]) mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_USER_CONNECTIONS #{int}"].compact).chomp - max_user_connections == int ? (return true) : (return false) + (max_user_connections == int) ? (return true) : (return false) end def max_connections_per_hour=(int) merged_name = self.class.cmd_user(@resource[:name]) mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_CONNECTIONS_PER_HOUR #{int}"].compact).chomp - max_connections_per_hour == int ? (return true) : (return false) + (max_connections_per_hour == int) ? (return true) : (return false) end def max_queries_per_hour=(int) merged_name = self.class.cmd_user(@resource[:name]) mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_QUERIES_PER_HOUR #{int}"].compact).chomp - max_queries_per_hour == int ? (return true) : (return false) + (max_queries_per_hour == int) ? (return true) : (return false) end def max_updates_per_hour=(int) merged_name = self.class.cmd_user(@resource[:name]) mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_UPDATES_PER_HOUR #{int}"].compact).chomp - max_updates_per_hour == int ? (return true) : (return false) + (max_updates_per_hour == int) ? (return true) : (return false) end def tls_options=(array) merged_name = self.class.cmd_user(@resource[:name]) merged_tls_options = array.join(' AND ') - if (((mysqld_type == "mysql" or mysqld_type == "percona") and Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0) or - (mysqld_type == 'mariadb' and Puppet::Util::Package.versioncmp(mysqld_version, '10.2.0') >= 0)) + if ((mysqld_type == 'mysql' || mysqld_type == 'percona') && Puppet::Util::Package.versioncmp(mysqld_version, '5.7.6') >= 0) || + (mysqld_type == 'mariadb' && Puppet::Util::Package.versioncmp(mysqld_version, '10.2.0') >= 0) mysql([defaults_file, system_database, '-e', "ALTER USER #{merged_name} REQUIRE #{merged_tls_options}"].compact) else mysql([defaults_file, system_database, '-e', "GRANT USAGE ON *.* TO #{merged_name} REQUIRE #{merged_tls_options}"].compact) end - tls_options == array ? (return true) : (return false) + (tls_options == array) ? (return true) : (return false) end def self.parse_tls_options(ssl_type, ssl_cipher, x509_issuer, x509_subject) if ssl_type == 'ANY' - return ['SSL'] + ['SSL'] elsif ssl_type == 'X509' - return ['X509'] + ['X509'] elsif ssl_type == 'SPECIFIED' options = [] - options << "CIPHER #{ssl_cipher}" if not ssl_cipher.nil? and not ssl_cipher.empty? - options << "ISSUER #{x509_issuer}" if not x509_issuer.nil? and not x509_issuer.empty? - options << "SUBJECT #{x509_subject}" if not x509_subject.nil? and not x509_subject.empty? - return options + options << "CIPHER #{ssl_cipher}" if !ssl_cipher.nil? && !ssl_cipher.empty? + options << "ISSUER #{x509_issuer}" if !x509_issuer.nil? && !x509_issuer.empty? + options << "SUBJECT #{x509_subject}" if !x509_subject.nil? && !x509_subject.empty? + options else - return ['NONE'] + ['NONE'] end end - end diff --git a/lib/puppet/type/mysql_database.rb b/lib/puppet/type/mysql_database.rb index 1f94d5f88..f8b940650 100644 --- a/lib/puppet/type/mysql_database.rb +++ b/lib/puppet/type/mysql_database.rb @@ -6,20 +6,19 @@ autorequire(:file) { '/root/.my.cnf' } autorequire(:class) { 'mysql::server' } - newparam(:name, :namevar => true) do + newparam(:name, namevar: true) do desc 'The name of the MySQL database to manage.' end newproperty(:charset) do desc 'The CHARACTER SET setting for the database' defaultto :utf8 - newvalue(/^\S+$/) + newvalue(%r{^\S+$}) end newproperty(:collate) do desc 'The COLLATE setting for the database' defaultto :utf8_general_ci - newvalue(/^\S+$/) + newvalue(%r{^\S+$}) end - end diff --git a/lib/puppet/type/mysql_datadir.rb b/lib/puppet/type/mysql_datadir.rb index 367767def..61a4fdf82 100644 --- a/lib/puppet/type/mysql_datadir.rb +++ b/lib/puppet/type/mysql_datadir.rb @@ -5,13 +5,13 @@ autorequire(:package) { 'mysql-server' } - newparam(:datadir, :namevar => true) do - desc "The datadir name" + newparam(:datadir, namevar: true) do + desc 'The datadir name' end newparam(:basedir) do desc 'The basedir name, default /usr.' - newvalues(/^\//) + newvalues(%r{^/}) end newparam(:user) do @@ -19,17 +19,16 @@ end newparam(:defaults_extra_file) do - desc "MySQL defaults-extra-file with absolute path (*.cnf)." - newvalues(/^\/.*\.cnf$/) + desc 'MySQL defaults-extra-file with absolute path (*.cnf).' + newvalues(%r{^\/.*\.cnf$}) end - newparam(:insecure, :boolean => true) do - desc "Insecure initialization (needed for 5.7.6++)." + newparam(:insecure, boolean: true) do + desc 'Insecure initialization (needed for 5.7.6++).' end newparam(:log_error) do - desc "The path to the mysqld error log file (used with the --log-error option)" - newvalues(/^\//) + desc 'The path to the mysqld error log file (used with the --log-error option)' + newvalues(%r{^\/}) end - end diff --git a/lib/puppet/type/mysql_grant.rb b/lib/puppet/type/mysql_grant.rb index 1d7f3eb86..c936a9a2f 100644 --- a/lib/puppet/type/mysql_grant.rb +++ b/lib/puppet/type/mysql_grant.rb @@ -12,34 +12,35 @@ 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 and Array(self[:privileges]).count > 1 and self[:privileges].to_s.include?('ALL') + if self[:ensure] == :present && Array(self[:privileges]).count > 1 && self[:privileges].to_s.include?('ALL') self[:privileges] = 'ALL' end # 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. - self[:privileges] = Array(self[:privileges]).map{ |priv| - # split and sort the column_privileges in the parentheses and rejoin - if priv.include?('(') - type, col=priv.strip.split(/\s+|\b/,2) - type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")" - else - priv.strip.upcase - end - }.uniq.reject{|k| k == 'GRANT' or k == 'GRANT OPTION'}.sort! + # rubocop:disable Style/MultilineBlockChain + self[:privileges] = Array(self[:privileges]).map { |priv| + # 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(', ') + ')' + else + priv.strip.upcase + end + }.uniq.reject { |k| k == 'GRANT' || k == 'GRANT OPTION' }.sort! end - + # rubocop:enable Style/MultilineBlockChain validate do - fail('privileges parameter is required.') if self[:ensure] == :present and self[:privileges].nil? - fail('PROXY must be the only privilege specified.') if Array(self[:privileges]).count > 1 and Array(self[:privileges]).include?('PROXY') - fail('table parameter is required.') if self[:ensure] == :present and self[:table].nil? - fail('user parameter is required.') if self[:ensure] == :present and self[:user].nil? - if self[:user] and self[:table] - fail('name must match user@host/table format') if self[:name] != "#{self[:user]}/#{self[:table]}" + raise('privileges parameter is required.') if self[:ensure] == :present && self[:privileges].nil? + raise('PROXY must be the only privilege specified.') if Array(self[:privileges]).count > 1 && Array(self[:privileges]).include?('PROXY') + raise('table parameter is required.') if self[:ensure] == :present && self[:table].nil? + raise('user parameter is required.') if self[:ensure] == :present && self[:user].nil? + if self[:user] && self[:table] + raise('name must match user@host/table format') if self[:name] != "#{self[:user]}/#{self[:table]}" end end - newparam(:name, :namevar => true) do + newparam(:name, namevar: true) do desc 'Name to describe the grant.' munge do |value| @@ -47,12 +48,12 @@ def initialize(*args) end end - newproperty(:privileges, :array_matching => :all) do + newproperty(:privileges, array_matching: :all) do desc 'Privileges for user' validate do |value| mysql_version = Facter.value(:mysql_version) - if value =~ /proxy/i and Puppet::Util::Package.versioncmp(mysql_version, '5.5.0') < 0 + if value =~ %r{proxy}i && Puppet::Util::Package.versioncmp(mysql_version, '5.5.0') < 0 raise(ArgumentError, "PROXY user not supported on mysql versions < 5.5.0. Current version #{mysql_version}") end end @@ -62,16 +63,14 @@ def initialize(*args) desc 'Table to apply privileges to.' validate do |value| - if Array(@resource[:privileges]).include?('PROXY') and !/^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$/.match(value) - raise(ArgumentError, '"table" for PROXY should be specified as proxy_user@proxy_host') - end + raise(ArgumentError, '"table" for PROXY should be specified as proxy_user@proxy_host') if Array(@resource[:privileges]).include?('PROXY') && !%r{^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$}.match(value) end munge do |value| - value.delete("`") + value.delete('`') end - newvalues(/.*\..*/,/^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$/) + newvalues(%r{.*\..*}, %r{^[0-9a-zA-Z$_]*@[\w%\.:\-\/]*$}) end newproperty(:user) do @@ -79,41 +78,38 @@ def initialize(*args) validate do |value| # http://dev.mysql.com/doc/refman/5.5/en/identifiers.html # If at least one special char is used, string must be quoted - # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827 - if matches = /^(['`"])((?!\1).)*\1@([\w%\.:\-\/]+)$/.match(value) + # rubocop:disable Lint/AssignmentInCondition + # rubocop:disable Lint/UselessAssignment + if matches = %r{^(['`"])((?!\1).)*\1@([\w%\.:\-\/]+)$}.match(value) user_part = matches[2] host_part = matches[3] - elsif matches = /^([0-9a-zA-Z$_]*)@([\w%\.:\-\/]+)$/.match(value) + elsif matches = %r{^([0-9a-zA-Z$_]*)@([\w%\.:\-\/]+)$}.match(value) user_part = matches[1] host_part = matches[2] - elsif matches = /^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$/.match(value) + elsif matches = %r{^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$}.match(value) user_part = matches[1] host_part = matches[2] else raise(ArgumentError, "Invalid database user #{value}") end - + # rubocop:enable Lint/AssignmentInCondition + # rubocop:enable Lint/UselessAssignment mysql_version = Facter.value(:mysql_version) unless mysql_version.nil? - if Puppet::Util::Package.versioncmp(mysql_version, '5.7.8') < 0 and user_part.size > 16 - raise(ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters') - elsif Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') < 0 and user_part.size > 32 - raise(ArgumentError, 'MySQL usernames are limited to a maximum of 32 characters') - elsif Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') > 0 and user_part.size > 80 - raise(ArgumentError, 'MySQL usernames are limited to a maximum of 80 characters') - end + 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 end end munge do |value| - matches = /^((['`"]?).*\2)@(.+)$/.match(value) + matches = %r{^((['`"]?).*\2)@(.+)$}.match(value) "#{matches[1]}@#{matches[3].downcase}" end end - newproperty(:options, :array_matching => :all) do + newproperty(:options, array_matching: :all) do desc 'Options to grant.' end - end diff --git a/lib/puppet/type/mysql_plugin.rb b/lib/puppet/type/mysql_plugin.rb index e8279209f..029220e18 100644 --- a/lib/puppet/type/mysql_plugin.rb +++ b/lib/puppet/type/mysql_plugin.rb @@ -5,13 +5,12 @@ autorequire(:file) { '/root/.my.cnf' } - newparam(:name, :namevar => true) do + newparam(:name, namevar: true) do desc 'The name of the MySQL plugin to manage.' end newproperty(:soname) do desc 'The name of the library' - newvalue(/^\w+\.\w+$/) + newvalue(%r{^\w+\.\w+$}) end - end diff --git a/lib/puppet/type/mysql_user.rb b/lib/puppet/type/mysql_user.rb index 831a531d3..361e8a3d7 100644 --- a/lib/puppet/type/mysql_user.rb +++ b/lib/puppet/type/mysql_user.rb @@ -7,99 +7,95 @@ autorequire(:file) { '/root/.my.cnf' } autorequire(:class) { 'mysql::server' } - newparam(:name, :namevar => true) do + newparam(:name, namevar: true) do desc "The name of the user. This uses the 'username@hostname' or username@hostname." validate do |value| # http://dev.mysql.com/doc/refman/5.5/en/identifiers.html # If at least one special char is used, string must be quoted - # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827 - if matches = /^(['`"])((?:(?!\1).)*)\1@([\w%\.:\-\/]+)$/.match(value) + mysql_version = Facter.value(:mysql_version) + # rubocop:disable Lint/AssignmentInCondition + # rubocop:disable Lint/UselessAssignment + if matches = %r{^(['`"])((?:(?!\1).)*)\1@([\w%\.:\-\/]+)$}.match(value) user_part = matches[2] host_part = matches[3] - elsif matches = /^([0-9a-zA-Z$_]*)@([\w%\.:\-\/]+)$/.match(value) + elsif matches = %r{^([0-9a-zA-Z$_]*)@([\w%\.:\-\/]+)$}.match(value) user_part = matches[1] host_part = matches[2] - elsif matches = /^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$/.match(value) + elsif matches = %r{^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$}.match(value) user_part = matches[1] host_part = matches[2] else raise(ArgumentError, "Invalid database user #{value}") end - - mysql_version = Facter.value(:mysql_version) + # rubocop:enable Lint/AssignmentInCondition + # rubocop:enable Lint/UselessAssignment unless mysql_version.nil? - if Puppet::Util::Package.versioncmp(mysql_version, '5.7.8') < 0 and user_part.size > 16 - raise(ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters') - elsif Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') < 0 and user_part.size > 32 - raise(ArgumentError, 'MySQL usernames are limited to a maximum of 32 characters') - elsif Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') > 0 and user_part.size > 80 - raise(ArgumentError, 'MySQL usernames are limited to a maximum of 80 characters') - end + 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 end end munge do |value| - matches = /^((['`"]?).*\2)@(.+)$/.match(value) + matches = %r{^((['`"]?).*\2)@(.+)$}.match(value) "#{matches[1]}@#{matches[3].downcase}" end end newproperty(:password_hash) do desc 'The password hash of the user. Use mysql_password() for creating such a hash.' - newvalue(/\w*/) + newvalue(%r{\w*}) end newproperty(:plugin) do desc 'The authentication plugin of the user.' - newvalue(/\w+/) + newvalue(%r{\w+}) end newproperty(:max_user_connections) do - desc "Max concurrent connections for the user. 0 means no (or global) limit." - newvalue(/\d+/) + desc 'Max concurrent connections for the user. 0 means no (or global) limit.' + newvalue(%r{\d+}) end newproperty(:max_connections_per_hour) do - desc "Max connections per hour for the user. 0 means no (or global) limit." - newvalue(/\d+/) + desc 'Max connections per hour for the user. 0 means no (or global) limit.' + newvalue(%r{\d+}) end newproperty(:max_queries_per_hour) do - desc "Max queries per hour for the user. 0 means no (or global) limit." - newvalue(/\d+/) + desc 'Max queries per hour for the user. 0 means no (or global) limit.' + newvalue(%r{\d+}) end newproperty(:max_updates_per_hour) do - desc "Max updates per hour for the user. 0 means no (or global) limit." - newvalue(/\d+/) + desc 'Max updates per hour for the user. 0 means no (or global) limit.' + newvalue(%r{\d+}) end - newproperty(:tls_options, :array_matching => :all) do - desc "Options to that set the TLS-related REQUIRE attributes for the user." + newproperty(:tls_options, array_matching: :all) do + desc 'Options to that set the TLS-related REQUIRE attributes for the user.' validate do |value| - value = [value] if not value.is_a?(Array) - if value.include? 'NONE' or value.include? 'SSL' or value.include? 'X509' + value = [value] unless value.is_a?(Array) + if value.include?('NONE') || value.include?('SSL') || value.include?('X509') if value.length > 1 - raise(ArgumentError, "REQUIRE tls options NONE, SSL and X509 cannot be used with other options, you may only use one of them.") + raise(ArgumentError, 'REQUIRE tls options NONE, SSL and X509 cannot be used with other options, you may only use one of them.') end else value.each do |opt| - if not o = opt.match(/^(CIPHER|ISSUER|SUBJECT)/i) - raise(ArgumentError, "Invalid tls option #{o}") - end + o = opt.match(%r{^(CIPHER|ISSUER|SUBJECT)}i) + raise(ArgumentError, "Invalid tls option #{o}") unless o end end end def insync?(is) # 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) and @should.is_a?(Array) + if is.is_a?(Array) && @should.is_a?(Array) is.sort == @should.sort else is == @should end end end - end diff --git a/spec/classes/graceful_failures_spec.rb b/spec/classes/graceful_failures_spec.rb index 9fb811786..d00090ee7 100644 --- a/spec/classes/graceful_failures_spec.rb +++ b/spec/classes/graceful_failures_spec.rb @@ -2,16 +2,14 @@ describe 'mysql::server' do context "on an unsupported OS" do - # fetch any sets of facts to modify them - os, facts = on_supported_os.first - - let(:facts) { - facts.merge({ - :osfamily => 'UNSUPPORTED', - :operatingsystem => 'UNSUPPORTED', - }) - } + let(:facts) do + { + :osfamily => 'UNSUPPORTED', + :operatingsystem => 'UNSUPPORTED' + } + end + it 'should gracefully fail' do is_expected.to compile.and_raise_error(/Unsupported platform:/) end