diff --git a/.fixtures.yml b/.fixtures.yml index 39cbdd00..b7af544a 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -3,7 +3,7 @@ fixtures: facts: 'https://github.com/puppetlabs/puppetlabs-facts.git' puppet_agent: repo: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' - ref: v4.12.1 + ref: v4.13.0 provision: 'https://github.com/puppetlabs/provision.git' stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' mount_iso: 'https://github.com/puppetlabs/puppetlabs-mount_iso.git' diff --git a/.github/workflows/auto_release.yml b/.github/workflows/auto_release.yml index ca677186..d6270c56 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/ci.yml b/.github/workflows/ci.yml index ac4d74b4..2d665b03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,10 @@ jobs: fail-fast: false matrix: ${{fromJson(needs.setup_matrix.outputs.matrix)}} + env: + PUPPET_GEM_VERSION: '~> 7.24' + FACTER_GEM_VERSION: 'https://github.com/puppetlabs/facter#main' + steps: - name: Checkout Source uses: actions/checkout@v2 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c560300b..4a2c7cae 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -55,6 +55,10 @@ jobs: fail-fast: false matrix: ${{fromJson(needs.setup_matrix.outputs.matrix)}} + env: + PUPPET_GEM_VERSION: '~> 7.24' + FACTER_GEM_VERSION: 'https://github.com/puppetlabs/facter#main' + steps: - name: Checkout Source uses: actions/checkout@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 82caec76..0b7b8a05 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 a886d8db..e365cd83 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.6' Include: - "**/*.rb" Exclude: @@ -18,7 +23,6 @@ AllCops: - "**/Puppetfile" - "**/Vagrantfile" - "**/Guardfile" -inherit_from: ".rubocop_todo.yml" Layout/LineLength: Description: People have wide screens, use them. Max: 200 @@ -80,441 +84,7 @@ 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 +# RSpec/MultipleExpectations: +# Max: 3 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 + AllowedNames: 'is' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 5b57cce5..9fbaf4aa 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,24 +1,95 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2020-12-17 20:22:52 UTC using RuboCop version 1.6.1. +# on 2023-04-25 10:15:50 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 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/functions/sqlserver_upcase_spec.rb' + +# Offense count: 7 +# Configuration parameters: AllowComments, AllowEmptyLambdas. +Lint/EmptyBlock: + Exclude: + - 'lib/puppet/type/sqlserver_instance.rb' + - 'lib/puppet_x/sqlserver/features.rb' + - 'spec/defines/manifest_shared_examples.rb' + - 'spec/functions/functions_shared_examples.rb' + # Offense count: 3 -# Configuration parameters: AllowComments. +# Configuration parameters: AllowComments, AllowNil. Lint/SuppressedException: Exclude: - 'lib/puppet_x/sqlserver/features.rb' - 'lib/puppet_x/sqlserver/sql_connection.rb' +# Offense count: 16 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 36 + +# Offense count: 5 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 158 + # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect. -Performance/StringInclude: +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 158 + +# Offense count: 10 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 12 + +# Offense count: 39 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 41 + +# Offense count: 10 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 13 + +# Offense count: 12 +# Configuration parameters: ForbiddenDelimiters. +# ForbiddenDelimiters: (?i-mx:(^|\s)(EO[A-Z]{1}|END)(\s|$)) +Naming/HeredocDelimiterNaming: Exclude: - - 'lib/puppet/provider/sqlserver_tsql/mssql.rb' + - 'lib/puppet/type/sqlserver_tsql.rb' + - 'spec/defines/database_spec.rb' + - 'spec/defines/login/permissions_spec.rb' + - 'spec/defines/login_spec.rb' + - 'spec/defines/sp_configure_spec.rb' + - 'spec/defines/user/permissions_spec.rb' + - 'spec/defines/user_spec.rb' + - 'spec/spec_helper_acceptance_local.rb' + - 'spec/sql_testing_helpers.rb' + +# Offense count: 66 +# Configuration parameters: Prefixes, AllowedPatterns. +# Prefixes: when, with, without +RSpec/ContextWording: + Enabled: false + +# Offense count: 28 +# Configuration parameters: IgnoredMetadata. +RSpec/DescribeClass: + Enabled: false + +# Offense count: 51 +# Configuration parameters: CountAsOne. +RSpec/ExampleLength: + Max: 59 # Offense count: 2 # Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly. @@ -28,7 +99,7 @@ RSpec/FilePath: - 'spec/unit/puppet_x/server_helper_spec.rb' - 'spec/unit/puppet_x/sql_connection_spec.rb' -# Offense count: 301 +# Offense count: 302 # Configuration parameters: AssignmentOnly. RSpec/InstanceVariable: Exclude: @@ -46,10 +117,84 @@ RSpec/InstanceVariable: - 'spec/unit/puppet/type/sqlserver_instance_spec.rb' - 'spec/unit/puppet_x/sql_connection_spec.rb' -# Offense count: 17 -# Configuration parameters: IgnoreSharedExamples. +# Offense count: 1 +RSpec/LeakyConstantDeclaration: + Exclude: + - 'spec/functions/sqlserver_upcase_spec.rb' + +# Offense count: 22 +RSpec/MultipleExpectations: + Max: 8 + +# Offense count: 10 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 10 + +# Offense count: 31 +# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. +# SupportedStyles: always, named_only RSpec/NamedSubject: Exclude: + - 'spec/defines/config_spec.rb' + - 'spec/defines/database_spec.rb' + - 'spec/defines/login_spec.rb' + - 'spec/defines/role/permissions_spec.rb' + - 'spec/defines/role_spec.rb' + - 'spec/defines/sp_configure_spec.rb' + - 'spec/defines/user_spec.rb' + - 'spec/unit/puppet_x/sql_connection_spec.rb' + +# Offense count: 31 +# Configuration parameters: AllowedGroups. +RSpec/NestedGroups: + Max: 4 + +# Offense count: 70 +# Configuration parameters: AllowedPatterns. +# AllowedPatterns: ^expect_, ^assert_ +RSpec/NoExpectationExample: + Exclude: + - 'spec/acceptance/sqlserver_config_spec.rb' + - 'spec/acceptance/sqlserver_database_spec.rb' + - 'spec/acceptance/sqlserver_instance_spec.rb' + - 'spec/acceptance/sqlserver_login_spec.rb' + - 'spec/acceptance/sqlserver_role_spec.rb' + - 'spec/acceptance/sqlserver_tsql_spec.rb' + - 'spec/acceptance/sqlserver_user_spec.rb' + - 'spec/acceptance/z_last_sqlserver_features_spec.rb' + - 'spec/functions/sqlserver_upcase_spec.rb' + - 'spec/functions/sqlserver_validate_size_spec.rb' + - 'spec/unit/puppet/provider/sqlserver_features_spec.rb' + - 'spec/unit/puppet/provider/sqlserver_instance_spec.rb' + - 'spec/unit/puppet/provider/sqlserver_tsql_spec.rb' + - 'spec/unit/puppet/type/sqlserver_instance_spec.rb' + - 'spec/unit/puppet_x/server_helper_spec.rb' + +# Offense count: 4 +RSpec/RepeatedExampleGroupBody: + Exclude: + - 'spec/defines/login/permissions_spec.rb' + - 'spec/defines/user/permissions_spec.rb' + +# Offense count: 4 +RSpec/RepeatedExampleGroupDescription: + Exclude: + - 'spec/defines/config_spec.rb' + - 'spec/unit/puppet/provider/sqlserver_features_spec.rb' + +# Offense count: 7 +RSpec/StubbedMock: + Exclude: + - 'spec/unit/puppet/provider/sqlserver_features_spec.rb' + - 'spec/unit/puppet/provider/sqlserver_instance_spec.rb' + - 'spec/unit/puppet/provider/sqlserver_tsql_spec.rb' + - 'spec/unit/puppet_x/sql_connection_spec.rb' + +# Offense count: 2 +RSpec/SubjectDeclaration: + Exclude: + - 'spec/unit/puppet_x/server_helper_spec.rb' - 'spec/unit/puppet_x/sql_connection_spec.rb' # Offense count: 6 @@ -58,16 +203,29 @@ RSpec/SubjectStub: - 'spec/unit/puppet_x/server_helper_spec.rb' - 'spec/unit/puppet_x/sql_connection_spec.rb' +# Offense count: 4 +RSpec/UnspecifiedException: + Exclude: + - 'spec/functions/sqlserver_validate_hash_uniq_values_spec.rb' + - 'spec/functions/sqlserver_validate_instance_name_spec.rb' + # Offense count: 2 # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: Exclude: - 'spec/unit/puppet_x/sql_connection_spec.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, AllowInnerSlashes. -# SupportedStyles: slashes, percent_r, mixed -Style/RegexpLiteral: +# Offense count: 7 +Security/Open: Exclude: - - 'spec/defines/user_spec.rb' + - 'lib/puppet_x/sqlserver/features.rb' + - 'lib/puppet_x/sqlserver/sql_connection.rb' + +# Offense count: 3 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: + Exclude: + - 'lib/puppet/provider/sqlserver_instance/mssql.rb' + - 'lib/puppet/type/sqlserver_tsql.rb' + - 'spec/defines/manifest_shared_examples.rb' diff --git a/.sync.yml b/.sync.yml index 505552ce..9a7be77a 100644 --- a/.sync.yml +++ b/.sync.yml @@ -33,3 +33,5 @@ spec/spec_helper.rb: unmanaged: false .travis.yml: delete: true +.rubocop.yml: + unmanaged: true diff --git a/Gemfile b/Gemfile index 8298eb74..2f7e2ff7 100644 --- a/Gemfile +++ b/Gemfile @@ -26,13 +26,13 @@ group :development do 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 "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.6.1', require: false - gem "rubocop-performance", '= 1.9.1', require: false - gem "rubocop-rspec", '= 2.0.1', 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 "ruby-pwsh", require: false gem "github_changelog_generator", '= 1.15.2', require: false diff --git a/Rakefile b/Rakefile index 0f8754eb..53152e21 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/puppet/parser/functions/sqlserver_is_domain_or_local_user.rb b/lib/puppet/parser/functions/sqlserver_is_domain_or_local_user.rb index dd78a1ed..3c95afb0 100644 --- a/lib/puppet/parser/functions/sqlserver_is_domain_or_local_user.rb +++ b/lib/puppet/parser/functions/sqlserver_is_domain_or_local_user.rb @@ -4,9 +4,8 @@ module Puppet::Parser::Functions newfunction(:sqlserver_is_domain_or_local_user, type: :rvalue, doc: '@return [Boolean] Returns true is the username is for local/domain.') do |args| - if args.length != 1 - raise Puppet::ParseError, "is_domain_or_local_user(): requires exactly 1 argument, you provided #{args.length}" - end + raise Puppet::ParseError, "is_domain_or_local_user(): requires exactly 1 argument, you provided #{args.length}" if args.length != 1 + PuppetX::Sqlserver::ServerHelper.is_domain_or_local_user?(args[0], Facter.value(:hostname)) end end diff --git a/lib/puppet/parser/functions/sqlserver_validate_hash_uniq_values.rb b/lib/puppet/parser/functions/sqlserver_validate_hash_uniq_values.rb index 2d87e53d..1fdc7200 100644 --- a/lib/puppet/parser/functions/sqlserver_validate_hash_uniq_values.rb +++ b/lib/puppet/parser/functions/sqlserver_validate_hash_uniq_values.rb @@ -15,7 +15,7 @@ module Puppet::Parser::Functions total_count = value.count uniq_count = value.uniq.count - msg = (arguments[1]) ? arguments[1] : "Duplicate values passed to hash #{value}" + msg = arguments[1] || "Duplicate values passed to hash #{value}" raise(Puppet::ParseError, msg) if uniq_count != total_count end end diff --git a/lib/puppet/parser/functions/sqlserver_validate_instance_name.rb b/lib/puppet/parser/functions/sqlserver_validate_instance_name.rb index ebb1341b..dd869279 100644 --- a/lib/puppet/parser/functions/sqlserver_validate_instance_name.rb +++ b/lib/puppet/parser/functions/sqlserver_validate_instance_name.rb @@ -16,23 +16,16 @@ # http://msdn.microsoft.com/en-us/library/ms143531(v=sql.120).aspx module Puppet::Parser::Functions newfunction(:sqlserver_validate_instance_name, doc: '@return Error if not a valid instance name.') do |args| - if args.length != 1 - raise Puppet::ParseError, "mssql_validate_instance_name(): requires exactly 1 argument, you provided #{args.length}" - end + raise Puppet::ParseError, "mssql_validate_instance_name(): requires exactly 1 argument, you provided #{args.length}" if args.length != 1 + value = args[0] errors = [] - if value.empty? - errors << 'Instance name must be between 1 to 16 characters' - end - if value.length > 16 - errors << "Instance name can not be larger than 16 characters, you provided #{value}" - end - if %r{\\|\:|;|\,|\@|\'|\s|\&}.match?(value) + errors << 'Instance name must be between 1 to 16 characters' if value.empty? + errors << "Instance name can not be larger than 16 characters, you provided #{value}" if value.length > 16 + if %r{\\|:|;|,|@|'|\s|&}.match?(value) errors << "Instance name can not contain whitespaces, backslashes(\\), commas(,), colons(:), semi-colons(;), at symbols (@), single quotes(') or ampersand(&) sybmols, you provided '#{value}'" end - if %r{^_|_$}.match?(value) - errors << "Instance name can not start or end with underscore (_), you provided #{value}" - end + errors << "Instance name can not start or end with underscore (_), you provided #{value}" if %r{^_|_$}.match?(value) raise Puppet::ParseError, errors.join("\n") unless errors.empty? end end diff --git a/lib/puppet/parser/functions/sqlserver_validate_range.rb b/lib/puppet/parser/functions/sqlserver_validate_range.rb index f9d79429..8966e2f3 100644 --- a/lib/puppet/parser/functions/sqlserver_validate_range.rb +++ b/lib/puppet/parser/functions/sqlserver_validate_range.rb @@ -2,17 +2,15 @@ module Puppet::Parser::Functions newfunction(:sqlserver_validate_range, doc: '@return Error if value is not between range') do |args| - if (args.length < 3) || (args.length > 4) - raise Puppet::ParseError, "validate_range(): wrong number of arguments (#{args.length}; must be 3)" - end + raise Puppet::ParseError, "validate_range(): wrong number of arguments (#{args.length}; must be 3)" if (args.length < 3) || (args.length > 4) + values, lower, upper, msg = args values = [] << values unless values.is_a?(Array) values.each do |value| msg ||= "validate_range(): #{args[0].inspect} is not between #{args[1].inspect} and #{args[2].inspect}" - if value.is_a? Numeric - elsif %r{^\d+(|\.\d+)$}.match?(value) + if %r{^\d+(|\.\d+)$}.match?(value) raise(Puppet::ParseError, msg) unless Float(value).between?(Float(lower), Float(upper)) else value.strip! diff --git a/lib/puppet/parser/functions/sqlserver_validate_size.rb b/lib/puppet/parser/functions/sqlserver_validate_size.rb index 8dc8929b..df6ecb15 100644 --- a/lib/puppet/parser/functions/sqlserver_validate_size.rb +++ b/lib/puppet/parser/functions/sqlserver_validate_size.rb @@ -2,19 +2,12 @@ module Puppet::Parser::Functions newfunction(:sqlserver_validate_size, doc: '@return Error if not a valid size value') do |args| - if args.length != 1 - raise(Puppet::ParseError, "mssql_validate_size(): requires exactly 1 argument, you provided #{args.length}") - end + raise(Puppet::ParseError, "mssql_validate_size(): requires exactly 1 argument, you provided #{args.length}") if args.length != 1 + value = args[0] match = %r{^(?\d+)(?KB|MB|GB|TB)$}.match(value) - if match - if Integer(match[:size]) > 2_147_483_647 - raise(Puppet::ParseError, "Please use larger measurement for values greater than 2147483647, you provided #{value}") - end - end - if %r{\.}.match?(value) - raise(Puppet::ParseError, "Number must be an integer, you provided #{value}") - end + raise(Puppet::ParseError, "Please use larger measurement for values greater than 2147483647, you provided #{value}") if match && (Integer(match[:size]) > 2_147_483_647) + raise(Puppet::ParseError, "Number must be an integer, you provided #{value}") if value.include?('.') end end diff --git a/lib/puppet/property/sqlserver_login.rb b/lib/puppet/property/sqlserver_login.rb index a3bb692e..7b508b98 100644 --- a/lib/puppet/property/sqlserver_login.rb +++ b/lib/puppet/property/sqlserver_login.rb @@ -9,9 +9,8 @@ class Puppet::Property::SqlserverLogin < Puppet::Property # rubocop:disable Styl # value.length > 1 # does not contain two back slashes, contains no forward slashes # Determine what characters are valid for SQLLogin vs Domain Logins - if %r{\\.*\\}.match?(value) - raise 'More than one \ found, maximum of one for users is allowed' - end + raise 'More than one \ found, maximum of one for users is allowed' if %r{\\.*\\}.match?(value) + if %r{@}.match?(value) raise ArgumentError, _('@ sybmol is not allowed in the username, please follow the pattern of domain\login if you are attempting to add domain user') diff --git a/lib/puppet/property/sqlserver_tsql.rb b/lib/puppet/property/sqlserver_tsql.rb index 1bd7586a..98b7ce20 100644 --- a/lib/puppet/property/sqlserver_tsql.rb +++ b/lib/puppet/property/sqlserver_tsql.rb @@ -6,18 +6,18 @@ class Puppet::Property::SqlserverTsql < Puppet::Property # rubocop:disable Style desc 'TSQL property that we are going to wrap with a try catch' munge do |value| quoted_value = value.gsub('\'', '\'\'') - erb_template = <<-TEMPLATE -BEGIN TRY - SET NOCOUNT ON - DECLARE @sql_text as NVARCHAR(max); - SET @sql_text = N'#{quoted_value}' - EXECUTE sp_executesql @sql_text; -END TRY -BEGIN CATCH - DECLARE @msg as VARCHAR(max); - SELECT @msg = 'THROW CAUGHT: ' + ERROR_MESSAGE(); - THROW 51000, @msg, 10 -END CATCH + erb_template = <<~TEMPLATE + BEGIN TRY + SET NOCOUNT ON + DECLARE @sql_text as NVARCHAR(max); + SET @sql_text = N'#{quoted_value}' + EXECUTE sp_executesql @sql_text; + END TRY + BEGIN CATCH + DECLARE @msg as VARCHAR(max); + SELECT @msg = 'THROW CAUGHT: ' + ERROR_MESSAGE(); + THROW 51000, @msg, 10 + END CATCH TEMPLATE erb_template end diff --git a/lib/puppet/provider/sqlserver.rb b/lib/puppet/provider/sqlserver.rb index 9cf5f9bf..e06c0ae1 100644 --- a/lib/puppet/provider/sqlserver.rb +++ b/lib/puppet/provider/sqlserver.rb @@ -10,13 +10,13 @@ class Puppet::Provider::Sqlserver < Puppet::Provider # rubocop:disable Style/Doc initvars - commands powershell: if File.exist?("#{ENV['SYSTEMROOT']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe") - "#{ENV['SYSTEMROOT']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe" - elsif File.exist?("#{ENV['SYSTEMROOT']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe") - "#{ENV['SYSTEMROOT']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe" - else - 'powershell.exe' - end + commands powershell: if File.exist?("#{ENV.fetch('SYSTEMROOT', nil)}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe") + "#{ENV.fetch('SYSTEMROOT', nil)}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe" + elsif File.exist?("#{ENV.fetch('SYSTEMROOT', nil)}\\system32\\WindowsPowershell\\v1.0\\powershell.exe") + "#{ENV.fetch('SYSTEMROOT', nil)}\\system32\\WindowsPowershell\\v1.0\\powershell.exe" + else + 'powershell.exe' + end def try_execute(command, msg = nil, obfuscate_strings = nil, acceptable_exit_codes = [0]) command&.compact @@ -51,35 +51,33 @@ def not_nil_and_not_empty?(obj) # @api private def self.run_install_dot_net(source_location = nil) - unless source_location.nil? - warn("The specified windows_source_location directory for sqlserver of \"#{source_location}\" does not exist") unless Puppet::FileSystem.directory?(source_location) - end + warn("The specified windows_source_location directory for sqlserver of \"#{source_location}\" does not exist") if !source_location.nil? && !Puppet::FileSystem.directory?(source_location) - install_dot_net = <<-DOTNET -$Result = Dism /online /Get-featureinfo /featurename:NetFx3 -If($Result -contains "State : Enabled") -{ - Write-Host ".Net Framework 3.5 is already installed." -} -Else -{ - Write-Host "Installing .Net Framework 3.5, do not close this prompt..." - $InstallResult = DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /NoRestart /Quiet /LimitAccess #{"/Source:\"#{source_location}\"" unless source_location.nil?} - $Result = Dism /online /Get-featureinfo /featurename:NetFx3 - If($Result -contains "State : Enabled") - { - Write-Host "Install .Net Framework 3.5 successfully." - } - Else - { - Write-Host "Failed to install Install .Net Framework 3.5#{', please make sure the windows_feature_source is correct' unless source_location.nil?}." - Write-Host "DISM Install Result" - Write-Host "-----------" - Write-Host ($InstallResult -join "`n") - #exit 1 - } -} -DOTNET + install_dot_net = <<~DOTNET + $Result = Dism /online /Get-featureinfo /featurename:NetFx3 + If($Result -contains "State : Enabled") + { + Write-Host ".Net Framework 3.5 is already installed." + } + Else + { + Write-Host "Installing .Net Framework 3.5, do not close this prompt..." + $InstallResult = DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /NoRestart /Quiet /LimitAccess #{"/Source:\"#{source_location}\"" unless source_location.nil?} + $Result = Dism /online /Get-featureinfo /featurename:NetFx3 + If($Result -contains "State : Enabled") + { + Write-Host "Install .Net Framework 3.5 successfully." + } + Else + { + Write-Host "Failed to install Install .Net Framework 3.5#{', please make sure the windows_feature_source is correct' unless source_location.nil?}." + Write-Host "DISM Install Result" + Write-Host "-----------" + Write-Host ($InstallResult -join "`n") + #exit 1 + } + } + DOTNET powershell([install_dot_net]) end end diff --git a/lib/puppet/provider/sqlserver_features/mssql.rb b/lib/puppet/provider/sqlserver_features/mssql.rb index cbcfb415..564b4fdb 100644 --- a/lib/puppet/provider/sqlserver_features/mssql.rb +++ b/lib/puppet/provider/sqlserver_features/mssql.rb @@ -25,6 +25,7 @@ def self.instances featurelist = [] ALL_SQL_VERSIONS.each do |sql_version| next if result[sql_version].empty? + featurelist += result[sql_version] end @@ -58,6 +59,7 @@ def add_features(features) def modify_features(action, features) return unless not_nil_and_not_empty? features + debug "#{action.capitalize}ing features '#{features.join(',')}'" cmd_args = ["#{@resource[:source]}/setup.exe", "/ACTION=#{action}", @@ -66,15 +68,9 @@ def modify_features(action, features) "/FEATURES=#{features.join(',')}"] if action == 'install' cmd_args << '/UPDATEENABLED=False' - if not_nil_and_not_empty?(@resource[:is_svc_account]) - cmd_args << "/ISSVCACCOUNT=#{@resource[:is_svc_account]}" - end - if not_nil_and_not_empty?(@resource[:is_svc_password]) - cmd_args << "/ISSVCPASSWORD=#{@resource[:is_svc_password]}" - end - if not_nil_and_not_empty?(@resource[:pid]) - cmd_args << "/PID=#{@resource[:pid]}" - end + cmd_args << "/ISSVCACCOUNT=#{@resource[:is_svc_account]}" if not_nil_and_not_empty?(@resource[:is_svc_account]) + cmd_args << "/ISSVCPASSWORD=#{@resource[:is_svc_password]}" if not_nil_and_not_empty?(@resource[:is_svc_password]) + cmd_args << "/PID=#{@resource[:pid]}" if not_nil_and_not_empty?(@resource[:pid]) end begin config_file = create_temp_for_install_switch unless action == 'uninstall' @@ -95,9 +91,7 @@ def create_temp_for_install_switch if not_nil_and_not_empty? @resource[:install_switches] config_file = ['[OPTIONS]'] @resource[:install_switches].each_pair do |k, v| - if FEATURE_RESERVED_SWITCHES.include? k - warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value may be overridden by some command line arguments") - end + warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value may be overridden by some command line arguments") if FEATURE_RESERVED_SWITCHES.include? k config_file << if v.is_a?(Numeric) || (v.is_a?(String) && v =~ %r{^(true|false|1|0)$}i) "#{k}=#{v}" elsif v.nil? @@ -115,7 +109,7 @@ def create_temp_for_install_switch nil end - def install_net_35(source_location = nil) + def install_net35(source_location = nil) Puppet::Provider::Sqlserver.run_install_dot_net(source_location) end @@ -128,7 +122,7 @@ def create instance_version = PuppetX::Sqlserver::ServerHelper.sql_version_from_install_source(@resource[:source]) Puppet.debug("Installation source detected as version #{instance_version}") unless instance_version.nil? - install_net_35(@resource[:windows_feature_source]) if [SQL_2012, SQL_2014].include? instance_version + install_net35(@resource[:windows_feature_source]) if [SQL_2012, SQL_2014].include? instance_version debug "Installing features #{@resource[:features]}" add_features(@resource[:features]) diff --git a/lib/puppet/provider/sqlserver_instance/mssql.rb b/lib/puppet/provider/sqlserver_instance/mssql.rb index e3733915..b7cd3985 100644 --- a/lib/puppet/provider/sqlserver_instance/mssql.rb +++ b/lib/puppet/provider/sqlserver_instance/mssql.rb @@ -5,23 +5,24 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/server_helper')) require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/features')) +RESOURCEKEY_TO_CMDARG = { + 'agt_svc_account' => 'AGTSVCACCOUNT', + 'agt_svc_password' => 'AGTSVCPASSWORD', + 'as_svc_account' => 'ASSVCACCOUNT', + 'as_svc_password' => 'ASSVCPASSWORD', + 'pid' => 'PID', + 'rs_svc_account' => 'RSSVCACCOUNT', + 'rs_svc_password' => 'RSSVCPASSWORD', + 'polybase_svc_account' => 'PBENGSVCACCOUNT', + 'polybase_svc_password' => 'PBDMSSVCPASSWORD', + 'sa_pwd' => 'SAPWD', + 'security_mode' => 'SECURITYMODE', + 'sql_svc_account' => 'SQLSVCACCOUNT', + 'sql_svc_password' => 'SQLSVCPASSWORD' +}.freeze + Puppet::Type.type(:sqlserver_instance).provide(:mssql, parent: Puppet::Provider::Sqlserver) do desc 'SQLServer instance provider' - RESOURCEKEY_TO_CMDARG = { - 'agt_svc_account' => 'AGTSVCACCOUNT', - 'agt_svc_password' => 'AGTSVCPASSWORD', - 'as_svc_account' => 'ASSVCACCOUNT', - 'as_svc_password' => 'ASSVCPASSWORD', - 'pid' => 'PID', - 'rs_svc_account' => 'RSSVCACCOUNT', - 'rs_svc_password' => 'RSSVCPASSWORD', - 'polybase_svc_account' => 'PBENGSVCACCOUNT', - 'polybase_svc_password' => 'PBDMSSVCPASSWORD', - 'sa_pwd' => 'SAPWD', - 'security_mode' => 'SECURITYMODE', - 'sql_svc_account' => 'SQLSVCACCOUNT', - 'sql_svc_password' => 'SQLSVCPASSWORD', - }.freeze def instance_reserved_switches # List of all puppet managed install switches @@ -62,6 +63,7 @@ def add_features(features) def modify_features(features, action) return unless not_nil_and_not_empty? features + debug "#{action.capitalize}ing features '#{features.join(',')}'" cmd_args, obfuscated_strings = build_cmd_args(features, action) @@ -80,7 +82,7 @@ def modify_features(features, action) end end - def install_net_35(source_location = nil) + def install_net35(source_location = nil) Puppet::Provider::Sqlserver.run_install_dot_net(source_location) end @@ -105,7 +107,7 @@ def create instance_version = PuppetX::Sqlserver::ServerHelper.sql_version_from_install_source(@resource[:source]) Puppet.debug("Installation source detected as version #{instance_version}") unless instance_version.nil? - install_net_35(@resource[:windows_feature_source]) if [SQL_2012, SQL_2014].include? instance_version + install_net35(@resource[:windows_feature_source]) if [SQL_2012, SQL_2014].include? instance_version add_features(@resource[:features]) end @@ -115,9 +117,7 @@ def create_temp_for_install_switch if not_nil_and_not_empty? @resource[:install_switches] config_file = ['[OPTIONS]'] @resource[:install_switches].each_pair do |k, v| - if instance_reserved_switches.include? k - warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value may be overridden by some command line arguments") - end + warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value may be overridden by some command line arguments") if instance_reserved_switches.include? k config_file << if v.is_a?(Numeric) || (v.is_a?(String) && v =~ %r{^(true|false|1|0)$}i) "#{k}=#{v}" elsif v.nil? @@ -152,10 +152,9 @@ def build_cmd_args(features, action = 'install') if action == 'install' RESOURCEKEY_TO_CMDARG.keys.sort.map do |key| next unless not_nil_and_not_empty? @resource[key] + cmd_args << "/#{RESOURCEKEY_TO_CMDARG[key]}=\"#{@resource[key.to_sym]}\"" - if %r{(_pwd|_password)$}i.match?(key.to_s) - obfuscated_strings.push(@resource[key]) - end + obfuscated_strings.push(@resource[key]) if %r{(_pwd|_password)$}i.match?(key.to_s) end format_cmd_args_array('/SQLSYSADMINACCOUNTS', @resource[:sql_sysadmin_accounts], cmd_args, true) @@ -166,6 +165,7 @@ def build_cmd_args(features, action = 'install') def format_cmd_args_array(switch, arr, cmd_args, use_discrete = false) return unless not_nil_and_not_empty? arr + arr = [arr] unless arr.is_a?(Array) # The default action is to join the array elements with a space ' ' so the cmd_args ends up like; diff --git a/lib/puppet/provider/sqlserver_tsql/mssql.rb b/lib/puppet/provider/sqlserver_tsql/mssql.rb index be7968de..c5ac5b42 100644 --- a/lib/puppet/provider/sqlserver_tsql/mssql.rb +++ b/lib/puppet/provider/sqlserver_tsql/mssql.rb @@ -15,12 +15,10 @@ def run(query) def get_config(instance = resource[:instance]) config_resc = resource.catalog.resources.find do |resc| - resc.title =~ %r{Sqlserver::Config} && + resc.title.to_s.include?('Sqlserver::Config') && resc.original_parameters[:instance_name] =~ %r{#{instance}}i end - if config_resc.nil? - raise("Sqlserver_tsql[#{resource.title}] was unable to retrieve the config, please ensure the catalog contains sqlserver::config{'#{resource[:instance]}':}") - end + raise("Sqlserver_tsql[#{resource.title}] was unable to retrieve the config, please ensure the catalog contains sqlserver::config{'#{resource[:instance]}':}") if config_resc.nil? config_resc.original_parameters end diff --git a/lib/puppet/type/sqlserver_features.rb b/lib/puppet/type/sqlserver_features.rb index 3d87983b..6744e8b6 100644 --- a/lib/puppet/type/sqlserver_features.rb +++ b/lib/puppet/type/sqlserver_features.rb @@ -60,6 +60,7 @@ def validate # IS_SVC_ACCOUNT validation return unless set?(:features) && self[:features].include?('IS') return unless set?(:is_svc_account) || set?(:is_svc_password) + validate_user_password_required(:is_svc_account, :is_svc_password) end @@ -70,6 +71,7 @@ def domain_or_local_user?(user) def validate_user_password_required(account, pass) raise("User #{account} is required") unless set?(account) return unless domain_or_local_user?(self[account]) && self[pass].nil? + raise("#{pass} required when using domain account") end diff --git a/lib/puppet/type/sqlserver_instance.rb b/lib/puppet/type/sqlserver_instance.rb index ca80dbd9..b33f4d09 100644 --- a/lib/puppet/type/sqlserver_instance.rb +++ b/lib/puppet/type/sqlserver_instance.rb @@ -84,10 +84,8 @@ following characters: " / \ [ ] : ; | = , + * ? < > ' validate do |value| value.is_a? String - matches = value.scan(%r{(\/|\\|\[|\]|\:|\;|\||\=|\,|\+|\*|\?|\<|\>)}) - unless matches.empty? - raise("rs_svc_account can not contain any of the special characters, / \\ [ ] : ; | = , + * ? < >, your entry contained #{matches}") - end + matches = value.scan(%r{(/|\\|\[|\]|:|;|\||=|,|\+|\*|\?|<|>)}) + raise("rs_svc_account can not contain any of the special characters, / \\ [ ] : ; | = , + * ? < >, your entry contained #{matches}") unless matches.empty? end end @@ -122,16 +120,13 @@ end def validate - if set?(:agt_svc_account) - validate_user_password_required(:agt_svc_account, :agt_svc_password) - end + validate_user_password_required(:agt_svc_account, :agt_svc_password) if set?(:agt_svc_account) self[:features] = self[:features].flatten.sort.uniq if set?(:features) # RS Must have Strong Password - if set?(:rs_svc_password) && self[:features].include?('RS') - strong_password?(:rs_svc_password) - end + strong_password?(:rs_svc_password) if set?(:rs_svc_password) && self[:features].include?('RS') return unless self[:security_mode] == 'SQL' + strong_password?(:sa_pwd) end @@ -143,6 +138,7 @@ def validate_user_password_required(account, pass) # rubocop:disable Style/SignalException fail("User #{account} is required") unless set?(account) return unless domain_or_local_user?(self[account]) && self[pass].nil? + fail("#{pass} required when using domain account") # rubocop:enable Style/SignalException end @@ -154,6 +150,7 @@ def domain_or_local_user?(user) def strong_password?(key) password = self[key] return unless password + message_start = "Password for #{key} is not strong" failures = [] failures << 'must be at least 8 characters long' unless password.length >= 8 @@ -161,7 +158,8 @@ def strong_password?(key) failures << 'must contain uppercase letters' unless %r{[A-Z]}.match?(password) failures << 'must contain numbers' unless %r{\d}.match?(password) failures << 'must contain a special character' unless %r{}.match?(password) - fail("#{message_start}:\n#{failures.join("\n")}") if failures.count > 0 # rubocop:disable Style/SignalException + fail("#{message_start}:\n#{failures.join("\n")}") if failures.count.positive? # rubocop:disable Style/SignalException + true end end diff --git a/lib/puppet/type/sqlserver_tsql.rb b/lib/puppet/type/sqlserver_tsql.rb index fe153cd7..4cf465ef 100644 --- a/lib/puppet/type/sqlserver_tsql.rb +++ b/lib/puppet/type/sqlserver_tsql.rb @@ -35,7 +35,7 @@ def self.checks desc 'initial database to connect to during query execution' defaultto 'master' validate do |value| - raise("Invalid database name #{value}") unless %r{^[[:word:]|#|@]+}.match?(value) + raise("Invalid database name #{value}") unless %r{^[[:word:]|#@]+}.match?(value) end end @@ -109,13 +109,10 @@ def sync event = :executed_command @output = provider.run(resource[:command]) - if @output.has_errors - raise("Unable to apply changes, failed with error message #{@output.error_message}") - end + raise("Unable to apply changes, failed with error message #{@output.error_message}") if @output.has_errors + + raise("#{resource[:command]} returned #{@output.exitstatus} instead of one of [#{should.join(',')}]") unless @output.exitstatus.to_s == '0' - unless @output.exitstatus.to_s == '0' - raise("#{resource[:command]} returned #{@output.exitstatus} instead of one of [#{should.join(',')}]") - end event end end diff --git a/lib/puppet_x/sqlserver/features.rb b/lib/puppet_x/sqlserver/features.rb index 1cb249c8..20f649de 100644 --- a/lib/puppet_x/sqlserver/features.rb +++ b/lib/puppet_x/sqlserver/features.rb @@ -2,14 +2,14 @@ require 'puppet/util/windows' -SQL_2012 ||= 'SQL_2012' -SQL_2014 ||= 'SQL_2014' -SQL_2016 ||= 'SQL_2016' -SQL_2017 ||= 'SQL_2017' -SQL_2019 ||= 'SQL_2019' -SQL_2022 ||= 'SQL_2022' +SQL_2012 = 'SQL_2012' +SQL_2014 = 'SQL_2014' +SQL_2016 = 'SQL_2016' +SQL_2017 = 'SQL_2017' +SQL_2019 = 'SQL_2019' +SQL_2022 = 'SQL_2022' -ALL_SQL_VERSIONS ||= [SQL_2012, SQL_2014, SQL_2016, SQL_2017, SQL_2019, SQL_2022].freeze +ALL_SQL_VERSIONS = [SQL_2012, SQL_2014, SQL_2016, SQL_2017, SQL_2019, SQL_2022].freeze # rubocop:disable Style/ClassAndModuleChildren module PuppetX @@ -19,35 +19,35 @@ class Features # rubocop:disable Style/Documentation include Puppet::Util::Windows::Registry extend Puppet::Util::Windows::Registry - SQL_CONFIGURATION ||= { + SQL_CONFIGURATION = { SQL_2012 => { major_version: 11, - registry_path: '110', + registry_path: '110' }, SQL_2014 => { major_version: 12, - registry_path: '120', + registry_path: '120' }, SQL_2016 => { major_version: 13, - registry_path: '130', + registry_path: '130' }, SQL_2017 => { major_version: 14, - registry_path: '140', + registry_path: '140' }, SQL_2019 => { major_version: 15, - registry_path: '150', + registry_path: '150' }, SQL_2022 => { major_version: 16, - registry_path: '160', - }, + registry_path: '160' + } }.freeze - SQL_REG_ROOT ||= 'Software\Microsoft\Microsoft SQL Server' - HKLM ||= 'HKEY_LOCAL_MACHINE' + SQL_REG_ROOT = 'Software\Microsoft\Microsoft SQL Server' + HKLM = 'HKEY_LOCAL_MACHINE' def self.get_parent_path(key_path) # should be the same as SQL_REG_ROOT @@ -56,14 +56,14 @@ def self.get_parent_path(key_path) def self.get_reg_key_val(win32_reg_key, val_name, reg_type) win32_reg_key[val_name, reg_type] - rescue + rescue StandardError nil end def self.key_exists?(path) open(HKLM, path, KEY_READ | KEY64) {} true - rescue + rescue StandardError false end @@ -84,6 +84,7 @@ def self.get_sql_reg_val_features(key_name, reg_val_feat_hash) def self.get_reg_instance_info(friendly_version) instance_root = 'SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names' return [] unless key_exists?(instance_root) + discovered = {} open(HKLM, instance_root.to_s, KEY_READ | KEY64) do |registry| each_key(registry) do |instance_type, _| @@ -91,11 +92,12 @@ def self.get_reg_instance_info(friendly_version) each_value(instance) do |short_name, _, long_name| root = "Software\\Microsoft\\Microsoft SQL Server\\#{long_name}" next unless key_exists?("#{root}\\MSSQLServer\\CurrentVersion") + discovered[short_name] ||= { 'name' => short_name, 'reg_root' => [], 'version' => open(HKLM, "#{root}\\MSSQLServer\\CurrentVersion", KEY_READ | KEY64) { |r| values(r)['CurrentVersion'] }, - 'version_friendly' => friendly_version, + 'version_friendly' => friendly_version } discovered[short_name]['reg_root'].push(root) @@ -122,11 +124,11 @@ def self.get_instance_features(reg_root, instance_name) # also reg Replication/IsInstalled set to 1 'SQL_Replication_Core_Inst' => 'Replication', # SQL Server Replication # also WMI: SqlService WHERE SQLServiceType = 1 # MSSQLSERVER - 'SQL_Engine_Core_Inst' => 'SQLEngine', # Database Engine Services - 'SQL_FullText_Adv' => 'FullText', # Full-Text and Semantic Extractions for Search - 'SQL_DQ_Full' => 'DQ', # Data Quality Services - 'sql_inst_mr' => 'ADVANCEDANALYTICS', # R Services (In-Database) - 'SQL_Polybase_Core_Inst' => 'POLYBASE', # PolyBase Query Service for External Data + 'SQL_Engine_Core_Inst' => 'SQLEngine', # Database Engine Services + 'SQL_FullText_Adv' => 'FullText', # Full-Text and Semantic Extractions for Search + 'SQL_DQ_Full' => 'DQ', # Data Quality Services + 'sql_inst_mr' => 'ADVANCEDANALYTICS', # R Services (In-Database) + 'SQL_Polybase_Core_Inst' => 'POLYBASE' # PolyBase Query Service for External Data } feat_root = "#{reg_root}\\ConfigurationState" @@ -152,20 +154,20 @@ def self.get_shared_features(version) shared_features = { # Client tools support removed with SQLServer 2022 # (ref https://learn.microsoft.com/en-us/sql/database-engine/install-windows/install-sql-server-on-server-core?view=sql-server-ver16#BK_SupportedFeatures) - 'Connectivity_Full' => 'Conn', # Client Tools Connectivity - 'SDK_Full' => 'SDK', # Client Tools SDK - 'MDSCoreFeature' => 'MDS', # Master Data Services - 'Tools_Legacy_Full' => 'BC', # Client Tools Backwards Compatibility - 'SQL_SSMS_Full' => 'ADV_SSMS', # Management Tools - Complete (Does not exist in SQL 2016+) - 'SQL_SSMS_Adv' => 'SSMS', # Management Tools - Basic (Does not exist in SQL 2016) - 'SQL_DQ_CLIENT_Full' => 'DQC', # Data Quality Client - 'SQL_BOL_Components' => 'BOL', # Documentation Components + 'Connectivity_Full' => 'Conn', # Client Tools Connectivity + 'SDK_Full' => 'SDK', # Client Tools SDK + 'MDSCoreFeature' => 'MDS', # Master Data Services + 'Tools_Legacy_Full' => 'BC', # Client Tools Backwards Compatibility + 'SQL_SSMS_Full' => 'ADV_SSMS', # Management Tools - Complete (Does not exist in SQL 2016+) + 'SQL_SSMS_Adv' => 'SSMS', # Management Tools - Basic (Does not exist in SQL 2016) + 'SQL_DQ_CLIENT_Full' => 'DQC', # Data Quality Client + 'SQL_BOL_Components' => 'BOL', # Documentation Components 'SQL_DReplay_Controller' => 'DREPLAY_CTLR', # Distributed Replay Controller - 'SQL_DReplay_Client' => 'DREPLAY_CLT', # Distributed Replay Client - 'sql_shared_mr' => 'SQL_SHARED_MR', # R Server (Standalone) + 'SQL_DReplay_Client' => 'DREPLAY_CLT', # Distributed Replay Client + 'sql_shared_mr' => 'SQL_SHARED_MR', # R Server (Standalone) # SQL Client Connectivity SDK (Installed by default) # also WMI: SqlService WHERE SQLServiceType = 4 # MsDtsServer - 'SQL_DTS_Full' => 'IS', # Integration Services + 'SQL_DTS_Full' => 'IS' # Integration Services # currently ignoring Reporting Services Shared # currently ignoring R Server Standalone } @@ -215,15 +217,16 @@ def self.instances # by inspecting the major version of the instance_version instances.select! do |value| return true if value[1]['version'].nil? + ver = Gem::Version.new(value[1]['version']) # Segment 0 is the major version number of the SQL Instance ver.segments[0] == major_version end - [version, Hash[instances]] + [version, instances.to_h] end - Hash[version_instance_map] + version_instance_map.to_h end # return a hash of version => shared features array @@ -260,6 +263,7 @@ def self.get_instance_info(version, sql_instance) # it's possible to request information for a valid instance_name but not for version. In this case # we just return nil. return nil if sql_instance['reg_root'].nil? + feats = [] sql_instance['reg_root'].each do |reg_root| feats += get_instance_features(reg_root, sql_instance['name']) diff --git a/lib/puppet_x/sqlserver/server_helper.rb b/lib/puppet_x/sqlserver/server_helper.rb index 26128485..f2daed42 100644 --- a/lib/puppet_x/sqlserver/server_helper.rb +++ b/lib/puppet_x/sqlserver/server_helper.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true module PuppetX # rubocop:disable Style/ClassAndModuleChildren - module Sqlserver # rubocop:disable Style/ClassAndModuleChildren + module Sqlserver class ServerHelper # rubocop:disable Style/Documentation @super_feature_hash = { SQL: [:DQ, :FullText, :Replication, :SQLEngine], - Tools: [:BC, :SSMS, :ADV_SSMS, :Conn, :SDK], + Tools: [:BC, :SSMS, :ADV_SSMS, :Conn, :SDK] } def self.get_sub_features(super_feature) @@ -17,11 +17,7 @@ def self.is_super_feature(feature) # rubocop:disable Naming/PredicateName end def self.is_domain_or_local_user?(user, hostname) # rubocop:disable Naming/PredicateName - if %r{(^(((nt (authority|service))|#{hostname})\\\w+)$)|^(\w+)$}i.match?(user) - false - else - true - end + !%r{(^(((nt (authority|service))|#{hostname})\\\w+)$)|^(\w+)$}i.match?(user) end # Returns either SQL_2016, SQL_2014 or SQL_2012 if it can determine the SQL Version from the install source @@ -30,14 +26,17 @@ def self.sql_version_from_install_source(source_dir) # Attempt to read the Mediainfo.xml file in the root of the install media media_file = File.expand_path("#{source_dir}/MediaInfo.xml") return nil unless File.exist?(media_file) + # As we don't have a XML parser easily, just use simple text matching to find the following XML element. This # also means we can just ignore BOM markers etc. # content = File.read(media_file) index1 = content.index('"BaselineVersion"') return nil if index1.nil? + index2 = content.index('/>', index1) return nil if index2.nil? + content = content.slice(index1 + 18, index2 - index1 - 18) # Extract the version number from the text snippet # Value="xx.yyy.zz." diff --git a/lib/puppet_x/sqlserver/sql_connection.rb b/lib/puppet_x/sqlserver/sql_connection.rb index c35c86e2..08e476a8 100644 --- a/lib/puppet_x/sqlserver/sql_connection.rb +++ b/lib/puppet_x/sqlserver/sql_connection.rb @@ -31,11 +31,11 @@ def open(config) def get_connection_string(config) params = { - 'Provider' => 'MSOLEDBSQL', - 'Initial Catalog' => config[:database] || 'master', - 'Application Name' => 'Puppet', - 'Data Source' => '.', - 'DataTypeComptibility' => 80, + 'Provider' => 'MSOLEDBSQL', + 'Initial Catalog' => config[:database] || 'master', + 'Application Name' => 'Puppet', + 'Data Source' => '.', + 'DataTypeComptibility' => 80 } admin_user = config[:admin_user] || '' @@ -45,18 +45,18 @@ def get_connection_string(config) # Windows based authentication raise ArgumentError, _('admin_user must be empty or nil') unless admin_user == '' raise ArgumentError, _('admin_pass must be empty or nil') unless admin_pass == '' + params.store('Integrated Security', 'SSPI') else # SQL Server based authentication raise ArgumentError, _('admin_user must not be empty or nil') unless admin_user != '' raise ArgumentError, _('admin_pass must not be empty or nil') unless admin_pass != '' + params.store('UID', admin_user) params.store('PWD', admin_pass) end - if !config[:instance_name].nil? && config[:instance_name] !~ %r{^MSSQLSERVER$} - params['Data Source'] = ".\\#{config[:instance_name]}" - end + params['Data Source'] = ".\\#{config[:instance_name]}" if !config[:instance_name].nil? && config[:instance_name] !~ %r{^MSSQLSERVER$} params.map { |k, v| "#{k}=#{v}" }.join(';') end diff --git a/manifests/login.pp b/manifests/login.pp index dba55fa1..45c881f6 100644 --- a/manifests/login.pp +++ b/manifests/login.pp @@ -92,25 +92,25 @@ instance => $instance, require => Sqlserver_tsql["login-${instance}-${login}"], } - if has_key($_upermissions, 'GRANT') and is_array($_upermissions['GRANT']) { + if has_key($_upermissions, 'GRANT') and $_upermissions['GRANT'] =~ Array { sqlserver::login::permissions { "Sqlserver::Login[${title}]-GRANT-${login}": state => 'GRANT', permissions => $_upermissions['GRANT'], } } - if has_key($_upermissions, 'DENY') and is_array($_upermissions['DENY']) { + if has_key($_upermissions, 'DENY') and $_upermissions['DENY'] =~ Array { sqlserver::login::permissions { "Sqlserver::Login[${title}]-DENY-${login}": state => 'DENY', permissions => $_upermissions['DENY'], } } - if has_key($_upermissions, 'REVOKE') and is_array($_upermissions['REVOKE']) { + if has_key($_upermissions, 'REVOKE') and $_upermissions['REVOKE'] =~ Array { sqlserver::login::permissions { "Sqlserver::Login[${title}]-REVOKE-${login}": state => 'REVOKE', permissions => $_upermissions['REVOKE'], } } - if has_key($_upermissions, 'GRANT_WITH_OPTION') and is_array($_upermissions['GRANT_WITH_OPTION']) { + if has_key($_upermissions, 'GRANT_WITH_OPTION') and $_upermissions['GRANT_WITH_OPTION'] =~ Array { sqlserver::login::permissions { "Sqlserver::Login[${title}]-GRANT-WITH_GRANT_OPTION-${login}": state => 'GRANT', with_grant_option => true, diff --git a/manifests/role.pp b/manifests/role.pp index 54719d2b..82aa96fd 100644 --- a/manifests/role.pp +++ b/manifests/role.pp @@ -79,25 +79,25 @@ type => $type, require => Sqlserver_tsql[$sqlserver_tsql_title], } - if has_key($_upermissions, 'GRANT') and is_array($_upermissions['GRANT']) { + if has_key($_upermissions, 'GRANT') and $_upermissions['GRANT'] =~ Array { sqlserver::role::permissions { "Sqlserver::Role[${title}]-GRANT-${role}": state => 'GRANT', permissions => $_upermissions['GRANT'], } } - if has_key($_upermissions, 'DENY') and is_array($_upermissions['DENY']) { + if has_key($_upermissions, 'DENY') and $_upermissions['DENY'] =~ Array { sqlserver::role::permissions { "Sqlserver::Role[${title}]-DENY-${role}": state => 'DENY', permissions => $_upermissions['DENY'], } } - if has_key($_upermissions, 'REVOKE') and is_array($_upermissions['REVOKE']) { + if has_key($_upermissions, 'REVOKE') and $_upermissions['REVOKE'] =~ Array { sqlserver::role::permissions { "Sqlserver::Role[${title}]-REVOKE-${role}": state => 'REVOKE', permissions => $_upermissions['REVOKE'], } } - if has_key($_upermissions, 'GRANT_WITH_OPTION') and is_array($_upermissions['GRANT_WITH_OPTION']) { + if has_key($_upermissions, 'GRANT_WITH_OPTION') and $_upermissions['GRANT_WITH_OPTION'] =~ Array { sqlserver::role::permissions { "Sqlserver::Role[${title}]-GRANT-WITH_GRANT_OPTION-${role}": state => 'GRANT', with_grant_option => true, diff --git a/manifests/user.pp b/manifests/user.pp index 2cdf0ddd..529d466a 100644 --- a/manifests/user.pp +++ b/manifests/user.pp @@ -79,25 +79,25 @@ instance => $instance, require => Sqlserver_tsql["user-${instance}-${database}-${user}"], } - if has_key($_upermissions, 'GRANT') and is_array($_upermissions['GRANT']) { + if has_key($_upermissions, 'GRANT') and $_upermissions['GRANT'] =~ Array { sqlserver::user::permissions { "Sqlserver::User[${title}]-GRANT-${user}": state => 'GRANT', permissions => $_upermissions['GRANT'], } } - if has_key($_upermissions, 'DENY') and is_array($_upermissions['DENY']) { + if has_key($_upermissions, 'DENY') and $_upermissions['DENY'] =~ Array { sqlserver::user::permissions { "Sqlserver::User[${title}]-DENY-${user}": state => 'DENY', permissions => $_upermissions['DENY'], } } - if has_key($_upermissions, 'REVOKE') and is_array($_upermissions['REVOKE']) { + if has_key($_upermissions, 'REVOKE') and $_upermissions['REVOKE'] =~ Array { sqlserver::user::permissions { "Sqlserver::User[${title}]-REVOKE-${user}": state => 'REVOKE', permissions => $_upermissions['REVOKE'], } } - if has_key($_upermissions, 'GRANT_WITH_OPTION') and is_array($_upermissions['GRANT_WITH_OPTION']) { + if has_key($_upermissions, 'GRANT_WITH_OPTION') and $_upermissions['GRANT_WITH_OPTION'] =~ Array { sqlserver::user::permissions { "Sqlserver::User[${title}]-GRANT-WITH_GRANT_OPTION-${user}": state => 'GRANT', with_grant_option => true, diff --git a/metadata.json b/metadata.json index 113f9617..8a7f758a 100644 --- a/metadata.json +++ b/metadata.json @@ -32,7 +32,7 @@ "requirements": [ { "name": "puppet", - "version_requirement": ">=6.0.0 < 8.0.0" + "version_requirement": ">=7.0.0 < 9.0.0" } ], "tags": [ @@ -49,7 +49,7 @@ "tsql", "database" ], - "pdk-version": "2.6.1", + "pdk-version": "2.7.1", "template-url": "https://github.com/puppetlabs/pdk-templates.git#main", - "template-ref": "heads/main-0-g6e2b72d" + "template-ref": "tags/2.7.5-0-ge5b0114" } diff --git a/spec/acceptance/sqlserver_config_spec.rb b/spec/acceptance/sqlserver_config_spec.rb index 8768be73..6788563f 100644 --- a/spec/acceptance/sqlserver_config_spec.rb +++ b/spec/acceptance/sqlserver_config_spec.rb @@ -5,9 +5,9 @@ require 'erb' # Get instance name -inst_name = ('MSSQL' + SecureRandom.hex(4)).upcase +inst_name = "MSSQL#{SecureRandom.hex(4)}".upcase # Get database name -db_name = ('DB' + SecureRandom.hex(4)).upcase +db_name = "DB#{SecureRandom.hex(4)}".upcase describe 'sqlserver::config test' do def ensure_sqlserver_instance(inst_name, ensure_val = 'present') @@ -32,11 +32,11 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') ensure_sqlserver_instance(inst_name) # get credentials for new config - @admin_user = 'test_user' + SecureRandom.hex(2) + @admin_user = "test_user#{SecureRandom.hex(2)}" @admin_pass = 'Pupp3t1@' # get database user - @db_user = 'dbuser' + SecureRandom.hex(2) + @db_user = "dbuser#{SecureRandom.hex(2)}" end after(:all) do @@ -81,7 +81,7 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') query = "USE #{db_name}; SELECT * from master..sysdatabases WHERE name = '#{db_name}'" run_sql_query(query: query, server: hostname, instance: inst_name, \ - sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, expected_row_count: 1) + sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, expected_row_count: 1) end it 'Validate New Config WITHOUT using instance_name in sqlserver::config' do diff --git a/spec/acceptance/sqlserver_database_spec.rb b/spec/acceptance/sqlserver_database_spec.rb index a49bc6d2..afe23678 100644 --- a/spec/acceptance/sqlserver_database_spec.rb +++ b/spec/acceptance/sqlserver_database_spec.rb @@ -10,14 +10,14 @@ def run_sql_query_opts(query, expected_row_count) query: query, sql_admin_user: 'sa', sql_admin_pass: 'Pupp3t1@', - expected_row_count: expected_row_count, + expected_row_count: expected_row_count } end context 'Start testing...' do before(:each) do - @db_name = ('DB' + SecureRandom.hex(4)).upcase - @table_name = 'Tables_' + SecureRandom.hex(3) + @db_name = "DB#{SecureRandom.hex(4)}".upcase + @table_name = "Tables_#{SecureRandom.hex(3)}" end after(:each) do @@ -298,7 +298,6 @@ def run_sql_query_opts(query, expected_row_count) AND default_language_lcid = '1028';" run_sql_query(run_sql_query_opts(query, 1)) - # rubocop:enable RSpec/InstanceVariable end end end diff --git a/spec/acceptance/sqlserver_instance_spec.rb b/spec/acceptance/sqlserver_instance_spec.rb index b9e25369..e2ba6c4f 100644 --- a/spec/acceptance/sqlserver_instance_spec.rb +++ b/spec/acceptance/sqlserver_instance_spec.rb @@ -5,7 +5,7 @@ require 'erb' def new_random_instance_name - ('MSSQL' + SecureRandom.hex(4)).upcase.to_s + "MSSQL#{SecureRandom.hex(4)}".upcase.to_s end describe 'sqlserver_instance' do @@ -16,7 +16,7 @@ def ensure_sqlserver_instance(features, inst_name, ensure_val = 'present', sysad sysadmin_accounts << user # If no password env variable set (by CI), then default to vagrant password = Helper.instance.run_shell('$env:pass').stdout.chomp - password = password.empty? ? 'vagrant' : password + password = 'vagrant' if password.empty? pp = <<-MANIFEST sqlserver_instance{'#{inst_name}': @@ -43,7 +43,7 @@ def run_sql_query_opts(inst_name, query, expected_row_count) server: '.', sql_admin_user: 'sa', sql_admin_pass: 'Pupp3t1@', - expected_row_count: expected_row_count, + expected_row_count: expected_row_count } end @@ -99,7 +99,7 @@ def sql_query_is_user_sysadmin(username) it "#{inst_name} instance has ExtraSQLAdmin as a sysadmin" do run_sql_query(run_sql_query_opts(inst_name, sql_query_is_user_sysadmin(@extra_admin_user), 1)) end - # rubocop:enable RSpec/InstanceVariable + it "remove #{inst_name} instance" do ensure_sqlserver_instance(features, inst_name, 'absent') diff --git a/spec/acceptance/sqlserver_login_spec.rb b/spec/acceptance/sqlserver_login_spec.rb index 992901e4..de814877 100644 --- a/spec/acceptance/sqlserver_login_spec.rb +++ b/spec/acceptance/sqlserver_login_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper_acceptance' require 'securerandom' -db_name = ('DB' + SecureRandom.hex(4)).upcase -table_name = 'Tables_' + SecureRandom.hex(3) +db_name = "DB#{SecureRandom.hex(4)}".upcase +table_name = "Tables_#{SecureRandom.hex(3)}" # Covers testrail => ['89118', '89119', '89120', '89121', '89122', '89123', '89124', '89125', '89540'] describe 'Test sqlserver::login' do @@ -14,7 +14,7 @@ def run_sql_query_opts(user, passwd, query, expected_row_count) query: query, sql_admin_user: user, sql_admin_pass: passwd, - expected_row_count: expected_row_count, + expected_row_count: expected_row_count } end @@ -48,9 +48,7 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) case testcase when 'SQL_LOGIN user' login_type = 'SQL_LOGIN' - when 'WINDOWS_LOGIN user' - login_type = 'WINDOWS_LOGIN' - when 'WINDOWS_LOGIN group' + when 'WINDOWS_LOGIN user', 'WINDOWS_LOGIN group' login_type = 'WINDOWS_LOGIN' else raise "Unknown testcase name #{testcase}" @@ -73,18 +71,18 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) #{"disabled => #{options['disabled']}," unless options['disabled'].nil?} #{"ensure => '#{options['ensure']}'," unless options['ensure'].nil?} } - MANIFEST + MANIFEST end before(:all) do - @login_user = 'Login' + SecureRandom.hex(4) - @login_passwd = 'Password1!' + SecureRandom.hex(5) - @windows_user = 'User' + SecureRandom.hex(4) - @windows_group = 'Group' + SecureRandom.hex(4) + @login_user = "Login#{SecureRandom.hex(4)}" + @login_passwd = "Password1!#{SecureRandom.hex(5)}" + @windows_user = "User#{SecureRandom.hex(4)}" + @windows_group = "Group#{SecureRandom.hex(4)}" host_shortname = Helper.instance.run_shell('$env:computername').stdout.upcase.strip # Require the NETBIOS name for later database searches - @login_windows_user = host_shortname + '\\' + @windows_user - @login_windows_group = host_shortname + '\\' + @windows_group + @login_windows_user = "#{host_shortname}\\#{@windows_user}" + @login_windows_group = "#{host_shortname}\\#{@windows_group}" # Create a database, a simple table and windows accounts fixtures pp = <<-MANIFEST @@ -179,6 +177,7 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) # check_expiration and check_policy are only applicable to SQL based logins before(:all) { remove_test_logins(host) } + it "can create an #{testcase} with 'check_expiration','check_policy' set" do options = { 'check_expiration' => true, 'check_policy' => true } pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) @@ -292,6 +291,7 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) AND pri.name = '#{@login_under_test}'" run_sql_query(run_sql_query_opts_as_sa(query, 1)) end + it 'has the specified serveradmin role' do # Note - IS_SRVROLEMEMBER always returns false for a disabled WINDOWS_LOGIN user login query = "SELECT pri.name from sys.server_role_members member @@ -351,7 +351,6 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}'" run_sql_query(run_sql_query_opts_as_sa(query, 0)) end - # rubocop:enable RSpec/InstanceVariable end end end diff --git a/spec/acceptance/sqlserver_role_spec.rb b/spec/acceptance/sqlserver_role_spec.rb index b05da34b..e1982fc0 100644 --- a/spec/acceptance/sqlserver_role_spec.rb +++ b/spec/acceptance/sqlserver_role_spec.rb @@ -7,11 +7,11 @@ hostname = Helper.instance.run_shell('hostname').stdout.upcase.strip # database name -db_name = ('DB' + SecureRandom.hex(4)).upcase -LOGIN1 = 'Login1_' + SecureRandom.hex(2) -LOGIN2 = 'Login2_' + SecureRandom.hex(2) -LOGIN3 = 'Login3_' + SecureRandom.hex(2) -USER1 = 'User1_' + SecureRandom.hex(2) +db_name = "DB#{SecureRandom.hex(4)}".upcase +LOGIN1 = "Login1_#{SecureRandom.hex(2)}" +LOGIN2 = "Login2_#{SecureRandom.hex(2)}" +LOGIN3 = "Login3_#{SecureRandom.hex(2)}" +USER1 = "User1_#{SecureRandom.hex(2)}" describe 'Test sqlserver::role' do def ensure_sqlserver_logins_users(db_name) @@ -50,9 +50,11 @@ def ensure_sqlserver_logins_users(db_name) # Create database users ensure_sqlserver_logins_users(db_name) end + before(:each) do - @role = 'Role_' + SecureRandom.hex(2) + @role = "Role_#{SecureRandom.hex(2)}" end + after(:each) do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -255,7 +257,6 @@ def ensure_sqlserver_logins_users(db_name) OR spr.name = '#{LOGIN3}';" run_sql_query(query: query, server: hostname, expected_row_count: 1) - # rubocop:enable RSpec/InstanceVariable end end end diff --git a/spec/acceptance/sqlserver_tsql_spec.rb b/spec/acceptance/sqlserver_tsql_spec.rb index 14967388..a8a5801b 100644 --- a/spec/acceptance/sqlserver_tsql_spec.rb +++ b/spec/acceptance/sqlserver_tsql_spec.rb @@ -7,10 +7,10 @@ version = sql_version? # database name -db_name = ('DB' + SecureRandom.hex(4)).upcase +db_name = "DB#{SecureRandom.hex(4)}".upcase # database user: -DB_LOGIN_USER = 'loginuser' + SecureRandom.hex(2) +DB_LOGIN_USER = "loginuser#{SecureRandom.hex(2)}" describe 'sqlserver_tsql test' do def ensure_sqlserver_database(db_name, _ensure_val = 'present') @@ -29,7 +29,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') context 'Test sqlserver_tsql with Windows based authentication' do before(:all) do # Create new database - @table_name = 'Tables_' + SecureRandom.hex(3) + @table_name = "Tables_#{SecureRandom.hex(3)}" @query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" ensure_sqlserver_database(db_name) @@ -59,7 +59,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') query: @query, sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, - expected_row_count: 1, + expected_row_count: 1 } run_sql_query(run_sql_query_opts) end @@ -68,7 +68,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') context 'Test sqlserver_tsql with default SQL Server based authentication' do before(:all) do # Create new database - @table_name = 'Tables_' + SecureRandom.hex(3) + @table_name = "Tables_#{SecureRandom.hex(3)}" @query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" ensure_sqlserver_database(db_name) @@ -99,7 +99,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') query: @query, sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, - expected_row_count: 1, + expected_row_count: 1 } run_sql_query(run_sql_query_opts) end @@ -107,7 +107,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') it 'Run sqlserver_tsql WITH onlyif is true:', if: version.to_i != 2016 do # Timeout issues with command run on Sql Server 2016. Functionality of test covered by test below. # Initilize a new table name: - @table_name = 'Table_' + SecureRandom.hex(3) + @table_name = "Table_#{SecureRandom.hex(3)}" @query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -129,14 +129,14 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') query: @query, sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, - expected_row_count: 1, + expected_row_count: 1 } run_sql_query(run_sql_query_opts) end it 'Run sqlserver_tsql WITH onlyif is false:' do # Initilize a new table name: - @table_name = 'Table_' + SecureRandom.hex(3) + @table_name = "Table_#{SecureRandom.hex(3)}" @query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -159,14 +159,14 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') query: @query, sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, - expected_row_count: 0, + expected_row_count: 0 } run_sql_query(run_sql_query_opts) end it 'Run sqlserver_tsql WITH onlyif that does a table insert:' do # Initilize a new table name: - @table_name = 'Table_' + SecureRandom.hex(3) + @table_name = "Table_#{SecureRandom.hex(3)}" @query = "USE #{db_name}; SELECT * FROM #{@table_name} WHERE id = 2;" pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -190,7 +190,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') query: @query, sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, - expected_row_count: 1, + expected_row_count: 1 } run_sql_query(run_sql_query_opts) end @@ -212,7 +212,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') end it 'Negative test: Run tsql with non-existing database:' do - @table_name = 'Table_' + SecureRandom.hex(3) + @table_name = "Table_#{SecureRandom.hex(3)}" pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': instance_name => 'MSSQLSERVER', @@ -225,7 +225,6 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') command => "CREATE TABLE #{@table_name} (id INT, name VARCHAR(20), email VARCHAR(20));", } MANIFEST - # rubocop:enable RSpec/InstanceVariable apply_manifest(pp, expect_failures: true) end end diff --git a/spec/acceptance/sqlserver_user_spec.rb b/spec/acceptance/sqlserver_user_spec.rb index 4ea795c9..b5a652d7 100644 --- a/spec/acceptance/sqlserver_user_spec.rb +++ b/spec/acceptance/sqlserver_user_spec.rb @@ -7,7 +7,7 @@ hostname = Helper.instance.run_shell('hostname').stdout.upcase.strip # database name -db_name = ('DB' + SecureRandom.hex(4)).upcase +db_name = "DB#{SecureRandom.hex(4)}".upcase describe 'sqlserver::user test' do def ensure_sqlserver_database(db_name, _ensure_val = 'present') @@ -38,15 +38,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') # Create new database ensure_sqlserver_database(db_name) end - before(:each) do - @new_sql_login = 'Login' + SecureRandom.hex(2) - @db_user = 'DBuser' + SecureRandom.hex(2) - end - after(:all) do - # remove the newly created database - # Temporarily skip delete database because of MODULES-2554 - # ensure_sqlserver_database(host, 'absent') + before(:each) do + @new_sql_login = "Login#{SecureRandom.hex(2)}" + @db_user = "DBuser#{SecureRandom.hex(2)}" end it 'Create database user with optional default_schema' do @@ -96,7 +91,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') user => '#{@db_user}', require => Sqlserver::Login['#{@db_user}'], } - MANIFEST + MANIFEST apply_manifest(pp, catch_failures: true) # validate that the database user '#{@db_user}' is successfully created: @@ -200,7 +195,6 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') # validate that the database user '#{@db_user}' should be deleted: query = "USE #{db_name}; SELECT * FROM SYS.DATABASE_PRINCIPALS WHERE name = '#{@db_user}';" run_sql_query(query: query, server: hostname, expected_row_count: 0) - # rubocop:enable RSpec/InstanceVariable end end end diff --git a/spec/acceptance/z_last_sqlserver_features_spec.rb b/spec/acceptance/z_last_sqlserver_features_spec.rb index 6c5bf20f..75881cdb 100644 --- a/spec/acceptance/z_last_sqlserver_features_spec.rb +++ b/spec/acceptance/z_last_sqlserver_features_spec.rb @@ -11,7 +11,7 @@ def ensure_sql_features(features, ensure_val = 'present') user = Helper.instance.run_shell('$env:UserName').stdout.chomp # If no password env variable set (by CI), then default to vagrant password = Helper.instance.run_shell('$env:pass').stdout.chomp - password = password.empty? ? 'vagrant' : password + password = 'vagrant' if password.empty? pp = <<-MANIFEST sqlserver::config{ 'MSSQLSERVER': @@ -156,7 +156,7 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') end it 'fails when ADV_SSMS is supplied but SSMS is not - FM-2712', unless: version.to_i >= 2016 do - pending('error not shown on Sql Server 2014') if version .to_i == 2014 + pending('error not shown on Sql Server 2014') if version.to_i == 2014 features = ['BC', 'Conn', 'ADV_SSMS', 'SDK'] bind_and_apply_failing_manifest(features) end @@ -181,7 +181,7 @@ def remove_sql_instance source => 'H:', sql_sysadmin_accounts => ['#{user}'], } - MANIFEST + MANIFEST idempotent_apply(pp) end diff --git a/spec/defines/config_spec.rb b/spec/defines/config_spec.rb index cde3065d..cd48f323 100644 --- a/spec/defines/config_spec.rb +++ b/spec/defines/config_spec.rb @@ -12,13 +12,13 @@ { instance_name: 'MSSQLSERVER', admin_user: 'sa', - admin_pass: 'Pupp3t1@', + admin_pass: 'Pupp3t1@' } end it { - is_expected.not_to contain_file('C:/ProgramData/PuppetLabs/puppet/var/cache/sqlserver/.MSSQLSERVER.cfg') - is_expected.not_to contain_file('C:/ProgramData/PuppetLabs/puppet/var/cache/sqlserver') + expect(subject).not_to contain_file('C:/ProgramData/PuppetLabs/puppet/var/cache/sqlserver/.MSSQLSERVER.cfg') + expect(subject).not_to contain_file('C:/ProgramData/PuppetLabs/puppet/var/cache/sqlserver') } end @@ -28,14 +28,14 @@ { instance_name: 'MSSQLSERVER', admin_user: 'sa', - admin_login_type: 'SQL_LOGIN', + admin_login_type: 'SQL_LOGIN' } end let(:error_message) { %r{expects admin_pass to be set for a admin_login_type of SQL_LOGIN} } it { - is_expected.not_to compile + expect(subject).not_to compile expect { catalogue }.to raise_error(Puppet::Error, error_message) } end @@ -45,14 +45,14 @@ { instance_name: 'MSSQLSERVER', admin_pass: 'Pupp3t1@', - admin_login_type: 'SQL_LOGIN', + admin_login_type: 'SQL_LOGIN' } end let(:error_message) { %r{expects admin_user to be set for a admin_login_type of SQL_LOGIN} } it { - is_expected.not_to compile + expect(subject).not_to compile expect { catalogue }.to raise_error(Puppet::Error, error_message) } end @@ -64,14 +64,14 @@ { instance_name: 'MSSQLSERVER', admin_user: 'sa', - admin_login_type: 'WINDOWS_LOGIN', + admin_login_type: 'WINDOWS_LOGIN' } end let(:error_message) { %r{expects admin_user to be empty for a admin_login_type of WINDOWS_LOGIN} } it { - is_expected.not_to compile + expect(subject).not_to compile expect { catalogue }.to raise_error(Puppet::Error, error_message) } end @@ -81,14 +81,14 @@ { instance_name: 'MSSQLSERVER', admin_pass: 'Pupp3t1@', - admin_login_type: 'WINDOWS_LOGIN', + admin_login_type: 'WINDOWS_LOGIN' } end let(:error_message) { %r{expects admin_pass to be empty for a admin_login_type of WINDOWS_LOGIN} } it { - is_expected.not_to compile + expect(subject).not_to compile expect { catalogue }.to raise_error(Puppet::Error, error_message) } end diff --git a/spec/defines/database_spec.rb b/spec/defines/database_spec.rb index fde8594e..b0ba5966 100644 --- a/spec/defines/database_spec.rb +++ b/spec/defines/database_spec.rb @@ -10,14 +10,14 @@ let(:params) do { db_name: 'myTestDb', - instance: 'MSSQLSERVER', + instance: 'MSSQLSERVER' } end let(:pre_condition) do <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end end @@ -33,7 +33,7 @@ it_behaves_like 'validation error' do let(:additional_params) do { - filespec_filename: 'c:/test/test.mdf', + filespec_filename: 'c:/test/test.mdf' } end let(:raise_error_check) { %r{filespec_name must also be specified when specifying filespec_filename} } @@ -43,12 +43,13 @@ let(:additional_params) do { filespec_filename: 'c:/test/test.mdf', - filespec_name: 'OMGthisISsoReallyLongAndBoringProcessImeanAReallyOMGthisISsoReallyLongAndBoringProcessMakeItOMGthisISsoReallyLongAndBoringProcess', + filespec_name: 'OMGthisISsoReallyLongAndBoringProcessImeanAReallyOMGthisISsoReallyLongAndBoringProcessMakeItOMGthisISsoReallyLongAndBoringProcess' } end let(:raise_error_check) { "'filespec_name' expects" } end end + it_behaves_like 'sqlserver_tsql command' do let(:additional_params) do { @@ -60,20 +61,21 @@ let(:should_contain_command) do [ %r{NAME = N'myCre-Cre'}, - %r{FILENAME = N'c\:/test/test\.mdf'}, + %r{FILENAME = N'c:/test/test\.mdf'}, %r{NAME = N'myCrazy_Log'}, - %r{FILENAME = N'c\:/test/logfile\.ldf'}, + %r{FILENAME = N'c:/test/logfile\.ldf'}, ] end end end + describe 'collation_name' do let(:additional_params) { { collation_name: 'SQL_Latin1_General_CP1_CI_AS' } } let(:should_contain_command) do [ - %r{\-\-\s*UPDATE SECTION.*ALTER\sDATABASE\s\[myTestDb\]\sCOLLATE\sSQL_Latin1_General_CP1_CI_AS}m, - %r{\-\-\s*CREATE SECTION.*IF\ NOT\ EXISTS\(SELECT\ name\ FROM\ sys\.databases\ WHERE\ name\ =\ 'myTestDb'\ AND\ collation_name\ =\ 'SQL_Latin1_General_CP1_CI_AS'\)}m, - %r{\-\-\s*UPDATE SECTION.*IF\ NOT\ EXISTS\(SELECT\ name\ FROM\ sys\.databases\ WHERE\ name\ =\ 'myTestDb'\ AND\ collation_name\ =\ 'SQL_Latin1_General_CP1_CI_AS'\)}m, + %r{--\s*UPDATE SECTION.*ALTER\sDATABASE\s\[myTestDb\]\sCOLLATE\sSQL_Latin1_General_CP1_CI_AS}m, + %r{--\s*CREATE SECTION.*IF\ NOT\ EXISTS\(SELECT\ name\ FROM\ sys\.databases\ WHERE\ name\ =\ 'myTestDb'\ AND\ collation_name\ =\ 'SQL_Latin1_General_CP1_CI_AS'\)}m, + %r{--\s*UPDATE SECTION.*IF\ NOT\ EXISTS\(SELECT\ name\ FROM\ sys\.databases\ WHERE\ name\ =\ 'myTestDb'\ AND\ collation_name\ =\ 'SQL_Latin1_General_CP1_CI_AS'\)}m, ] end let(:should_contain_onlyif) do @@ -85,22 +87,24 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'filestream failure' do let(:title) { 'myTitle' } let(:params) do { db_name: 'myTestDb', - instance: 'MSSQLSERVER', + instance: 'MSSQLSERVER' } end it 'does not compile' do params[:filestream_directory_name] = 'C:/TestDirectory' expect { - is_expected.to contain_sqlserver_tsql('database-MSSQLSERVER-myTestDb') + expect(subject).to contain_sqlserver_tsql('database-MSSQLSERVER-myTestDb') }.to raise_error(Puppet::Error) end end + describe 'include filestream_non_transacted_access' do let(:additional_params) { { filestream_non_transacted_access: 'FULL' } } let(:should_contain_command) { [%r{FILESTREAM\s+\(\s+NON_TRANSACTED_ACCESS\s+=\s+FULL}] } @@ -109,6 +113,7 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql without_command' end + describe 'should not contain filestream by default' do let(:should_not_contain_command) { [%r{FILESTREAM}] } @@ -138,7 +143,7 @@ %r{WITH\s*DB_CHAINING}m, # Should have no comma between, newlines are fine %r{DEFAULT_FULLTEXT_LANGUAGE=\[English\]\s*,}, # Should enclose default language of us_english in brackets %r{TRUSTWORTHY OFF\s*,}, - %r{\-\- CREATE.*TWO_DIGIT_YEAR_CUTOFF = 2049.*\-\- UPDATE}m, + %r{-- CREATE.*TWO_DIGIT_YEAR_CUTOFF = 2049.*-- UPDATE}m, ] end let(:should_not_contain_command) do @@ -154,42 +159,49 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql without_command' end + describe 'default_fulltext_language' do let(:additional_params) { { containment: 'PARTIAL', default_fulltext_language: 'us_english' } } let(:should_contain_command) { [%r{CONTAINMENT\s=\sPARTIAL}, %r{SET DEFAULT_FULLTEXT_LANGUAGE = \[us_english\]}, %r{,\s*DEFAULT_FULLTEXT_LANGUAGE=\[us_english\]}m] } it_behaves_like 'sqlserver_tsql command' end + describe 'transform_noise_words ON' do let(:additional_params) { { containment: 'PARTIAL', transform_noise_words: 'ON' } } let(:should_contain_command) { [%r{CONTAINMENT\s=\sPARTIAL}, %r{,\s*TRANSFORM_NOISE_WORDS = ON}, %r{SET TRANSFORM_NOISE_WORDS = ON}, %r{is_transform_noise_words_on = 1}] } it_behaves_like 'sqlserver_tsql command' end + describe 'transform_noise_words OFF' do let(:additional_params) { { containment: 'PARTIAL', transform_noise_words: 'OFF' } } let(:should_contain_command) { [%r{CONTAINMENT\s=\sPARTIAL}, %r{,\s*TRANSFORM_NOISE_WORDS = OFF}, %r{SET TRANSFORM_NOISE_WORDS = OFF}, %r{is_transform_noise_words_on = 0}] } it_behaves_like 'sqlserver_tsql command' end + describe 'nested_triggers OFF' do let(:additional_params) { { containment: 'PARTIAL', nested_triggers: 'OFF' } } let(:should_contain_command) { [%r{CONTAINMENT\s=\sPARTIAL}, %r{NESTED_TRIGGERS = OFF}, %r{is_nested_triggers_on = 0}] } it_behaves_like 'sqlserver_tsql command' end + describe 'nested_triggers ON' do let(:additional_params) { { containment: 'PARTIAL', nested_triggers: 'ON' } } let(:should_contain_command) { [%r{CONTAINMENT\s=\sPARTIAL}, %r{NESTED_TRIGGERS = ON}, %r{is_nested_triggers_on = 1}] } it_behaves_like 'sqlserver_tsql command' end + describe 'trustworthy OFF' do let(:additional_params) { { containment: 'PARTIAL', trustworthy: 'OFF' } } let(:should_contain_command) { [%r{CONTAINMENT\s=\sPARTIAL}, %r{,\s*TRUSTWORTHY OFF}, %r{SET TRUSTWORTHY OFF}, %r{is_trustworthy_on = 0}] } it_behaves_like 'sqlserver_tsql command' end + describe 'trustwothy ON' do let(:additional_params) { { containment: 'PARTIAL', trustworthy: 'ON' } } let(:should_contain_command) do @@ -211,6 +223,7 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'db_chainging ON' do let(:additional_params) { { containment: 'PARTIAL', db_chaining: 'ON' } } let(:should_contain_command) do @@ -233,6 +246,7 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'db_chainging OFF' do let(:additional_params) { { containment: 'PARTIAL', db_chaining: 'OFF' } } let(:should_contain_command) do diff --git a/spec/defines/login/permissions_spec.rb b/spec/defines/login/permissions_spec.rb index 8d3be4f3..30f42210 100644 --- a/spec/defines/login/permissions_spec.rb +++ b/spec/defines/login/permissions_spec.rb @@ -8,7 +8,7 @@ <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end context 'validation errors' do @@ -19,7 +19,7 @@ context 'login =>' do let(:params) do { - permissions: ['SELECT'], + permissions: ['SELECT'] } end let(:raise_error_check) { %r{'login' expects a String.+ value} } @@ -32,21 +32,24 @@ end it_behaves_like 'validation error' end + describe 'empty' do let(:additional_params) { { login: '' } } it_behaves_like 'validation error' end + describe 'over limit' do let(:additional_params) { { login: random_string_of_size(129) } } it_behaves_like 'validation error' end end + context 'permissions' do let(:params) do { - login: 'loggingUser', + login: 'loggingUser' } end let(:raise_error_check) { %r{'permissions' .+ expects a String.+ value} } @@ -56,22 +59,25 @@ it_behaves_like 'validation error' end + describe 'under limit' do let(:additional_params) { { permissions: [random_string_of_size(3, false)] } } it_behaves_like 'validation error' end + describe 'over limit' do let(:additional_params) { { permissions: [random_string_of_size(129, false)] } } it_behaves_like 'validation error' end end + context 'state =>' do let(:params) do { permissions: ['SELECT'], - login: 'loggingUser', + login: 'loggingUser' } end @@ -83,6 +89,7 @@ end end end + context 'successfully' do include_context 'manifests' do let(:title) { 'myTitle' } @@ -90,7 +97,7 @@ let(:params) do { login: 'loggingUser', - permissions: ['SELECT'], + permissions: ['SELECT'] } end end @@ -123,6 +130,7 @@ it_behaves_like 'sqlserver_tsql command' end + describe 'alter' do let(:additional_params) { { permissions: ['ALTER'] } } let(:should_contain_command) { ['USE [master];', 'GRANT ALTER TO [loggingUser];'] } @@ -137,7 +145,7 @@ <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end it_behaves_like 'compile' @@ -151,7 +159,7 @@ let(:params) do { login: 'loggingUser', - permissions: ['SELECT'], + permissions: ['SELECT'] } end diff --git a/spec/defines/login_spec.rb b/spec/defines/login_spec.rb index 0559ee61..28cb4297 100644 --- a/spec/defines/login_spec.rb +++ b/spec/defines/login_spec.rb @@ -10,22 +10,23 @@ let(:params) do { login: 'myTitle', - instance: 'MSSQLSERVER', + instance: 'MSSQLSERVER' } end let(:pre_condition) do <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end end describe 'Minimal Params' do it 'compiles' do - is_expected.to contain_sqlserver_tsql('login-MSSQLSERVER-myTitle') + expect(subject).to contain_sqlserver_tsql('login-MSSQLSERVER-myTitle') end end + describe 'parameter assignment' do let(:should_contain_command) do [ @@ -49,17 +50,19 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'check_policy' do let(:additional_params) { { check_policy: false, check_expiration: true } } let(:raise_error_check) { 'Can not have check expiration enabled when check_policy is disabled' } it_behaves_like 'validation error' end + context 'permissions =>' do let(:title) { 'myTitle' } let(:params) do { - login: 'myLogin', + login: 'myLogin' } end let(:permissions) { {} } @@ -68,7 +71,7 @@ it { params[:permissions] = permissions type_title = ((type =~ %r{GRANT_WITH_OPTION}i) ? 'GRANT-WITH_GRANT_OPTION' : type.upcase) - is_expected.to contain_sqlserver__login__permissions("Sqlserver::Login[#{title}]-#{type_title}-myLogin").with( + expect(subject).to contain_sqlserver__login__permissions("Sqlserver::Login[#{title}]-#{type_title}-myLogin").with( 'login' => 'myLogin', 'state' => (type == 'GRANT_WITH_OPTION') ? 'GRANT' : type.upcase, 'with_grant_option' => type == 'GRANT_WITH_OPTION', @@ -82,7 +85,7 @@ it { params[:permissions] = permissions type_title = ((type =~ %r{GRANT_WITH_OPTION}i) ? 'GRANT-WITH_GRANT_OPTION' : type.upcase) - is_expected.not_to contain_sqlserver__login__permissions("Sqlserver::Login[#{title}]-#{type_title}-myLogin") + expect(subject).not_to contain_sqlserver__login__permissions("Sqlserver::Login[#{title}]-#{type_title}-myLogin") } end @@ -128,7 +131,7 @@ describe 'duplicate permissions' do let(:additional_params) do { - permissions: { 'GRANT' => ['CONNECT SQL'], 'REVOKE' => ['CONNECT SQL'] }, + permissions: { 'GRANT' => ['CONNECT SQL'], 'REVOKE' => ['CONNECT SQL'] } } end let(:raise_error_check) { "Duplicate permissions found for sqlserver::login[#{title}" } diff --git a/spec/defines/manifest_shared_examples.rb b/spec/defines/manifest_shared_examples.rb index 9e4f7b6a..46d9ad65 100644 --- a/spec/defines/manifest_shared_examples.rb +++ b/spec/defines/manifest_shared_examples.rb @@ -14,6 +14,7 @@ def convert_to_regexp(str) return str if str.is_a? Regexp + Regexp.new(Regexp.escape(str)) end @@ -21,7 +22,7 @@ def convert_to_regexp(str) it { params.merge!(additional_params) should_contain_onlyif.each do |check| - is_expected.to contain_sqlserver_tsql(sqlserver_tsql_title).with_onlyif(convert_to_regexp(check)) + expect(subject).to contain_sqlserver_tsql(sqlserver_tsql_title).with_onlyif(convert_to_regexp(check)) end } end @@ -29,7 +30,7 @@ def convert_to_regexp(str) it { params.merge!(additional_params) should_not_contain_onlyif.each do |check| - is_expected.to contain_sqlserver_tsql(sqlserver_tsql_title).with_onlyif(convert_to_regexp(check)) + expect(subject).to contain_sqlserver_tsql(sqlserver_tsql_title).with_onlyif(convert_to_regexp(check)) end } end @@ -38,7 +39,7 @@ def convert_to_regexp(str) it { params.merge!(additional_params) should_contain_command.each do |check| - is_expected.to contain_sqlserver_tsql(sqlserver_tsql_title).with_command(convert_to_regexp(check)) + expect(subject).to contain_sqlserver_tsql(sqlserver_tsql_title).with_command(convert_to_regexp(check)) end } end @@ -47,7 +48,7 @@ def convert_to_regexp(str) it { params.merge!(additional_params) should_not_contain_command.each do |check| - is_expected.not_to contain_sqlserver_tsql(sqlserver_tsql_title).with_command(convert_to_regexp(check)) + expect(subject).not_to contain_sqlserver_tsql(sqlserver_tsql_title).with_command(convert_to_regexp(check)) end } end @@ -55,7 +56,7 @@ def convert_to_regexp(str) shared_examples 'compile' do it { params.merge!(additional_params) - is_expected.to compile + expect(subject).to compile } end diff --git a/spec/defines/role/permissions_spec.rb b/spec/defines/role/permissions_spec.rb index 67d4a3d1..6e3738e8 100644 --- a/spec/defines/role/permissions_spec.rb +++ b/spec/defines/role/permissions_spec.rb @@ -10,7 +10,7 @@ let(:params) do { role: 'myCustomRole', - permissions: ['INSERT', 'UPDATE', 'DELETE', 'SELECT'], + permissions: ['INSERT', 'UPDATE', 'DELETE', 'SELECT'] } end end @@ -33,13 +33,14 @@ let(:params) do { role: 'myCustomRole', - permissions: ['INSERT', 'UPDATE', 'DELETE', 'SELECT'], + permissions: ['INSERT', 'UPDATE', 'DELETE', 'SELECT'] } end it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + context 'type =>' do shared_examples 'GRANT Permissions' do |type| base_commands = [ @@ -61,7 +62,6 @@ 'GRANT DELETE TO [myCustomRole];', 'GRANT SELECT TO [myCustomRole];', ] - # rubocop:enable Layout/IndentArray let(:should_contain_command) { base_commands + should_commands } let(:should_contain_onlyif) { base_commands } @@ -72,7 +72,7 @@ describe 'DATABASE' do let(:additional_params) do { - type: 'DATABASE', + type: 'DATABASE' } end @@ -82,7 +82,7 @@ describe 'SERVER' do let(:additional_params) do { - type: 'SERVER', + type: 'SERVER' } end @@ -112,17 +112,18 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe '[]' do let(:params) do { role: 'myCustomRole', - permissions: [], + permissions: [] } end it { - is_expected.to compile - is_expected.not_to contain_sqlserver_tsql(sqlserver_tsql_title) + expect(subject).to compile + expect(subject).not_to contain_sqlserver_tsql(sqlserver_tsql_title) } end end @@ -135,6 +136,7 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'customDatabase' do let(:additional_params) { { database: 'customDatabase' } } let(:should_contain_command) { ['USE [customDatabase];'] } @@ -157,12 +159,12 @@ { role: 'myCustomRole', permissions: ['INSERT', 'UPDATE', 'DELETE', 'SELECT'], - instance: instance, + instance: instance } end it { - is_expected.to contain_sqlserver_tsql("role-permissions-myCustomRole-GRANT-#{instance}-master").with_instance(instance) + expect(subject).to contain_sqlserver_tsql("role-permissions-myCustomRole-GRANT-#{instance}-master").with_instance(instance) } end end diff --git a/spec/defines/role_spec.rb b/spec/defines/role_spec.rb index e19f4343..82ebaf32 100644 --- a/spec/defines/role_spec.rb +++ b/spec/defines/role_spec.rb @@ -13,13 +13,14 @@ describe 'invalid' do let(:additional_params) do { - type: 'invalid', + type: 'invalid' } end let(:raise_error_check) { "'type' expects" } it_behaves_like 'validation error' end + describe 'SERVER' do let(:should_contain_command) do [ @@ -39,10 +40,11 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'DATABASE' do let(:additional_params) do { - 'type' => 'DATABASE', + 'type' => 'DATABASE' } end let(:should_contain_command) do @@ -68,7 +70,7 @@ context 'database =>' do let(:additional_params) do { - 'database' => 'myCrazyDb', + 'database' => 'myCrazyDb' } end let(:sqlserver_tsql_title) { 'role-MSSQLSERVER-myCrazyDb-myCustomRole' } @@ -78,11 +80,12 @@ it_behaves_like 'validation error' end + describe 'with database role type' do let(:additional_params) do { 'database' => 'myCrazyDb', - 'type' => 'DATABASE', + 'type' => 'DATABASE' } end let(:should_contain_command) do @@ -100,9 +103,10 @@ let(:params) { { instance: 'MYCUSTOM' } } it { - is_expected.to contain_sqlserver_tsql('role-MYCUSTOM-master-myCustomRole').with_instance('MYCUSTOM') + expect(subject).to contain_sqlserver_tsql('role-MYCUSTOM-master-myCustomRole').with_instance('MYCUSTOM') } end + describe 'empty instance' do let(:additional_params) { { 'instance' => '' } } let(:raise_error_check) { "instance' expects a String[1, 16]" } @@ -122,10 +126,11 @@ it_behaves_like 'sqlserver_tsql without_command' end + describe 'myUser' do let(:additional_params) do { - authorization: 'myUser', + authorization: 'myUser' } end let(:should_contain_command) do @@ -137,11 +142,12 @@ it_behaves_like 'sqlserver_tsql command' end + describe 'myUser on Database' do let(:additional_params) do { authorization: 'myUser', - type: 'DATABASE', + type: 'DATABASE' } end let(:should_contain_command) do @@ -159,7 +165,7 @@ describe 'absent' do let(:additional_params) do { - ensure: 'absent', + ensure: 'absent' } end let(:should_contain_command) do @@ -178,6 +184,7 @@ it_behaves_like 'sqlserver_tsql onlyif' end end + context 'members_purge =>' do let(:sqlserver_tsql_title) { 'role-MSSQLSERVER-master-myCustomRole-members' } @@ -185,7 +192,7 @@ describe 'type => SERVER and members => []' do let(:additional_params) do { - members_purge: true, + members_purge: true } end let(:should_contain_command) do @@ -215,7 +222,7 @@ let(:additional_params) do { type: 'DATABASE', - members_purge: true, + members_purge: true } end let(:should_contain_command) do @@ -241,11 +248,12 @@ it_behaves_like 'sqlserver_tsql onlyif' end end + describe '[test these users]' do let(:additional_params) do { members_purge: true, - members: ['test', 'these', 'users'], + members: ['test', 'these', 'users'] } end let(:should_contain_command) do @@ -261,11 +269,8 @@ ] end - # rubocop:enable Style/RegexpLiteral it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end end - # rubocop:enable RSpec/EmptyLineAfterFinalLet - # rubocop:enable Layout/IndentArray end diff --git a/spec/defines/sp_configure_spec.rb b/spec/defines/sp_configure_spec.rb index 0b15e941..1c959407 100644 --- a/spec/defines/sp_configure_spec.rb +++ b/spec/defines/sp_configure_spec.rb @@ -10,14 +10,14 @@ let(:params) do { config_name: 'filestream access level', - value: 1, + value: 1 } end let(:pre_condition) do <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end end describe 'basic usage' do @@ -43,7 +43,7 @@ describe 'reconfigure => false' do let(:additional_params) do { - reconfigure: false, + reconfigure: false } end let(:should_not_contain_command) do @@ -73,7 +73,7 @@ describe 'with_override => false' do let(:additional_params) do { - with_override: false, + with_override: false } end let(:should_not_contain_command) do @@ -96,7 +96,7 @@ describe 'service' do it 'is defined' do - is_expected.to contain_exec('restart-service-MSSQLSERVER-filestream access level').with_refreshonly(true) + expect(subject).to contain_exec('restart-service-MSSQLSERVER-filestream access level').with_refreshonly(true) end end end diff --git a/spec/defines/user/permissions_spec.rb b/spec/defines/user/permissions_spec.rb index 0c1f5def..dc1ffbdc 100644 --- a/spec/defines/user/permissions_spec.rb +++ b/spec/defines/user/permissions_spec.rb @@ -8,7 +8,7 @@ <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end context 'validation errors' do @@ -20,7 +20,7 @@ let(:params) do { permissions: ['SELECT'], - database: 'loggingDb', + database: 'loggingDb' } end let(:raise_error_check) { "'user' expects a String[1, 128] value" } @@ -30,22 +30,25 @@ it_behaves_like 'validation error' end + describe 'empty' do let(:additional_params) { { user: '' } } it_behaves_like 'validation error' end + describe 'over limit' do let(:additional_params) { { user: random_string_of_size(129) } } it_behaves_like 'validation error' end end + context 'permissions' do let(:params) do { user: 'loggingUser', - database: 'loggingDb', + database: 'loggingDb' } end let(:raise_error_check) { %r{'permissions' .+ expects a String.+ value} } @@ -56,23 +59,26 @@ it_behaves_like 'validation error' end + describe 'under limit' do let(:additional_params) { { permissions: [random_string_of_size(3, false)] } } it_behaves_like 'validation error' end + describe 'over limit' do let(:additional_params) { { permissions: [random_string_of_size(129, false)] } } it_behaves_like 'validation error' end end + context 'state =>' do let(:params) do { permissions: ['SELECT'], database: 'loggingDb', - user: 'loggingUser', + user: 'loggingUser' } end @@ -83,12 +89,13 @@ it_behaves_like 'validation error' end end - context 'with_grant_option => ' do + + context 'with_grant_option =>' do let(:params) do { permissions: ['SELECT'], database: 'loggingDb', - user: 'loggingUser', + user: 'loggingUser' } end @@ -98,6 +105,7 @@ it_behaves_like 'validation error' end + describe 'invalid' do let(:additional_params) { { with_grant_option: 'invalid' } } let(:raise_error_check) { "'with_grant_option' expects" } @@ -106,6 +114,7 @@ end end end + context 'successfully' do include_context 'manifests' do let(:title) { 'myTitle' } @@ -114,7 +123,7 @@ { user: 'loggingUser', permissions: ['SELECT'], - database: 'loggingDb', + database: 'loggingDb' } end end @@ -147,6 +156,7 @@ it_behaves_like 'sqlserver_tsql command' end + describe 'alter' do let(:additional_params) { { permissions: ['ALTER'] } } let(:should_contain_command) { ['USE [loggingDb];', 'GRANT ALTER TO [loggingUser];'] } @@ -161,7 +171,7 @@ <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end let(:should_contain_command) { ['USE [loggingDb];'] } @@ -189,6 +199,7 @@ it_behaves_like 'sqlserver_tsql without_command' it_behaves_like 'sqlserver_tsql onlyif' end + describe 'false' do let(:should_contain_command) do [ @@ -214,7 +225,7 @@ { user: 'loggingUser', permissions: ['SELECT'], - database: 'loggingDb', + database: 'loggingDb' } end diff --git a/spec/defines/user_spec.rb b/spec/defines/user_spec.rb index 858016fe..81693ee8 100644 --- a/spec/defines/user_spec.rb +++ b/spec/defines/user_spec.rb @@ -12,7 +12,7 @@ <<-EOF define sqlserver::config{} sqlserver::config {'MSSQLSERVER': } - EOF + EOF end end @@ -116,7 +116,7 @@ let(:should_contain_command) do [ 'USE [myDatabase]', - /CREATE USER \[myMachineName\/myUser\]\n\s+FROM LOGIN \[myMachineName\/myUser\]/, + %r{CREATE USER \[myMachineName/myUser\]\n\s+FROM LOGIN \[myMachineName/myUser\]}, ] end @@ -125,7 +125,7 @@ describe 'have dependency on Sqlserver::Config[MSSQLSERVER]' do it 'requires ::config' do - is_expected.to contain_sqlserver_tsql(sqlserver_tsql_title).with_require('Sqlserver::Config[MSSQLSERVER]') + expect(subject).to contain_sqlserver_tsql(sqlserver_tsql_title).with_require('Sqlserver::Config[MSSQLSERVER]') end end @@ -146,6 +146,7 @@ it_behaves_like 'sqlserver_tsql command' it_behaves_like 'sqlserver_tsql onlyif' end + context 'permissions =>' do let(:title) { 'myTitle' } let(:params) { { user: 'loggingUser', database: 'myDatabase' } } @@ -155,7 +156,7 @@ it { params[:permissions] = permissions type_title = ((type =~ %r{GRANT_WITH_OPTION}i) ? 'GRANT-WITH_GRANT_OPTION' : type.upcase) - is_expected.to contain_sqlserver__user__permissions("Sqlserver::User[#{title}]-#{type_title}-loggingUser").with( + expect(subject).to contain_sqlserver__user__permissions("Sqlserver::User[#{title}]-#{type_title}-loggingUser").with( 'user' => 'loggingUser', 'database' => 'myDatabase', 'state' => (type == 'GRANT_WITH_OPTION') ? 'GRANT' : type.upcase, @@ -170,7 +171,7 @@ it { params[:permissions] = permissions type_title = ((type =~ %r{GRANT_WITH_OPTION}i) ? 'GRANT-WITH_GRANT_OPTION' : type.upcase) - is_expected.not_to contain_sqlserver__user__permissions("Sqlserver::User[#{title}]-#{type_title}-loggingUser") + expect(subject).not_to contain_sqlserver__user__permissions("Sqlserver::User[#{title}]-#{type_title}-loggingUser") } end @@ -216,7 +217,7 @@ describe 'duplicate permissions' do let(:additional_params) do { - permissions: { 'GRANT' => ['CONNECT SQL'], 'REVOKE' => ['CONNECT SQL'] }, + permissions: { 'GRANT' => ['CONNECT SQL'], 'REVOKE' => ['CONNECT SQL'] } } end let(:raise_error_check) { "Duplicate permissions found for sqlserver::user[#{title}" } diff --git a/spec/functions/sqlserver_upcase_spec.rb b/spec/functions/sqlserver_upcase_spec.rb index 884809b3..7a0b0120 100644 --- a/spec/functions/sqlserver_upcase_spec.rb +++ b/spec/functions/sqlserver_upcase_spec.rb @@ -38,11 +38,13 @@ class AlsoString < String scope.function_sqlserver_upcase([{ test: [:this, :that, :other] }]), ).to eq(TEST: [:THIS, :THAT, :OTHER]) end + it 'returns upcase symbol' do expect( scope.function_sqlserver_upcase([:test]), ).to eq(:TEST) end + it 'returns mixed objects in upcease' do expect( scope.function_sqlserver_upcase([[:test, 'woot']]), diff --git a/spec/functions/sqlserver_validate_size_spec.rb b/spec/functions/sqlserver_validate_size_spec.rb index 1eea650c..a6a88414 100644 --- a/spec/functions/sqlserver_validate_size_spec.rb +++ b/spec/functions/sqlserver_validate_size_spec.rb @@ -35,6 +35,7 @@ describe 'when giving a decimal value' do it_behaves_like 'should raise error', "0.2#{measure}", %r{Number must be an integer} end + describe 'when giving a value larger than 2147483647' do it_behaves_like 'should raise error', "2147483648#{measure}", %r{Please use larger measurement for values greater than 2147483647} end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 20239e64..ec79997f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -9,11 +9,11 @@ require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) -include RspecPuppetFacts +include RspecPuppetFacts # rubocop:disable Style/MixinUsage 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 eb68be52..7d46cc36 100644 --- a/spec/spec_helper_acceptance_local.rb +++ b/spec/spec_helper_acceptance_local.rb @@ -23,13 +23,13 @@ class Helper RSpec.configure do |c| c.before(:suite) do - Helper.instance.run_shell('puppet module install puppetlabs/mount_iso') + Helper.instance.run_shell('puppet module install puppetlabs-mount_iso') Helper.instance.run_shell('puppet module install puppet/archive') iso_opts = { folder: WIN_ISO_ROOT, file: WIN_2019_ISO, - drive_letter: 'I', + drive_letter: 'I' } # Allows litmus to use SSH, by explicitly setting specinfra # os family to windows (would fail when using ssh on windows) @@ -46,20 +46,15 @@ def node_vars? hash['groups'].each do |group| group['targets'].each do |node| - if ENV['TARGET_HOST'] == node['uri'] - return node['vars'] - end + return node['vars'] if ENV['TARGET_HOST'] == node['uri'] end end end def sql_version? vars = node_vars? - unless vars.nil? - if vars['sqlversion'] - return vars['sqlversion'].match(%r{sqlserver_(.*)})[1] - end - end + return vars['sqlversion'].match(%r{sqlserver_(.*)})[1] if !vars.nil? && (vars['sqlversion']) + # Return's a default version if none was given '2019' end @@ -95,31 +90,31 @@ def base_install(sql_version) iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2012_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2014 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2014_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2016 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2016_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2017 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2017_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2019 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2019_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2022 iso_opts = { @@ -156,7 +151,7 @@ def install_sqlserver(features) }, windows_feature_source => 'I:\\sources\\sxs', } - MANIFEST + MANIFEST Helper.instance.apply_manifest(pp) end @@ -168,19 +163,17 @@ def run_sql_query(opts = {}, &block) sql_admin_user = opts[:sql_admin_user] ||= SQL_ADMIN_USER powershell = <<-EOS - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\110\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\120\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\130\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\140\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\140\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\150\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\170\\Tools\\Binn\\" - sqlcmd.exe -S #{server}\\#{instance} -U #{sql_admin_user} -P #{sql_admin_pass} -Q \"#{query}\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\110\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\120\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\130\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\140\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\140\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\150\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\170\\Tools\\Binn\\" + sqlcmd.exe -S #{server}\\#{instance} -U #{sql_admin_user} -P #{sql_admin_pass} -Q "#{query}" EOS # sqlcmd has problem authenticate to sqlserver if the instance is the default one MSSQLSERVER # Below is a work-around for it (remove "-S server\instance" from the connection string) - if instance.nil? || instance == 'MSSQLSERVER' - powershell.dup.gsub!("-S #{server}\\#{instance}", '') - end + powershell.dup.gsub!("-S #{server}\\#{instance}", '') if instance.nil? || instance == 'MSSQLSERVER' Tempfile.open 'tmp.ps1' do |tempfile| File.open(tempfile.path, 'w') { |file| file.puts powershell } @@ -191,11 +184,13 @@ def run_sql_query(opts = {}, &block) Helper.instance.run_shell("powershell -NonInteractive -NoLogo -File 'c:\\users\\#{USER}\\tmp.ps1'") do |r| match = %r{(\d*) rows affected}.match(r.stdout) raise 'Could not match number of rows for SQL query' unless match + rows_observed = match[1] error_message = "Expected #{opts[:expected_row_count]} rows but observed #{rows_observed}" raise error_message unless opts[:expected_row_count] == rows_observed.to_i end return unless block + case block.arity when 0 yield self @@ -215,6 +210,7 @@ def validate_sql_install(opts = {}, &block) cmd = "type \"#{bootstrap_dir}\\Log\\Summary.txt\"" result = Helper.instance.run_shell(cmd) return unless block + case block.arity when 0 yield self @@ -226,16 +222,14 @@ def validate_sql_install(opts = {}, &block) def get_install_paths(version) vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150', '2022' => '160' } - raise _('Valid version must be specified') unless vers.keys.include?(version) + raise _('Valid version must be specified') unless vers.key?(version) dir = "C://Program Files/Microsoft SQL Server/#{vers[version]}/Setup Bootstrap" sql_directory = case version - when '2022' + when '2022', '2017' "SQL#{version}" when '2019' "SQL#{version}CTP2.4" - when '2017' - "SQL#{version}" else "SQLServer#{version}" end diff --git a/spec/sql_testing_helpers.rb b/spec/sql_testing_helpers.rb index 79d215f6..55a986b8 100644 --- a/spec/sql_testing_helpers.rb +++ b/spec/sql_testing_helpers.rb @@ -44,7 +44,7 @@ def install_sqlserver(host, opts = {}) }, windows_feature_source => 'I:\\sources\\sxs', } - MANIFEST + MANIFEST apply_manifest_on(host, pp) end @@ -56,30 +56,30 @@ def run_sql_query(host, opts = {}, &block) sql_admin_user = opts[:sql_admin_user] ||= SQL_ADMIN_USER powershell = <<-EOS - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\110\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\120\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\130\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\140\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\140\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\150\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\" - $Env:Path +=\";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\170\\Tools\\Binn\\" - sqlcmd.exe -S #{server}\\#{instance} -U #{sql_admin_user} -P #{sql_admin_pass} -Q \"#{query}\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\110\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\120\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\130\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\140\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\140\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\150\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\" + $Env:Path +=";C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn;C:\\Program Files\\Microsoft SQL Server\\170\\Tools\\Binn\\" + sqlcmd.exe -S #{server}\\#{instance} -U #{sql_admin_user} -P #{sql_admin_pass} -Q "#{query}" EOS # sqlcmd has problem authenticate to sqlserver if the instance is the default one MSSQLSERVER # Below is a work-around for it (remove "-S server\instance" from the connection string) - if instance.nil? || instance == 'MSSQLSERVER' - powershell.gsub!("-S #{server}\\#{instance}", '') - end + powershell.gsub!("-S #{server}\\#{instance}", '') if instance.nil? || instance == 'MSSQLSERVER' create_remote_file(host, 'tmp.ps1', powershell) on(host, 'powershell -NonInteractive -NoLogo -File "C:\\cygwin64\\home\\Administrator\\tmp.ps1"') do |r| match = %r{(\d*) rows affected}.match(r.stdout) raise 'Could not match number of rows for SQL query' unless match + rows_observed = match[1] error_message = "Expected #{opts[:expected_row_count]} rows but observed #{rows_observed}" raise error_message unless opts[:expected_row_count] == rows_observed.to_i end return unless block + case block.arity when 0 yield self @@ -94,31 +94,31 @@ def base_install(sql_version) iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2012_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2014 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2014_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2016 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2016_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2017 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2017_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2019 iso_opts = { folder: QA_RESOURCE_ROOT, file: SQL_2019_ISO, - drive_letter: 'H', + drive_letter: 'H' } when 2022 iso_opts = { @@ -145,6 +145,7 @@ def validate_sql_install(host, opts = {}, &block) cmd = "type \\\"#{bootstrap_dir}\\Log\\Summary.txt\\\"" result = on(host, "cmd.exe /c \"#{cmd}\"") return unless block + case block.arity when 0 yield self @@ -170,16 +171,14 @@ def remove_sql_instances(host, opts = {}) def get_install_paths(version) vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150', '2022' => '160' } - raise _('Valid version must be specified') unless vers.keys.include?(version) + raise _('Valid version must be specified') unless vers.key?(version) dir = "C://Program Files/Microsoft SQL Server/#{vers[version]}/Setup Bootstrap" sql_directory = case version - when '2022' + when '2022', '2017' "SQL#{version}" when '2019' "SQL#{version}CTP2.4" - when '2017' - "SQL#{version}" else "SQLServer#{version}" end @@ -189,19 +188,19 @@ def get_install_paths(version) def install_pe_license(host) # Init - license = <<-EOF -####################### -# Begin License File # -####################### -# PUPPET ENTERPRISE LICENSE - Puppet Labs -to: qa -nodes: 100 -start: 2016-03-31 -end: 2026-03-31 -##################### -# End License File # -##################### -EOF + license = <<~EOF + ####################### + # Begin License File # + ####################### + # PUPPET ENTERPRISE LICENSE - Puppet Labs + to: qa + nodes: 100 + start: 2016-03-31 + end: 2026-03-31 + ##################### + # End License File # + ##################### + EOF create_remote_file(host, '/etc/puppetlabs/license.key', license) end diff --git a/spec/unit/puppet/property/tsql_spec.rb b/spec/unit/puppet/property/tsql_spec.rb index c7cbf49f..8946836c 100644 --- a/spec/unit/puppet/property/tsql_spec.rb +++ b/spec/unit/puppet/property/tsql_spec.rb @@ -12,6 +12,7 @@ expect(@node[:command]).to match(%r{BEGIN TRY}) expect(@node[:command]).to include('UPDATE [my_login] SET PASSWORD = "MYSillyPassword"') } + it 'munges value to have begin and end try' do @node[:command] = 'function foo' @node[:onlyif] = 'exec bar' @@ -21,6 +22,6 @@ it 'properlies escape single quotes in queries' do @node[:command] = 'SELECT \'FOO\'' - expect(@node[:command]).to match(%r{SET @sql_text = N'SELECT \'\'FOO\'\'}) + expect(@node[:command]).to match(%r{SET @sql_text = N'SELECT ''FOO''}) end end diff --git a/spec/unit/puppet/provider/sqlserver_features_spec.rb b/spec/unit/puppet/provider/sqlserver_features_spec.rb index f0af0856..a4f6220f 100644 --- a/spec/unit/puppet/provider/sqlserver_features_spec.rb +++ b/spec/unit/puppet/provider/sqlserver_features_spec.rb @@ -15,7 +15,7 @@ { name: 'Base features', source: 'C:\myinstallexecs', - features: ['BC', 'SSMS'], + features: ['BC', 'SSMS'] } end let(:additional_params) { {} } @@ -41,7 +41,7 @@ @feature_params = { name: 'Base features', source: 'C:\myinstallexecs', - features: ['BC', 'SSMS'], + features: ['BC', 'SSMS'] } let(:feature_remove) { [] } let(:feature_add) { [] } @@ -60,6 +60,7 @@ allow(@file_double).to receive(:close) allow(Tempfile).to receive(:new).with(['sqlconfig', '.ini']).and_return(@file_double) end + it_behaves_like 'create' do let(:additional_params) { { install_switches: { 'ERRORREPORTING' => 1, 'SQLBACKUPDIR' => 'I:\DBbackup' } } } let(:additional_switches) { ["/ConfigurationFile=\"#{@file_double.path}\""] } @@ -80,12 +81,8 @@ stub_powershell_call(provider_class_ut) stub_source_which_call args - unless feature_remove.empty? - stub_remove_features(args, feature_remove, exit_code || 0) - end - unless feature_add.empty? - stub_add_features(args, feature_add, [], exit_code || 0) - end + stub_remove_features(args, feature_remove, exit_code || 0) unless feature_remove.empty? + stub_add_features(args, feature_add, [], exit_code || 0) unless feature_add.empty? # If warning_matcher supplied ensure warnings raised match, otherwise no warnings raised allow(@provider).to receive(:warn).with(match(warning_matcher)).and_return(nil) if warning_matcher @@ -145,7 +142,7 @@ feature_params = { name: 'Base features', source: 'C:\myinstallexecs', - features: [], + features: [] } @resource = Puppet::Type::Sqlserver_features.new(feature_params) @provider = provider_class.new(@resource) @@ -157,7 +154,7 @@ '/ACTION=uninstall', '/Q', '/IACCEPTSQLSERVERLICENSETERMS', - "/FEATURES=#{['SSMS', 'ADV_SSMS', 'Conn'].join(',')}"], failonfail: false + "/FEATURES=#{['SSMS', 'ADV_SSMS', 'Conn'].join(',')}"], { failonfail: false } ).and_return(result) @provider.create } @@ -171,6 +168,5 @@ let(:feature_add) { ['BC', 'IS', 'SSMS'] } it_behaves_like 'features=', @feature_params - # rubocop:enable RSpec/InstanceVariable end end diff --git a/spec/unit/puppet/provider/sqlserver_instance_spec.rb b/spec/unit/puppet/provider/sqlserver_instance_spec.rb index 2378cd0e..67edab38 100644 --- a/spec/unit/puppet/provider/sqlserver_instance_spec.rb +++ b/spec/unit/puppet/provider/sqlserver_instance_spec.rb @@ -16,18 +16,18 @@ let(:resourcekey_to_cmdarg) do { 'agt_svc_account' => 'AGTSVCACCOUNT', - 'agt_svc_password' => 'AGTSVCPASSWORD', - 'as_svc_account' => 'ASSVCACCOUNT', - 'as_svc_password' => 'ASSVCPASSWORD', - 'pid' => 'PID', - 'rs_svc_account' => 'RSSVCACCOUNT', - 'rs_svc_password' => 'RSSVCPASSWORD', - 'polybase_svc_account' => 'PBENGSVCACCOUNT', + 'agt_svc_password' => 'AGTSVCPASSWORD', + 'as_svc_account' => 'ASSVCACCOUNT', + 'as_svc_password' => 'ASSVCPASSWORD', + 'pid' => 'PID', + 'rs_svc_account' => 'RSSVCACCOUNT', + 'rs_svc_password' => 'RSSVCPASSWORD', + 'polybase_svc_account' => 'PBENGSVCACCOUNT', 'polybase_svc_password' => 'PBDMSSVCPASSWORD', - 'sa_pwd' => 'SAPWD', - 'security_mode' => 'SECURITYMODE', - 'sql_svc_account' => 'SQLSVCACCOUNT', - 'sql_svc_password' => 'SQLSVCPASSWORD', + 'sa_pwd' => 'SAPWD', + 'security_mode' => 'SECURITYMODE', + 'sql_svc_account' => 'SQLSVCACCOUNT', + 'sql_svc_password' => 'SQLSVCPASSWORD' } end @@ -40,7 +40,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) "/FEATURES=#{installed_features.join(',')}"] result = Puppet::Util::Execution::ProcessOutput.new('', exit_code) - allow(Puppet::Util::Execution).to receive(:execute).with(cmd_args.compact, failonfail: false).and_return(result) + allow(Puppet::Util::Execution).to receive(:execute).with(cmd_args.compact, { failonfail: false }).and_return(result) end shared_examples 'create' do |exit_code, warning_matcher| @@ -67,7 +67,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) # Extrace the SQL Sysadmins admin_args = execute_args[:sql_sysadmin_accounts].map(&:to_s) # prepend first arg only with CLI switch - admin_args[0] = '/SQLSYSADMINACCOUNTS=' + admin_args[0] + admin_args[0] = "/SQLSYSADMINACCOUNTS=#{admin_args[0]}" cmd_args += admin_args additional_install_switches.each do |switch| @@ -78,7 +78,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) allow(@provider).to receive(:warn).with(anything) unless warning_matcher result = Puppet::Util::Execution::ProcessOutput.new('', exit_code || 0) - allow(Puppet::Util::Execution).to receive(:execute).with(cmd_args.compact, failonfail: false).and_return(result) + allow(Puppet::Util::Execution).to receive(:execute).with(cmd_args.compact, { failonfail: false }).and_return(result) @provider.create } end @@ -107,7 +107,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) # wrap each arg in doublequotes admin_args = execute_args[:sql_sysadmin_accounts].map { |a| "\"#{a}\"" } # prepend first arg only with CLI switch - admin_args[0] = '/SQLSYSADMINACCOUNTS=' + admin_args[0] + admin_args[0] = "/SQLSYSADMINACCOUNTS=#{admin_args[0]}" cmd_args += admin_args additional_install_switches.each do |switch| @@ -117,7 +117,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) allow(@provider).to receive(:warn).with(anything) result = Puppet::Util::Execution::ProcessOutput.new('', exit_code || 0) - allow(Puppet::Util::Execution).to receive(:execute).with(cmd_args.compact, failonfail: false).and_return(result) + allow(Puppet::Util::Execution).to receive(:execute).with(cmd_args.compact, { failonfail: false }).and_return(result) expect { @provider.create }.to raise_error(error_matcher) } end @@ -228,7 +228,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) { name: 'MYSQLSERVER', source: 'C:\myinstallexecs', - features: [], + features: [] } end end @@ -240,7 +240,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) { name: 'MYSQLSERVER', source: 'C:\myinstallexecs', - features: [], + features: [] } end let(:installed_features) { ['SQLEngine', 'Replication'] } @@ -253,7 +253,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) { name: 'MYSQLSERVER', source: 'C:\myinstallexecs', - features: [], + features: [] } end let(:installed_features) { ['SQLEngine', 'Replication'] } @@ -266,7 +266,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) { name: 'MYSQLSERVER', source: 'C:\myinstallexecs', - features: [], + features: [] } end let(:installed_features) { ['SQLEngine', 'Replication'] } @@ -279,7 +279,7 @@ def stub_uninstall(args, installed_features, exit_code = 0) { name: 'MYSQLSERVER', source: 'C:\myinstallexecs', - features: ['SQL'], + features: ['SQL'] } end let(:installed_features) { ['SQLEngine', 'Replication'] } @@ -310,7 +310,6 @@ def stub_uninstall(args, installed_features, exit_code = 0) args = basic_args args[:install_switches] = { 'ERRORREPORTING' => 1, 'SQLBACKUPDIR' => 'I:\DBbackup' } let(:additional_install_switches) { ["/ConfigurationFile=\"#{@file_double.path}\""] } - # rubocop:enable RSpec/InstanceVariable let(:args) { args } munged = { features: Array.new(args[:features]) } munged[:features].delete('SQL') diff --git a/spec/unit/puppet/provider/sqlserver_tsql_spec.rb b/spec/unit/puppet/provider/sqlserver_tsql_spec.rb index d82448fb..f70e51cd 100644 --- a/spec/unit/puppet/provider/sqlserver_tsql_spec.rb +++ b/spec/unit/puppet/provider/sqlserver_tsql_spec.rb @@ -25,17 +25,17 @@ def stub_get_instance_config(config) def gen_query(query) quoted_query = query.gsub('\'', '\'\'') - <<-PP -BEGIN TRY - DECLARE @sql_text as NVARCHAR(max); - SET @sql_text = N'#{quoted_query}' - EXECUTE sp_executesql @sql_text; -END TRY -BEGIN CATCH - DECLARE @msg as VARCHAR(max); - SELECT @msg = 'THROW CAUGHT: ' + ERROR_MESSAGE(); - THROW 51000, @msg, 10 -END CATCH + <<~PP + BEGIN TRY + DECLARE @sql_text as NVARCHAR(max); + SET @sql_text = N'#{quoted_query}' + EXECUTE sp_executesql @sql_text; + END TRY + BEGIN CATCH + DECLARE @msg as VARCHAR(max); + SELECT @msg = 'THROW CAUGHT: ' + ERROR_MESSAGE(); + THROW 51000, @msg, 10 + END CATCH PP end @@ -49,6 +49,7 @@ def gen_query(query) @provider.run(gen_query('whacka whacka')) } end + describe 'against default database' do it { create_sqlserver_tsql(title: 'runme', command: 'whacka whacka', instance: 'MSSQLSERVER') @@ -59,6 +60,7 @@ def gen_query(query) } end end + context 'run with onlyif' do describe 'against default database' do it { @@ -69,6 +71,7 @@ def gen_query(query) @provider.run(gen_query('fozy wozy')) } end + describe 'against non master database' do it { create_sqlserver_tsql( @@ -81,7 +84,6 @@ def gen_query(query) stub_get_instance_config(config) stub_open_and_run('fozy wozy', config.merge(database: 'myDb')) @provider.run(gen_query('fozy wozy')) - # rubocop:enable RSpec/InstanceVariable } end end diff --git a/spec/unit/puppet/sqlserver_install_context.rb b/spec/unit/puppet/sqlserver_install_context.rb index dcfc3424..3b90eb5e 100644 --- a/spec/unit/puppet/sqlserver_install_context.rb +++ b/spec/unit/puppet/sqlserver_install_context.rb @@ -15,6 +15,6 @@ def basic_args polybase_svc_account: 'nexus\polyuser', polybase_svc_password: 'P@ssword1', sql_svc_account: 'NT Service\MSSQLSERVER', - sql_sysadmin_accounts: ['localAdminAccount', 'nexus\domainUser'], + sql_sysadmin_accounts: ['localAdminAccount', 'nexus\domainUser'] } end diff --git a/spec/unit/puppet/sqlserver_spec_helper.rb b/spec/unit/puppet/sqlserver_spec_helper.rb index 564ceb6a..217776a9 100644 --- a/spec/unit/puppet/sqlserver_spec_helper.rb +++ b/spec/unit/puppet/sqlserver_spec_helper.rb @@ -25,14 +25,12 @@ def stub_modify_features(action, args, features, additional_switches = [], exit_ "/FEATURES=#{features.join(',')}"] cmds << '/UPDATEENABLED=False' if action == 'install' cmds << "/ISSVCACCOUNT=#{args[:is_svc_account]}" if args.key?(:is_svc_account) - if args.key?(:is_svc_password) - cmds << "/ISSVCPASSWORD=#{args[:is_svc_password]}" - end + cmds << "/ISSVCPASSWORD=#{args[:is_svc_password]}" if args.key?(:is_svc_password) additional_switches.each do |switch| cmds << switch end result = Puppet::Util::Execution::ProcessOutput.new('', exit_code) - allow(Puppet::Util::Execution).to receive(:execute).with(cmds, failonfail: false).and_return(result) + allow(Puppet::Util::Execution).to receive(:execute).with(cmds, { failonfail: false }).and_return(result) end diff --git a/spec/unit/puppet/type/sqlserver_features_spec.rb b/spec/unit/puppet/type/sqlserver_features_spec.rb index a09e18ad..85a6b11a 100644 --- a/spec/unit/puppet/type/sqlserver_features_spec.rb +++ b/spec/unit/puppet/type/sqlserver_features_spec.rb @@ -12,7 +12,7 @@ args = { name: 'Generic Features', ensure: 'present', - features: [feature_name], + features: [feature_name] } expect(Puppet).to receive(:deprecation_warning).at_least(:once) Puppet::Type.type(:sqlserver_features).new(args) diff --git a/spec/unit/puppet/type/sqlserver_instance_spec.rb b/spec/unit/puppet/type/sqlserver_instance_spec.rb index 9a9a4b92..e3d87bda 100644 --- a/spec/unit/puppet/type/sqlserver_instance_spec.rb +++ b/spec/unit/puppet/type/sqlserver_instance_spec.rb @@ -39,7 +39,7 @@ args = { name: 'MSSQLSERVER', ensure: 'present', - features: [feature_name], + features: [feature_name] } expect(Puppet).to receive(:deprecation_warning).at_least(:once) Puppet::Type.type(:sqlserver_instance).new(args) diff --git a/spec/unit/puppet_x/sql_connection_spec.rb b/spec/unit/puppet_x/sql_connection_spec.rb index e685715f..40f34010 100644 --- a/spec/unit/puppet_x/sql_connection_spec.rb +++ b/spec/unit/puppet_x/sql_connection_spec.rb @@ -26,6 +26,7 @@ def stub_connection stub_connection allow(@connection).to receive(:Open).with('Provider=MSOLEDBSQL;Initial Catalog=master;Application Name=Puppet;Data Source=.;DataTypeComptibility=80;UID=sa;PWD=Pupp3t1@') end + it 'does not raise an error but populate has_errors with message' do allow(@connection.Errors).to receive(:count).and_return(2) expect(@connection).to receive(:Errors).with(0).and_return(double(Description: 'SQL Error in Connection')) @@ -36,6 +37,7 @@ def stub_connection expect(result.error_message).to eq("SQL Error in Connection\nRowdy Roddy Piper") }.not_to raise_error(Exception) end + it 'yields when passed a block' do allow(subject).to receive(:execute).and_return('results') subject.open_and_run_command('myquery', config) do |r| @@ -43,6 +45,7 @@ def stub_connection end end end + context 'closed connection' do before :each do stub_connection @@ -58,7 +61,7 @@ def stub_connection context 'SQL Server based authentication' do it 'results with error if set admin_user is not set' do - expect(@connection).to receive(:Open).never + expect(@connection).not_to receive(:Open) expect { result = subject.open_and_run_command('query', admin_pass: 'Pupp3t1@', admin_login_type: 'SQL_LOGIN') expect(result.exitstatus).to eq(1) @@ -66,7 +69,7 @@ def stub_connection end it 'results with error if set admin_pass is not set' do - expect(@connection).to receive(:Open).never + expect(@connection).not_to receive(:Open) expect { result = subject.open_and_run_command('query', admin_user: 'sa', admin_login_type: 'SQL_LOGIN') expect(result.exitstatus).to eq(1) @@ -77,6 +80,7 @@ def stub_connection expect(@connection).to receive(:Open).with('Provider=MSOLEDBSQL;Initial Catalog=master;Application Name=Puppet;Data Source=.;DataTypeComptibility=80;UID=sa;PWD=Pupp3t1@') subject.open_and_run_command('query', admin_user: 'sa', admin_pass: 'Pupp3t1@', instance_name: 'MSSQLSERVER') end + it 'adds a non default instance to connection string' do expect(@connection).to receive(:Open).with('Provider=MSOLEDBSQL;Initial Catalog=master;Application Name=Puppet;Data Source=.\\LOGGING;DataTypeComptibility=80;UID=sa;PWD=Pupp3t1@') subject.open_and_run_command('query', admin_user: 'sa', admin_pass: 'Pupp3t1@', instance_name: 'LOGGING') @@ -85,7 +89,7 @@ def stub_connection context 'Windows based authentication' do it 'results with error if set admin_user is set' do - expect(@connection).to receive(:Open).never + expect(@connection).not_to receive(:Open) expect { result = subject.open_and_run_command('query', admin_user: 'sa', admin_pass: '', admin_login_type: 'WINDOWS_LOGIN') expect(result.exitstatus).to eq(1) @@ -93,7 +97,7 @@ def stub_connection end it 'results with error if set admin_pass is set' do - expect(@connection).to receive(:Open).never + expect(@connection).not_to receive(:Open) expect { result = subject.open_and_run_command('query', admin_user: '', admin_pass: 'Pupp3t1@', admin_login_type: 'WINDOWS_LOGIN') expect(result.exitstatus).to eq(1) @@ -111,22 +115,24 @@ def stub_connection end end end + context 'open connection' do it 'does not reopen an existing connection' do stub_connection - expect(@connection).to receive(:open).never + expect(@connection).not_to receive(:open) allow(@connection).to receive(:State).and_return(1) # any value other than CONNECTION_CLOSED expect(@connection).to receive(:Execute).with('query', nil, nil) subject.open_and_run_command('query', config) end end + context 'return result with errors' do it { stub_connection allow(@connection.Errors).to receive(:count).and_return(1) allow(@connection.Errors).to receive(:Description).and_return('SQL Error in Connection') allow(@connection).to receive(:Execute).and_raise(Exception) - expect(subject).to receive(:open).with(admin_user: 'sa', admin_pass: 'Pupp3t1@', instance_name: 'MSSQLSERVER') + expect(subject).to receive(:open).with({ admin_user: 'sa', admin_pass: 'Pupp3t1@', instance_name: 'MSSQLSERVER' }) expect(subject).to receive(:close).once result = subject.open_and_run_command('SELECT * FROM sys.databases', config) @@ -134,15 +140,14 @@ def stub_connection expect(result.error_message).to eq('SQL Error in Connection') } end + context 'open connection failure' do it { stub_connection err_message = 'ConnectionFailed' allow(@connection).to receive(:Open).and_raise(Exception.new(err_message)) - # rubocop:enable RSpec/InstanceVariable expect { result = subject.open_and_run_command('whacka whacka whacka', config) - # rubocop:enable RSpec/NamedSubject expect(result.exitstatus).to eq(1) expect(result.error_message).to eq 'ConnectionFailed' }.not_to raise_error(Exception)