diff --git a/.fixtures.yml b/.fixtures.yml index ae707da9..bbca4d63 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,5 +1,8 @@ fixtures: repositories: - "stdlib": "https://github.com/puppetlabs/puppetlabs-stdlib.git" + facts: 'https://github.com/puppetlabs/puppetlabs-facts.git' + puppet_agent: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' + provision: 'https://github.com/puppetlabs/provision.git' + stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' symlinks: sqlserver: "#{source_dir}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..c9fd51f9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,81 @@ + +name: "release" + +on: + push: + branches: + - 'release' + +jobs: + LitmusAcceptance2012Sql: + runs-on: self-hosted + strategy: + matrix: + ruby_version: [2.5.x] + puppet_gem_version: [~> 6.0] + platform: [release_checks_sql_2012] + agent_family: ['puppet5', 'puppet6'] + + steps: + - uses: actions/checkout@v1 + - name: Litmus Parallel + uses: puppetlabs/action-litmus_parallel@master + with: + platform: ${{ matrix.platform }} + agent_family: ${{ matrix.agent_family }} + additional_command: ${{ matrix.additional_command }} + LitmusAcceptance2014Sql: + runs-on: self-hosted + strategy: + matrix: + ruby_version: [2.5.x] + puppet_gem_version: [~> 6.0] + platform: [release_checks_sql_2014] + agent_family: ['puppet5', 'puppet6'] + + steps: + - uses: actions/checkout@v1 + - name: Litmus Parallel + uses: puppetlabs/action-litmus_parallel@master + with: + platform: ${{ matrix.platform }} + agent_family: ${{ matrix.agent_family }} + additional_command: ${{ matrix.additional_command }} + LitmusAcceptance2016Sql: + runs-on: self-hosted + strategy: + matrix: + ruby_version: [2.5.x] + puppet_gem_version: [~> 6.0] + platform: [release_checks_sql_2016_parity] + agent_family: ['puppet5', 'puppet6'] + additional_command: ['bundle exec rake litmus:add_feature[sqlversion_2016]'] + + steps: + - uses: actions/checkout@v1 + - name: Litmus Parallel + uses: puppetlabs/action-litmus_parallel@master + with: + platform: ${{ matrix.platform }} + agent_family: ${{ matrix.agent_family }} + additional_command: ${{ matrix.additional_command }} + + Spec: + runs-on: self-hosted + strategy: + matrix: + check: [parallel_spec, 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop'] + ruby_version: [2.5.x] + puppet_gem_version: [~> 5.0, ~> 6.0] + exclude: + - puppet_gem_version: ~> 5.0 + check: 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop' + - ruby_version: 2.5.x + puppet_gem_version: ~> 5.0 + steps: + - uses: actions/checkout@v1 + - name: Spec Tests + uses: puppetlabs/action-litmus_spec@master + with: + puppet_gem_version: ${{ matrix.puppet_gem_version }} + check: ${{ matrix.check }} \ No newline at end of file diff --git a/.sync.yml b/.sync.yml index 998548b4..474de578 100644 --- a/.sync.yml +++ b/.sync.yml @@ -31,20 +31,6 @@ appveyor.yml: CHECK: parallel_spec simplecov: true Gemfile: - required: - ":system_tests": - - gem: puppet-module-posix-system-r#{minor_version} - platforms: ruby - - gem: puppet-module-win-system-r#{minor_version} - platforms: - - mswin - - mingw - - x64_mingw - - gem: beaker-testmode_switcher - version: "~> 0.4" - - gem: master_manipulator - - gem: puppet-blacksmith - version: "~> 3.4" optional: ":development": - gem: ruby-pwsh diff --git a/Gemfile b/Gemfile index 75c4a1f3..3378919b 100644 --- a/Gemfile +++ b/Gemfile @@ -31,13 +31,6 @@ group :development do gem "ruby-pwsh", require: false gem "github_changelog_generator", require: false, git: 'https://github.com/skywinder/github-changelog-generator', ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2') end -group :system_tests do - gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "beaker-testmode_switcher", '~> 0.4', require: false - gem "master_manipulator", require: false - gem "puppet-blacksmith", '~> 3.4', require: false -end puppet_version = ENV['PUPPET_GEM_VERSION'] facter_version = ENV['FACTER_GEM_VERSION'] diff --git a/lib/puppet_x/sqlserver/sql_connection.rb b/lib/puppet_x/sqlserver/sql_connection.rb index f5d9fe53..9e5059fe 100644 --- a/lib/puppet_x/sqlserver/sql_connection.rb +++ b/lib/puppet_x/sqlserver/sql_connection.rb @@ -1,110 +1,112 @@ -module PuppetX::Sqlserver - CONNECTION_CLOSED = 0 - - class SqlConnection # rubocop:disable Style/Documentation - def open_and_run_command(query, config) - begin - open(config) - execute(query) - rescue win32_exception => e - return ResultOutput.new(true, e.message, @connection) - ensure - close +module PuppetX # rubocop:disable Style/ClassAndModuleChildren + module Sqlserver + CONNECTION_CLOSED = 0 + + class SqlConnection # rubocop:disable Style/Documentation + def open_and_run_command(query, config) + begin + open(config) + execute(query) + rescue win32_exception => e + return ResultOutput.new(true, e.message, @connection) + ensure + close + end + + ResultOutput.new(false, nil, @connection) end - ResultOutput.new(false, nil, @connection) - end - - private - - def connection - @connection ||= create_connection - end + private - def open(config) - connection_string = get_connection_string(config) - connection.Open(connection_string) if connection_closed? - end - - def get_connection_string(config) - params = { - 'Provider' => 'SQLNCLI11', - 'Initial Catalog' => config[:database] || 'master', - 'Application Name' => 'Puppet', - 'Data Source' => '.', - 'DataTypeComptibility' => 80, - } - - admin_user = config[:admin_user] || '' - admin_pass = config[:admin_pass] || '' - - if config[:admin_login_type] == 'WINDOWS_LOGIN' - # 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('User ID', admin_user) - params.store('Password', admin_pass) + def connection + @connection ||= create_connection end - if !config[:instance_name].nil? && config[:instance_name] !~ %r{^MSSQLSERVER$} - params['Data Source'] = ".\\#{config[:instance_name]}" + def open(config) + connection_string = get_connection_string(config) + connection.Open(connection_string) if connection_closed? end - params.map { |k, v| "#{k}=#{v}" }.join(';') - end + def get_connection_string(config) + params = { + 'Provider' => 'SQLNCLI11', + 'Initial Catalog' => config[:database] || 'master', + 'Application Name' => 'Puppet', + 'Data Source' => '.', + 'DataTypeComptibility' => 80, + } + + admin_user = config[:admin_user] || '' + admin_pass = config[:admin_pass] || '' + + if config[:admin_login_type] == 'WINDOWS_LOGIN' + # 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('User ID', admin_user) + params.store('Password', admin_pass) + end + + if !config[:instance_name].nil? && config[:instance_name] !~ %r{^MSSQLSERVER$} + params['Data Source'] = ".\\#{config[:instance_name]}" + end + + params.map { |k, v| "#{k}=#{v}" }.join(';') + end - def close - connection.Close unless connection_closed? - rescue win32_exception # rubocop:disable Lint/HandleExceptions - end + def close + connection.Close unless connection_closed? + rescue win32_exception # rubocop:disable Lint/HandleExceptions + end - def connection_closed? - connection.State == CONNECTION_CLOSED - end + def connection_closed? + connection.State == CONNECTION_CLOSED + end - def create_connection - require 'win32ole' - WIN32OLE.new('ADODB.Connection') - end + def create_connection + require 'win32ole' + WIN32OLE.new('ADODB.Connection') + end - def execute(sql) - connection.Execute(sql, nil, nil) - end + def execute(sql) + connection.Execute(sql, nil, nil) + end - def parse_column_names(result) - result.Fields.extend(Enumerable).map(&:Name) - end + def parse_column_names(result) + result.Fields.extend(Enumerable).map(&:Name) + end - # having as a method instead of hard coded allows us to stub and test outside of Windows - def win32_exception - ::WIN32OLERuntimeError + # having as a method instead of hard coded allows us to stub and test outside of Windows + def win32_exception + ::WIN32OLERuntimeError + end end - end - class ResultOutput # rubocop:disable Style/Documentation - attr_reader :exitstatus, :error_message + class ResultOutput # rubocop:disable Style/Documentation + attr_reader :exitstatus, :error_message - def initialize(has_errors, error_message, connection) - @exitstatus = has_errors ? 1 : 0 + def initialize(has_errors, error_message, connection) + @exitstatus = has_errors ? 1 : 0 - @error_message = extract_messages(connection) || error_message - end + @error_message = extract_messages(connection) || error_message + end - def extract_messages(connection) - return nil if connection.nil? || connection.Errors.count.zero? + def extract_messages(connection) + return nil if connection.nil? || connection.Errors.count.zero? - error_count = connection.Errors.count - 1 + error_count = connection.Errors.count - 1 - ((0..error_count).map { |i| connection.Errors(i).Description.to_s }).join("\n") - end + ((0..error_count).map { |i| connection.Errors(i).Description.to_s }).join("\n") + end - def has_errors # rubocop:disable Style/PredicateName - @exitstatus != 0 + def has_errors # rubocop:disable Style/PredicateName + @exitstatus != 0 + end end end end diff --git a/provision.yaml b/provision.yaml new file mode 100644 index 00000000..33d2314c --- /dev/null +++ b/provision.yaml @@ -0,0 +1,31 @@ +default: + provisioner: vagrant + images: ['gusztavvargadr/windows-server'] +release_checks_sql_2012: + provisioner: vmpooler + images: ['win-2012r2-x86_64'] + vars: 'sqlversion: sqlserver_2012' +release_checks_sql_2014_parity: + provisioner: vmpooler + images: ['win-2012r2-x86_64'] + vars: 'sqlversion: sqlserver_2014' +release_checks_sql_2014: + provisioner: vmpooler + images: ['win-2012r2-x86_64', 'win-2016-x86_64', 'win-2019-x86_64'] + vars: 'sqlversion: sqlserver_2014' +release_checks_sql_2016_parity: + provisioner: vmpooler + images: ['win-2012r2-x86_64', 'win-2016-x86_64'] + vars: 'sqlversion: sqlserver_2016' +release_checks_sql_2016: + provisioner: vmpooler + images: ['win-2012r2-x86_64', 'win-2016-x86_64', 'win-2019-x86_64'] + vars: 'sqlversion: sqlserver_2016' +release_checks_sql_2017: + provisioner: vmpooler + images: ['win-2012r2-x86_64', 'win-2016-x86_64', 'win-2019-x86_64'] + vars: 'sqlversion: sqlserver_2017' +release_checks_sql_2019: + provisioner: vmpooler + images: ['win-2012r2-x86_64', 'win-2016-x86_64', 'win-2019-x86_64'] + vars: 'sqlversion: sqlserver_2019' diff --git a/spec/acceptance/nodesets/centos-7-x64.yml b/spec/acceptance/nodesets/centos-7-x64.yml deleted file mode 100644 index 5eebdefb..00000000 --- a/spec/acceptance/nodesets/centos-7-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-7-x64: - roles: - - agent - - default - platform: el-7-x86_64 - hypervisor: vagrant - box: puppetlabs/centos-7.2-64-nocm -CONFIG: - type: foss diff --git a/spec/acceptance/nodesets/debian-8-x64.yml b/spec/acceptance/nodesets/debian-8-x64.yml deleted file mode 100644 index fef6e63c..00000000 --- a/spec/acceptance/nodesets/debian-8-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - debian-8-x64: - roles: - - agent - - default - platform: debian-8-amd64 - hypervisor: vagrant - box: puppetlabs/debian-8.2-64-nocm -CONFIG: - type: foss diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml deleted file mode 100644 index 6f602319..00000000 --- a/spec/acceptance/nodesets/default.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -HOSTS: - windows2012-64-1: - pe_dir: - pe_ver: - pe_upgrade_dir: - pe_upgrade_ver: - hypervisor: vmpooler - platform: windows-2012-64 - ruby_arch: x64 - template: win-2012-x86_64 - roles: - - agent - - default -CONFIG: - nfs_server: none - consoleport: 443 - pooling_api: http://vmpooler.delivery.puppetlabs.net/ diff --git a/spec/acceptance/nodesets/docker/centos-7.yml b/spec/acceptance/nodesets/docker/centos-7.yml deleted file mode 100644 index a3333aac..00000000 --- a/spec/acceptance/nodesets/docker/centos-7.yml +++ /dev/null @@ -1,12 +0,0 @@ -HOSTS: - centos-7-x64: - platform: el-7-x86_64 - hypervisor: docker - image: centos:7 - docker_preserve_image: true - docker_cmd: '["/usr/sbin/init"]' - # install various tools required to get the image up to usable levels - docker_image_commands: - - 'yum install -y crontabs tar wget openssl sysvinit-tools iproute which initscripts' -CONFIG: - trace_limit: 200 diff --git a/spec/acceptance/nodesets/docker/debian-8.yml b/spec/acceptance/nodesets/docker/debian-8.yml deleted file mode 100644 index df5c3194..00000000 --- a/spec/acceptance/nodesets/docker/debian-8.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - debian-8-x64: - platform: debian-8-amd64 - hypervisor: docker - image: debian:8 - docker_preserve_image: true - docker_cmd: '["/sbin/init"]' - docker_image_commands: - - 'apt-get update && apt-get install -y net-tools wget locales strace lsof && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen' -CONFIG: - trace_limit: 200 diff --git a/spec/acceptance/nodesets/docker/ubuntu-14.04.yml b/spec/acceptance/nodesets/docker/ubuntu-14.04.yml deleted file mode 100644 index b1efa583..00000000 --- a/spec/acceptance/nodesets/docker/ubuntu-14.04.yml +++ /dev/null @@ -1,12 +0,0 @@ -HOSTS: - ubuntu-1404-x64: - platform: ubuntu-14.04-amd64 - hypervisor: docker - image: ubuntu:14.04 - docker_preserve_image: true - docker_cmd: '["/sbin/init"]' - docker_image_commands: - # ensure that upstart is booting correctly in the container - - 'rm /usr/sbin/policy-rc.d && rm /sbin/initctl && dpkg-divert --rename --remove /sbin/initctl && apt-get update && apt-get install -y net-tools wget && locale-gen en_US.UTF-8' -CONFIG: - trace_limit: 200 diff --git a/spec/acceptance/nodesets/win_2012_sql2012.yml b/spec/acceptance/nodesets/win_2012_sql2012.yml deleted file mode 100644 index a5a98494..00000000 --- a/spec/acceptance/nodesets/win_2012_sql2012.yml +++ /dev/null @@ -1,24 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012: - roles: - - agent - - sql_host - platform: windows-2012-x86_64 - template: win-2012-x86_64 - hypervisor: vcloud - sql_version: 2012 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/spec/acceptance/nodesets/win_2012_sql2012_future.yml b/spec/acceptance/nodesets/win_2012_sql2012_future.yml deleted file mode 100644 index 66a0f4fd..00000000 --- a/spec/acceptance/nodesets/win_2012_sql2012_future.yml +++ /dev/null @@ -1,27 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012: - roles: - - agent - - sql_host - platform: windows-2012-x86_64 - template: win-2012-x86_64 - hypervisor: vcloud - sql_version: 2012 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ - default_apply_opts: - parser: future - strict_variables: ~ diff --git a/spec/acceptance/nodesets/win_2012_sql2014.yml b/spec/acceptance/nodesets/win_2012_sql2014.yml deleted file mode 100644 index 97ce40d2..00000000 --- a/spec/acceptance/nodesets/win_2012_sql2014.yml +++ /dev/null @@ -1,24 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012: - roles: - - agent - - sql_host - platform: windows-2012-x86_64 - template: win-2012-x86_64 - hypervisor: vcloud - sql_version: 2014 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/spec/acceptance/nodesets/win_2012_sql2014_future.yml b/spec/acceptance/nodesets/win_2012_sql2014_future.yml deleted file mode 100644 index 56e3a90a..00000000 --- a/spec/acceptance/nodesets/win_2012_sql2014_future.yml +++ /dev/null @@ -1,27 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012: - roles: - - agent - - sql_host - platform: windows-2012-x86_64 - template: win-2012-x86_64 - hypervisor: vcloud - sql_version: 2014 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ - default_apply_opts: - parser: future - strict_variables: ~ diff --git a/spec/acceptance/nodesets/win_2012r2_sql2012.yml b/spec/acceptance/nodesets/win_2012r2_sql2012.yml deleted file mode 100644 index 2e80bcfe..00000000 --- a/spec/acceptance/nodesets/win_2012r2_sql2012.yml +++ /dev/null @@ -1,24 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012r2: - roles: - - agent - - sql_host - platform: windows-2012r2-x86_64 - template: win-2012r2-x86_64 - hypervisor: vcloud - sql_version: 2012 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/spec/acceptance/nodesets/win_2012r2_sql2012_future.yml b/spec/acceptance/nodesets/win_2012r2_sql2012_future.yml deleted file mode 100644 index 101e50c6..00000000 --- a/spec/acceptance/nodesets/win_2012r2_sql2012_future.yml +++ /dev/null @@ -1,27 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012r2: - roles: - - agent - - sql_host - platform: windows-2012r2-x86_64 - template: win-2012r2-x86_64 - hypervisor: vcloud - sql_version: 2012 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ - default_apply_opts: - parser: future - strict_variables: ~ diff --git a/spec/acceptance/nodesets/win_2012r2_sql2014.yml b/spec/acceptance/nodesets/win_2012r2_sql2014.yml deleted file mode 100644 index 0ac871bf..00000000 --- a/spec/acceptance/nodesets/win_2012r2_sql2014.yml +++ /dev/null @@ -1,24 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012r2: - roles: - - agent - - sql_host - platform: windows-2012r2-x86_64 - template: win-2012r2-x86_64 - hypervisor: vcloud - sql_version: 2014 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/spec/acceptance/nodesets/win_2012r2_sql2014_future.yml b/spec/acceptance/nodesets/win_2012r2_sql2014_future.yml deleted file mode 100644 index a02d9ee3..00000000 --- a/spec/acceptance/nodesets/win_2012r2_sql2014_future.yml +++ /dev/null @@ -1,27 +0,0 @@ -HOSTS: - centos7-master: - roles: - - master - - database - - dashboard - platform: el-7-x86_64 - template: centos-7-x86_64 - hypervisor: vcloud - win2012r2: - roles: - - agent - - sql_host - platform: windows-2012r2-x86_64 - template: win-2012r2-x86_64 - hypervisor: vcloud - sql_version: 2014 -CONFIG: - nfs_server: none - consoleport: 443 - datastore: instance0 - folder: Delivery/Quality Assurance/FOSS/Dynamic - resourcepool: delivery/Quality Assurance/FOSS/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ - default_apply_opts: - parser: future - strict_variables: ~ diff --git a/spec/acceptance/sqlserver_config_spec.rb b/spec/acceptance/sqlserver_config_spec.rb index a2a8e7fc..586fcbf0 100644 --- a/spec/acceptance/sqlserver_config_spec.rb +++ b/spec/acceptance/sqlserver_config_spec.rb @@ -2,21 +2,18 @@ require 'securerandom' require 'erb' -host = find_only_one('sql_host') - # Get instance name inst_name = ('MSSQL' + SecureRandom.hex(4)).upcase - # Get database name db_name = ('DB' + SecureRandom.hex(4)).upcase -describe 'sqlserver::config test', node: host do +describe 'sqlserver::config test' do def ensure_sqlserver_instance(inst_name, ensure_val = 'present') - create_new_instance = <<-MANIFEST + pp = <<-MANIFEST sqlserver_instance{'#{inst_name}': ensure => '#{ensure_val}', source => 'H:', - features => [ 'SQL' ], + features => ['DQ', 'FullText', 'Replication', 'SQLEngine'], sql_sysadmin_accounts => ['Administrator'], security_mode => 'SQL', sa_pwd => 'Pupp3t1@', @@ -24,12 +21,10 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') } MANIFEST - execute_manifest(create_new_instance) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end - context 'Testing sqlserver::config', testrail: ['89070', '89071', '89072', '89073'] do + context 'Testing sqlserver::config' do before(:all) do # Create new instance ensure_sqlserver_instance(inst_name) @@ -47,8 +42,8 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') ensure_sqlserver_instance(inst_name, 'absent') end - it 'Create New Admin Login:', tier_low: true do - create_new_login = <<-MANIFEST + it 'Create New Admin Login:' do + pp = <<-MANIFEST sqlserver::config{'#{inst_name}': instance_name => '#{inst_name}', admin_user => 'sa', @@ -62,12 +57,10 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') svrroles => {'sysadmin' => 1}, } MANIFEST - execute_manifest(create_new_login) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end - it 'Validate New Config WITH using instance_name in sqlserver::config', tier_low: true do + it 'Validate New Config WITH using instance_name in sqlserver::config' do pp = <<-MANIFEST sqlserver::config{'#{inst_name}': admin_user => '#{@admin_user}', @@ -78,20 +71,18 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') instance => '#{inst_name}', } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end - it 'Validate new login and database actualy created', tier_low: true do - hostname = host.hostname + it 'Validate new login and database actualy created' do + hostname = ENV['TARGET_HOST'] query = "USE #{db_name}; SELECT * from master..sysdatabases WHERE name = '#{db_name}'" - run_sql_query(host, query: query, server: hostname, instance: inst_name, \ - sql_admin_user: @admin_user, sql_admin_pass: @admin_pass, expected_row_count: 1) + run_sql_query(query: query, server: hostname, instance: inst_name, \ + 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', tier_low: true do + it 'Validate New Config WITHOUT using instance_name in sqlserver::config' do pp = <<-MANIFEST sqlserver::config{'#{inst_name}': admin_user => '#{@admin_user}', @@ -101,10 +92,7 @@ def ensure_sqlserver_instance(inst_name, ensure_val = 'present') instance => '#{inst_name}', } MANIFEST - # rubocop:enable RSpec/InstanceVariable - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end end end diff --git a/spec/acceptance/sqlserver_database_spec.rb b/spec/acceptance/sqlserver_database_spec.rb index d70f537e..394e818e 100644 --- a/spec/acceptance/sqlserver_database_spec.rb +++ b/spec/acceptance/sqlserver_database_spec.rb @@ -1,15 +1,7 @@ require 'spec_helper_acceptance' require 'securerandom' -host = find_only_one('sql_host') - -describe 'Test sqlserver::database', node: host do - def ensure_sqlserver_database(pp) - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end - end - +describe 'Test sqlserver::database' do # Return options for run_sql_query def run_sql_query_opts(query, expected_row_count) { @@ -20,7 +12,7 @@ def run_sql_query_opts(query, expected_row_count) } end - context 'Start testing...', testrail: ['89019', '89076', '89077', '89078', '89079', '89080', '89081'] do + context 'Start testing...' do before(:each) do @db_name = ('DB' + SecureRandom.hex(4)).upcase @table_name = 'Tables_' + SecureRandom.hex(3) @@ -40,10 +32,10 @@ def run_sql_query_opts(query, expected_row_count) ensure => 'absent', } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) end - it 'Test Case C89019: Create a database', tier_low: true do + it 'Test Case C89019: Create a database' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -58,14 +50,14 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts "Validate the Database '#{@db_name}' and table '#{@table_name}' are successfully created:" query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) end - it 'Delete a database', tier_low: true do + it 'Delete a database' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -74,11 +66,11 @@ def run_sql_query_opts(query, expected_row_count) sqlserver::database{'#{@db_name}': } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts "Validate the Database '#{@db_name}' exists" query = "SELECT database_id from sys.databases WHERE name = '#{@db_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -89,14 +81,14 @@ def run_sql_query_opts(query, expected_row_count) ensure => absent, } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts "Validate the Database '#{@db_name}' does not exist" query = "SELECT database_id from sys.databases WHERE name = '#{@db_name}';" - run_sql_query(host, run_sql_query_opts(query, 0)) + run_sql_query(run_sql_query_opts(query, 0)) end - it 'Test Case C89076: Create database with optional collation_name', tier_low: true do + it 'Test Case C89076: Create database with optional collation_name' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -112,11 +104,11 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts 'Validate that a table can be created in the database:' query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) puts "validate the Database '#{@db_name}' has correct collation name:" query = "SELECT name AS Database_Name, collation_name @@ -124,10 +116,10 @@ def run_sql_query_opts(query, expected_row_count) WHERE name = '#{@db_name}' AND collation_name = 'SQL_Estonian_CP1257_CS_AS';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) end - it 'Test Case C89077: Create database with optional compatibility', tier_low: true do + it 'Test Case C89077: Create database with optional compatibility' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -143,11 +135,11 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts 'Validate that a table can be created in the database:' query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) puts "validate the Database '#{@db_name}' has correct compatibility level:" query = "SELECT name AS Database_Name, compatibility_level @@ -155,10 +147,10 @@ def run_sql_query_opts(query, expected_row_count) WHERE name = '#{@db_name}' AND compatibility_level = '100';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) end - it 'Test Case C89078: Create database with optional containment', tier_low: true do + it 'Test Case C89078: Create database with optional containment' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -181,11 +173,11 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts 'Validate that a table can be created in the database:' query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) puts "validate the Database '#{@db_name}' has correct containment:" query = "SELECT name AS Database_Name, containment_desc @@ -193,10 +185,10 @@ def run_sql_query_opts(query, expected_row_count) WHERE name = '#{@db_name}' AND containment_desc = 'PARTIAL';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) end - it 'Test Case C89079: Create database with optional db_chaining', tier_low: true do + it 'Test Case C89079: Create database with optional db_chaining' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -220,11 +212,11 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts 'Validate that a table can be created in the database:' query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) puts "validate the Database '#{@db_name}' has correct db_chaing setting:" query = "SELECT name AS Database_Name, is_db_chaining_on @@ -232,7 +224,7 @@ def run_sql_query_opts(query, expected_row_count) WHERE name = '#{@db_name}' AND is_db_chaining_on = '1';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) end it 'Test Case C89080: Create database with optional default_fulltext_language', tier_low: true do @@ -259,11 +251,11 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts 'Validate that a table can be created in the database:' query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) puts "validate the Database '#{@db_name}' has correct default_fulltext_language_name setting:" query = "SELECT name AS Database_Name, default_fulltext_language_name @@ -271,10 +263,10 @@ def run_sql_query_opts(query, expected_row_count) WHERE name = '#{@db_name}' AND default_fulltext_language_name = 'Japanese';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) end - it 'Test Case C89081: Create database with optional default_language', tier_low: true do + it 'Test Case C89081: Create database with optional default_language' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -298,11 +290,11 @@ def run_sql_query_opts(query, expected_row_count) require => Sqlserver::Database['#{@db_name}'], } MANIFEST - ensure_sqlserver_database(pp) + apply_manifest(pp, catch_failures: true) puts 'Validate that a table can be created in the database:' query = "USE #{@db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" - run_sql_query(host, run_sql_query_opts(query, 1)) + run_sql_query(run_sql_query_opts(query, 1)) puts "validate the Database '#{@db_name}' has correct default_language setting:" query = "SELECT name AS Database_Name, default_language_name @@ -310,48 +302,7 @@ def run_sql_query_opts(query, expected_row_count) WHERE name = '#{@db_name}' AND default_language_lcid = '1028';" - run_sql_query(host, run_sql_query_opts(query, 1)) - # rubocop:enable RSpec/InstanceVariable - end - - it 'Test Case MODULES-10335: Create two database with seperate sp_configure', tier_low: true do - pp = <<-MANIFEST - sqlserver::config{'MSSQLSERVER': - admin_user => 'sa', - admin_pass => 'Pupp3t1@', - } - sqlserver::sp_configure{ 'sp_config4db': - config_name => 'contained database authentication', - value => 1, - reconfigure => true, - instance => 'MSSQLSERVER', - } - sqlserver::database{ '#{@db_name}': - require => Sqlserver::Sp_configure['sp_config4db'] - } - sqlserver_tsql{'testsqlserver_tsql': - instance => 'MSSQLSERVER', - database => '#{@db_name}', - command => "CREATE TABLE #{@table_name} (id INT, name VARCHAR(20), email VARCHAR(20));", - require => Sqlserver::Database['#{@db_name}'], - } - sqlserver::sp_configure{ 'sp_config5db': - config_name => 'contained database authentication', - value => 1, - reconfigure => true, - instance => 'MSSQLSERVER', - } - sqlserver::database{ '#{@db_name}-2': - require => Sqlserver::Sp_configure['sp_config5db'] - } - sqlserver_tsql{'testsqlserver_tsql': - instance => 'MSSQLSERVER', - database => '#{@db_name}-2', - command => "CREATE TABLE #{@table_name} (id INT, name VARCHAR(20), email VARCHAR(20));", - require => Sqlserver::Database['#{@db_name}-2'], - } - MANIFEST - ensure_sqlserver_database(pp) + run_sql_query(run_sql_query_opts(query, 1)) # rubocop:enable RSpec/InstanceVariable end end diff --git a/spec/acceptance/sqlserver_instance_spec.rb b/spec/acceptance/sqlserver_instance_spec.rb index af1e0e49..6ea98a0c 100644 --- a/spec/acceptance/sqlserver_instance_spec.rb +++ b/spec/acceptance/sqlserver_instance_spec.rb @@ -2,37 +2,29 @@ require 'securerandom' require 'erb' -host = find_only_one('sql_host') - def new_random_instance_name ('MSSQL' + SecureRandom.hex(4)).upcase.to_s end -describe 'sqlserver_instance', node: host do - version = host['sql_version'].to_s +describe 'sqlserver_instance' do + version = sql_version? def ensure_sqlserver_instance(features, inst_name, ensure_val = 'present', sysadmin_accounts = "['Administrator']") - manifest = <<-MANIFEST + pp = <<-MANIFEST sqlserver_instance{'#{inst_name}': name => '#{inst_name}', - ensure => <%= ensure_val %>, + ensure => #{ensure_val}, source => 'H:', security_mode => 'SQL', sa_pwd => 'Pupp3t1@', - features => [ <%= mssql_features %> ], + features => #{features}, sql_sysadmin_accounts => #{sysadmin_accounts}, agt_svc_account => 'Administrator', agt_svc_password => 'Qu@lity!', windows_feature_source => 'I:\\sources\\sxs', } MANIFEST - - mssql_features = features.map { |x| "'#{x}'" }.join(', ') - - pp = ERB.new(manifest).result(binding) - - execute_manifest(pp, catch_failures: true) - execute_manifest(pp, catch_changes: true) + idempotent_apply(pp) end # Return options for run_sql_query @@ -57,7 +49,7 @@ def sql_query_is_user_sysadmin(username) QUERY end - context 'Create an instance', testrail: ['88978', '89028', '89031', '89043', '89061'] do + context 'Create an instance' do before(:context) do # Use a username with a space to test argument parsing works correctly @extra_admin_user = 'Extra SQLAdmin' @@ -67,7 +59,7 @@ def sql_query_is_user_sysadmin(username) password => 'Puppet01!', } MANIFEST - execute_manifest(pp) + apply_manifest(pp, catch_failures: true) end after(:context) do @@ -76,34 +68,34 @@ def sql_query_is_user_sysadmin(username) ensure => absent, } MANIFEST - execute_manifest(pp) + apply_manifest(pp, catch_failures: true) end inst_name = new_random_instance_name features = ['SQLEngine', 'Replication', 'FullText', 'DQ'] - it "create #{inst_name} instance", tier_high: true do - host_computer_name = on(host, 'CMD /C ECHO %COMPUTERNAME%').stdout.chomp + it "create #{inst_name} instance" do + host_computer_name = run_shell('CMD /C ECHO %COMPUTERNAME%').stdout.chomp ensure_sqlserver_instance(features, inst_name, 'present', "['Administrator','#{host_computer_name}\\#{@extra_admin_user}']") - validate_sql_install(host, version: version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).to match(%r{#{Regexp.new(inst_name)}}) end end - it "#{inst_name} instance has Administrator as a sysadmin", tier_low: true do - run_sql_query(host, run_sql_query_opts(inst_name, sql_query_is_user_sysadmin('Administrator'), 1)) + it "#{inst_name} instance has Administrator as a sysadmin" do + run_sql_query(run_sql_query_opts(inst_name, sql_query_is_user_sysadmin('Administrator'), 1)) end - it "#{inst_name} instance has ExtraSQLAdmin as a sysadmin", tier_low: true do - run_sql_query(host, run_sql_query_opts(inst_name, sql_query_is_user_sysadmin(@extra_admin_user), 1)) + 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", tier_high: true do + it "remove #{inst_name} instance" do ensure_sqlserver_instance(features, inst_name, 'absent') # Ensure all features for this instance are removed and the defaults are left alone - validate_sql_install(host, version: version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).to match(%r{MSSQLSERVER\s+Database Engine Services}) expect(r.stdout).to match(%r{MSSQLSERVER\s+SQL Server Replication}) expect(r.stdout).to match(%r{MSSQLSERVER\s+Data Quality Services}) @@ -114,7 +106,7 @@ def sql_query_is_user_sysadmin(username) end end - context "Feature has only one 'RS'", testrail: ['89034'] do + context "Feature has only one 'RS'" do inst_name = new_random_instance_name features = ['RS'] @@ -122,31 +114,12 @@ def sql_query_is_user_sysadmin(username) ensure_sqlserver_instance(features, inst_name, 'absent') end - it "create #{inst_name} instance with only one RS feature", unless: version.to_i >= 2017, tier_high: true do + it "create #{inst_name} instance with only one RS feature", unless: version.to_i >= 2017 do ensure_sqlserver_instance(features, inst_name) - validate_sql_install(host, version: version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).to match(%r{#{inst_name}\s+Reporting Services}) end end end - - context "Feature has only one 'AS'", testrail: ['89033'] do - inst_name = new_random_instance_name - features = ['AS'] - - after(:all) do - ensure_sqlserver_instance(features, inst_name, 'absent') - end - - # skip below test due to ticket MODULES-2379, when the ticket was resolved - # will change xit to it - xit "create #{inst_name} instance with only one AS feature" do - ensure_sqlserver_instance(features, inst_name) - - validate_sql_install(host, version: version) do |r| - expect(r.stdout).to match(%r{#{Regexp.new(inst_name)}}) - end - end - end end diff --git a/spec/acceptance/sqlserver_login_spec.rb b/spec/acceptance/sqlserver_login_spec.rb index 0960f291..b7fb3628 100644 --- a/spec/acceptance/sqlserver_login_spec.rb +++ b/spec/acceptance/sqlserver_login_spec.rb @@ -1,18 +1,11 @@ require 'spec_helper_acceptance' require 'securerandom' -host = find_only_one('sql_host') 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', node: host do - def ensure_manifest_execute(pp) - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end - end - +describe 'Test sqlserver::login' do # Return options for run_sql_query def run_sql_query_opts(user, passwd, query, expected_row_count) { @@ -46,7 +39,7 @@ def remove_test_logins(_host) ensure => 'absent', } MANIFEST - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end def create_login_manifest(testcase, login_name, login_password, options = {}) @@ -87,7 +80,7 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) @windows_user = 'User' + SecureRandom.hex(4) @windows_group = 'Group' + SecureRandom.hex(4) - host_shortname = on(host, 'hostname').stdout.upcase.strip # Require the NETBIOS name for later database searches + host_shortname = run_shell('hostname').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 @@ -114,7 +107,7 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) ensure => 'present', } MANIFEST - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end # Delete all test fixtures @@ -137,7 +130,7 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) ensure => 'absent', } MANIFEST - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end ['SQL_LOGIN user', 'WINDOWS_LOGIN user', 'WINDOWS_LOGIN group'].each do |testcase| @@ -161,96 +154,91 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) describe "Create deafult #{testcase} login" do before(:all) { remove_test_logins(host) } - it "can create a default #{testcase}", tier_low: true do + it "can create a default #{testcase} idempotently" do pp = create_login_manifest(testcase, @login_under_test, @login_passwd) - ensure_manifest_execute(pp) + idempotent_apply(pp) end - it 'exists in the principals table', tier_low: true do + it 'exists in the principals table' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end if testcase == 'SQL_LOGIN user' - it 'can login to SQL Server', tier_low: true do + it 'can login to SQL Server' do puts "Validate the login '#{@login_under_test}' is successfully created and able to access database '#{db_name}':" query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{table_name}';" - run_sql_query(host, run_sql_query_opts(@login_under_test, @login_passwd, query, 1)) + run_sql_query(run_sql_query_opts(@login_under_test, @login_passwd, query, 1)) end end - - it 'is idempotent', tier_low: true do - pp = create_login_manifest(testcase, @login_under_test, @login_passwd) - ensure_manifest_execute(pp) - end end describe "Create #{testcase} login with 'check_expiration','check_policy'", if: testcase == 'SQL_LOGIN user' do # 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", tier_low: true do + 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) - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end - it 'has is_expiration_checked set', tier_low: true do + it 'has is_expiration_checked set' do query = "SELECT name as LOGIN_NAME, is_expiration_checked FROM SYS.SQL_LOGINS WHERE is_expiration_checked = '1' AND name = '#{@login_under_test}';" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has is_policy_checked set', tier_low: true do + it 'has is_policy_checked set' do query = "SELECT name as LOGIN_NAME, is_policy_checked FROM SYS.SQL_LOGINS WHERE is_policy_checked = '1' AND name = '#{@login_under_test}';" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end end describe "Create #{testcase} login with 'default_database','default_language'" do before(:all) { remove_test_logins(host) } - it "can create a #{testcase} with 'default_database','default_language'", tier_low: true do + it "can create a #{testcase} with 'default_database','default_language'" do options = { 'default_database' => db_name.to_s, 'default_language' => 'Spanish' } pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end - it 'exists in the principals table', tier_low: true do + it 'exists in the principals table' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has the specified default database', tier_low: true do + it 'has the specified default database' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}' AND default_database_name = '#{db_name}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has the specified default langauge', tier_low: true do + it 'has the specified default langauge' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}' AND default_language_name = 'Spanish'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end end describe "Create #{testcase} login with 'disabled'" do before(:all) { remove_test_logins(host) } - it "can create #{testcase} with optional 'disabled'", tier_low: true do + it "can create #{testcase} with optional 'disabled'" do options = { 'disabled' => true } pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end if testcase == 'WINDOWS_LOGIN group' - it 'has DENY CONNECT SQL set', tier_low: true do + it 'has DENY CONNECT SQL set' do query = "SELECT sp.[state] FROM sys.server_principals p INNER JOIN sys.server_permissions sp ON p.principal_id = sp.grantee_principal_id WHERE sp.permission_name = 'CONNECT SQL' AND sp.class = 100 AND sp.state = 'D' AND p.name = '#{@login_under_test}' AND p.[type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end else it 'has is_disabled set' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}' AND is_disabled = '1';" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end end end @@ -258,18 +246,18 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) describe "Modify a #{testcase} login" do before(:all) { remove_test_logins(host) } - it "should create an initial #{testcase}", tier_low: true do + it "should create an initial #{testcase}" do options = { 'svrroles' => '{\'sysadmin\' => 1}' } pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end - it 'exists in the principals table on creation', tier_low: true do + it 'exists in the principals table on creation' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it "should modify a #{testcase} login", tier_low: true do + it "should modify a #{testcase} login" do options = { 'disabled' => true, 'default_database' => db_name.to_s, 'default_language' => 'Spanish', @@ -277,22 +265,22 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) 'check_policy' => true, 'svrroles' => '{\'sysadmin\' => 1, \'serveradmin\' => 1}' } pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end if testcase == 'SQL_LOGIN user' - it 'has is_expiration_checked set', tier_low: true do + it 'has is_expiration_checked set' do query = "SELECT name as LOGIN_NAME, is_expiration_checked FROM SYS.SQL_LOGINS WHERE is_expiration_checked = '1' AND name = '#{@login_under_test}';" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has is_policy_checked set', tier_low: true do + it 'has is_policy_checked set' do query = "SELECT name as LOGIN_NAME, is_policy_checked FROM SYS.SQL_LOGINS WHERE is_policy_checked = '1' AND name = '#{@login_under_test}';" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end end - it 'has the specified sysadmin role', tier_low: true do + it 'has the specified sysadmin 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 JOIN sys.server_principals rol ON member.role_principal_id = rol.principal_id @@ -300,9 +288,9 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) WHERE rol.type_desc = 'SERVER_ROLE' AND rol.name = 'sysadmin' AND pri.name = '#{@login_under_test}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has the specified serveradmin role', tier_low: true do + 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 JOIN sys.server_principals rol ON member.role_principal_id = rol.principal_id @@ -310,30 +298,30 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) WHERE rol.type_desc = 'SERVER_ROLE' AND rol.name = 'serveradmin' AND pri.name = '#{@login_under_test}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has the specified default database', tier_low: true do + it 'has the specified default database' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}' AND default_database_name = '#{db_name}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it 'has the specified default langauge', tier_low: true do + it 'has the specified default langauge' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}' AND default_language_name = 'Spanish'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end if testcase == 'WINDOWS_LOGIN group' - it 'has DENY CONNECT SQL set', tier_low: true do + it 'has DENY CONNECT SQL set' do query = "SELECT sp.[state] FROM sys.server_principals p INNER JOIN sys.server_permissions sp ON p.principal_id = sp.grantee_principal_id WHERE sp.permission_name = 'CONNECT SQL' AND sp.class = 100 AND sp.state = 'D' AND p.name = '#{@login_under_test}' AND p.[type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end else - it 'has is_disabled set', tier_low: true do + it 'has is_disabled set' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}' AND is_disabled = '1';" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end end end @@ -341,31 +329,25 @@ def create_login_manifest(testcase, login_name, login_password, options = {}) describe "Delete #{testcase} login" do before(:all) { remove_test_logins(host) } - it "should create an initial #{testcase}", tier_low: true do + it "should create an initial #{testcase}" do pp = create_login_manifest(testcase, @login_under_test, @login_passwd) - ensure_manifest_execute(pp) + apply_manifest(pp, catch_failures: true) end - it 'exists in the principals table on creation', tier_low: true do + it 'exists in the principals table on creation' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 1)) - end - - it "should remove a #{testcase} on ensure => absent", tier_low: true do - options = { 'ensure' => 'absent' } - pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) - ensure_manifest_execute(pp) + run_sql_query(run_sql_query_opts_as_sa(query, 1)) end - it "remove a #{testcase} should be idempotent", tier_low: true do + it "should remove a #{testcase} on ensure => absent idempotently" do options = { 'ensure' => 'absent' } pp = create_login_manifest(testcase, @login_under_test, @login_passwd, options) - execute_manifest(pp, catch_changes: true) + idempotent_apply(pp) end - it 'does not exist in the principals table after deletion', tier_low: true do + it 'does not exist in the principals table after deletion' do query = "SELECT principal_id FROM SYS.server_principals WHERE name = '#{@login_under_test}' AND [type] = '#{@sql_principal_type}'" - run_sql_query(host, run_sql_query_opts_as_sa(query, 0)) + run_sql_query(run_sql_query_opts_as_sa(query, 0)) end # rubocop:enable RSpec/InstanceVariable end diff --git a/spec/acceptance/sqlserver_role_spec.rb b/spec/acceptance/sqlserver_role_spec.rb index 76d5bdde..d8d0cc44 100644 --- a/spec/acceptance/sqlserver_role_spec.rb +++ b/spec/acceptance/sqlserver_role_spec.rb @@ -2,8 +2,7 @@ require 'securerandom' require 'erb' -host = find_only_one('sql_host') -hostname = host.hostname +hostname = ENV['TARGET_HOST'] # database name db_name = ('DB' + SecureRandom.hex(4)).upcase @@ -12,7 +11,7 @@ LOGIN3 = 'Login3_' + SecureRandom.hex(2) USER1 = 'User1_' + SecureRandom.hex(2) -describe 'Test sqlserver::role', node: host do +describe 'Test sqlserver::role' do def ensure_sqlserver_logins_users(db_name) pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -41,12 +40,10 @@ def ensure_sqlserver_logins_users(db_name) require => Sqlserver::Login['#{LOGIN1}'], } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end - context 'Start testing sqlserver::role', testrail: ['89161', '89162', '89163', '89164', '89165'] do + context 'Start testing sqlserver::role' do before(:all) do # Create database users ensure_sqlserver_logins_users(db_name) @@ -64,9 +61,7 @@ def ensure_sqlserver_logins_users(db_name) ensure => 'absent', } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end after(:all) do @@ -81,12 +76,10 @@ def ensure_sqlserver_logins_users(db_name) ensure => 'absent', } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end - it "Create server role #{@role} with optional authorization", tier_low: true do + it "Create server role #{@role} with optional authorization" do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -100,9 +93,7 @@ def ensure_sqlserver_logins_users(db_name) type => 'SERVER', } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database-specific role '#{@role}' is successfully created with specified permissions': query = "USE #{db_name}; @@ -113,7 +104,7 @@ def ensure_sqlserver_logins_users(db_name) ON spe.grantee_principal_id = spr.principal_id WHERE spr.name = '#{@role}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 2) + run_sql_query(query: query, server: hostname, expected_row_count: 2) # validate that the database-specific role '#{@role}' has correct authorization #{LOGIN1} query = "USE #{db_name}; @@ -123,10 +114,10 @@ def ensure_sqlserver_logins_users(db_name) ON spr.owning_principal_id = sl.principal_id WHERE sl.name = '#{LOGIN1}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) end - it "Create database-specific role #{@role}", tier_low: true do + it "Create database-specific role #{@role}" do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -140,9 +131,7 @@ def ensure_sqlserver_logins_users(db_name) type => 'DATABASE', } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database-specific role '#{@role}' is successfully created with specified permissions': query = "USE #{db_name}; @@ -153,10 +142,10 @@ def ensure_sqlserver_logins_users(db_name) ON pe.grantee_principal_id = pr.principal_id WHERE pr.name = '#{@role}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 6) + run_sql_query(query: query, server: hostname, expected_row_count: 6) end - it 'Create a database-specific role with the same name on two databases', tier_low: true do + it 'Create a database-specific role with the same name on two databases' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -177,9 +166,7 @@ def ensure_sqlserver_logins_users(db_name) type => 'DATABASE', } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database-specific role '#{@role}' is successfully created with specified permissions': # and that it exists in both the MASTER database and the 'db_name' database. @@ -193,10 +180,10 @@ def ensure_sqlserver_logins_users(db_name) on pr.name = dbpr.name WHERE pr.name = '#{@role}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 6) + run_sql_query(query: query, server: hostname, expected_row_count: 6) end - it "Create server role #{@role} with optional members and optional members-purge", tier_low: true do + it "Create server role #{@role} with optional members and optional members-purge" do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -211,9 +198,7 @@ def ensure_sqlserver_logins_users(db_name) members => ['#{LOGIN1}', '#{LOGIN2}', '#{LOGIN3}'], } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the server role '#{@role}' is successfully created with specified permissions': query = "USE #{db_name}; @@ -224,7 +209,7 @@ def ensure_sqlserver_logins_users(db_name) ON spe.grantee_principal_id = spr.principal_id WHERE spr.name = '#{@role}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 2) + run_sql_query(query: query, server: hostname, expected_row_count: 2) # validate that the t server role '#{@role}' has correct members (Login1, 2, 3) query = "USE #{db_name}; @@ -237,7 +222,7 @@ def ensure_sqlserver_logins_users(db_name) OR spr.name = '#{LOGIN3}' OR spr.name = 'LOGIN4';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 3) + run_sql_query(query: query, server: hostname, expected_row_count: 3) puts "Create server role #{@role} with optional members_purge:" pp = <<-MANIFEST @@ -255,9 +240,7 @@ def ensure_sqlserver_logins_users(db_name) members_purge => true, } MANIFEST - execute_manifest(pp, {}) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the t server role '#{@role}' has correct members (only Login3) query = "USE #{db_name}; @@ -269,7 +252,7 @@ def ensure_sqlserver_logins_users(db_name) OR spr.name = '#{LOGIN2}' OR spr.name = '#{LOGIN3}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) # rubocop:enable RSpec/InstanceVariable end end diff --git a/spec/acceptance/sqlserver_tsql_spec.rb b/spec/acceptance/sqlserver_tsql_spec.rb index 760420dd..4a641f28 100644 --- a/spec/acceptance/sqlserver_tsql_spec.rb +++ b/spec/acceptance/sqlserver_tsql_spec.rb @@ -2,7 +2,7 @@ require 'securerandom' require 'erb' -host = find_only_one('sql_host') +version = sql_version? # database name db_name = ('DB' + SecureRandom.hex(4)).upcase @@ -10,7 +10,7 @@ # database user: DB_LOGIN_USER = 'loginuser' + SecureRandom.hex(2) -describe 'sqlserver_tsql test', node: host do +describe 'sqlserver_tsql test' do def ensure_sqlserver_database(db_name, _ensure_val = 'present') pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -21,10 +21,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') instance => 'MSSQLSERVER', } MANIFEST - - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end context 'Test sqlserver_tsql with Windows based authentication' do @@ -41,7 +38,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') ensure_sqlserver_database('absent') end - it 'Run a simple tsql command via sqlserver_tsql:', tier_low: true do + it 'Run a simple tsql command via sqlserver_tsql:' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': instance_name => 'MSSQLSERVER', @@ -53,9 +50,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') command => "CREATE TABLE #{@table_name} (id INT, name VARCHAR(20), email VARCHAR(20));", } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) puts "validate the result of tsql command and table #{@table_name} should be created:" run_sql_query_opts = { @@ -64,11 +59,11 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') sql_admin_pass: @admin_pass, expected_row_count: 1, } - run_sql_query(host, run_sql_query_opts) + run_sql_query(run_sql_query_opts) end end - context 'Test sqlserver_tsql with default SQL Server based authentication', testrail: ['89024', '89025', '89026', '89068', '89069'] do + context 'Test sqlserver_tsql with default SQL Server based authentication' do before(:all) do # Create new database @table_name = 'Tables_' + SecureRandom.hex(3) @@ -82,7 +77,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') ensure_sqlserver_database('absent') end - it 'Run a simple tsql command via sqlserver_tsql:', tier_low: true do + it 'Run a simple tsql command via sqlserver_tsql:' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': instance_name => 'MSSQLSERVER', @@ -95,9 +90,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') command => "CREATE TABLE #{@table_name} (id INT, name VARCHAR(20), email VARCHAR(20));", } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) puts "validate the result of tsql command and table #{@table_name} should be created:" run_sql_query_opts = { @@ -106,10 +99,11 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') sql_admin_pass: @admin_pass, expected_row_count: 1, } - run_sql_query(host, run_sql_query_opts) + run_sql_query(run_sql_query_opts) end - it 'Run sqlserver_tsql WITH onlyif is true:', tier_low: true do + 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) @query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" @@ -126,10 +120,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') onlyif => "IF (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES) < 10000" } MANIFEST - - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) puts "Validate #{@table_name} is successfully created:" run_sql_query_opts = { @@ -138,10 +129,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') sql_admin_pass: @admin_pass, expected_row_count: 1, } - run_sql_query(host, run_sql_query_opts) + run_sql_query(run_sql_query_opts) end - it 'Run sqlserver_tsql WITH onlyif is false:', tier_low: true do + it 'Run sqlserver_tsql WITH onlyif is false:' do # Initilize a new table name: @table_name = 'Table_' + SecureRandom.hex(3) @query = "USE #{db_name}; SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '#{@table_name}';" @@ -159,10 +150,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') THROW 5300, 'Too many tables', 10" } MANIFEST - - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) puts "Validate #{@table_name} is NOT created:" run_sql_query_opts = { @@ -171,10 +159,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') sql_admin_pass: @admin_pass, expected_row_count: 0, } - run_sql_query(host, run_sql_query_opts) + run_sql_query(run_sql_query_opts) end - it 'Negative test: Run tsql with invalid command:', tier_low: true do + it 'Negative test: Run tsql with invalid command:' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': instance_name => 'MSSQLSERVER', @@ -187,12 +175,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') command => "invalid-tsql-command", } MANIFEST - execute_manifest(pp, acceptable_exit_codes: [0, 1]) do |r| - expect(r.stderr).to match(%r{Incorrect syntax}i) - end + apply_manifest(pp, expect_failures: true) end - it 'Negative test: Run tsql with non-existing database:', tier_low: true do + it 'Negative test: Run tsql with non-existing database:' do @table_name = 'Table_' + SecureRandom.hex(3) pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -207,9 +193,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') } MANIFEST # rubocop:enable RSpec/InstanceVariable - execute_manifest(pp, acceptable_exit_codes: [0, 1]) do |r| - expect(r.stderr).to match(%r{Non-Existing-Database}i) - end + apply_manifest(pp, expect_failures: true) end end end diff --git a/spec/acceptance/sqlserver_user_spec.rb b/spec/acceptance/sqlserver_user_spec.rb index ff3bc803..8614bbdc 100644 --- a/spec/acceptance/sqlserver_user_spec.rb +++ b/spec/acceptance/sqlserver_user_spec.rb @@ -2,13 +2,12 @@ require 'securerandom' require 'erb' -host = find_only_one('sql_host') -hostname = host.hostname +hostname = ENV['TARGET_HOST'] # database name db_name = ('DB' + SecureRandom.hex(4)).upcase -describe 'sqlserver::user test', node: host do +describe 'sqlserver::user test' do def ensure_sqlserver_database(db_name, _ensure_val = 'present') pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -29,13 +28,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') require => Sqlserver::Sp_configure['spconfig1'] } MANIFEST - - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) end - context 'Create database users with optional attributes', testrail: ['89143', '89144', '89145', '89146', '89149'] do + context 'Create database users with optional attributes' do before(:all) do # Create new database ensure_sqlserver_database(db_name) @@ -51,7 +47,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') # ensure_sqlserver_database(host, 'absent') end - it 'Create database user with optional default_schema', tier_low: true do + it 'Create database user with optional default_schema' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -69,9 +65,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') require => Sqlserver::Login['#{@db_user}'], } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database user '#{@db_user}' is successfully created with default schema 'guest': query = "USE #{db_name}; @@ -80,10 +74,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') WHERE name = '#{@db_user}' AND default_schema_name = 'guest';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) end - it 'Create database user with optional instance', tier_low: true do + it 'Create database user with optional instance' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -101,19 +95,17 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') require => Sqlserver::Login['#{@db_user}'], } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database user '#{@db_user}' is successfully created: query = "USE #{db_name}; SELECT name AS Database_User_Name FROM SYS.DATABASE_PRINCIPALS WHERE name = '#{@db_user}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) end - it 'Create database user with optional login', tier_low: true do + it 'Create database user with optional login' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -132,9 +124,7 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') require => Sqlserver::Login['#{@new_sql_login}'], } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database user '#{@db_user}' is mapped with sql login '#{@new_sql_login}': query = "USE #{db_name}; @@ -142,10 +132,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') FROM SYS.DATABASE_PRINCIPALS d, MASTER.SYS.SQL_LOGINS l WHERE d.sid = l.sid AND d.name = '#{@db_user}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) end - it 'Create database user with optional password', tier_low: true do + it 'Create database user with optional password' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -165,16 +155,14 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') require => Sqlserver::Login['#{@new_sql_login}'], } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) puts "validate that the database user '#{@db_user}' is successfully created:" query = "USE #{db_name}; SELECT * FROM SYS.DATABASE_PRINCIPALS WHERE name = '#{@db_user}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) end - it 'Delete database user', tier_low: true do + it 'Delete database user' do pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': admin_user => 'sa', @@ -190,13 +178,11 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') require => Sqlserver::Login['#{@db_user}'], } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # validate that the database user '#{@db_user}' is successfully created: query = "USE #{db_name}; SELECT * FROM SYS.DATABASE_PRINCIPALS WHERE name = '#{@db_user}';" - run_sql_query(host, query: query, server: hostname, expected_row_count: 1) + run_sql_query(query: query, server: hostname, expected_row_count: 1) pp = <<-MANIFEST sqlserver::config{'MSSQLSERVER': @@ -208,12 +194,10 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present') database => '#{db_name}', } MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, catch_failures: true) # 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(host, query: query, server: hostname, expected_row_count: 0) + run_sql_query(query: query, server: hostname, expected_row_count: 0) # rubocop:enable RSpec/InstanceVariable end end diff --git a/spec/acceptance/z_last_sqlserver_features_spec.rb b/spec/acceptance/z_last_sqlserver_features_spec.rb index 6557233d..c5f5a57c 100644 --- a/spec/acceptance/z_last_sqlserver_features_spec.rb +++ b/spec/acceptance/z_last_sqlserver_features_spec.rb @@ -2,51 +2,60 @@ require 'erb' require 'json' -host = find_only_one('sql_host') -describe 'sqlserver_features', node: host do - sql_version = host['sql_version'].to_s +version = sql_version? +describe 'sqlserver_features', if: version.to_i != 2012 do def ensure_sql_features(features, ensure_val = 'present') - manifest = <<-MANIFEST + pp = <<-MANIFEST sqlserver::config{ 'MSSQLSERVER': admin_pass => '<%= SQL_ADMIN_PASS %>', admin_user => '<%= SQL_ADMIN_USER %>', } sqlserver_features{ 'MSSQLSERVER': - ensure => <%= ensure_value %>, + ensure => #{ensure_val}, source => 'H:', is_svc_account => "$::hostname\\\\Administrator", is_svc_password => 'Qu@lity!', - features => [ <%= mssql_features %> ], + features => #{features}, windows_feature_source => 'I:\\sources\\sxs', } MANIFEST - ensure_value = ensure_val - mssql_features = features.map { |x| "'#{x}'" }.join(', ') + apply_manifest(pp, catch_failures: true) + end - pp = ERB.new(manifest).result(binding) + def bind_and_apply_failing_manifest(features, ensure_val = 'present') + pp = <<-MANIFEST + sqlserver::config{ 'MSSQLSERVER': + admin_pass => '<%= SQL_ADMIN_PASS %>', + admin_user => '<%= SQL_ADMIN_USER %>', + } + sqlserver_features{ 'MSSQLSERVER': + ensure => #{ensure_val}, + source => 'H:', + is_svc_account => "$::hostname\\\\Administrator", + features => #{features}, + } + MANIFEST - execute_manifest(pp) do |r| - expect(r.stderr).not_to match(%r{Error}i) - end + apply_manifest(pp, expect_failures: true) end context 'can install' do - features = ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + features = if version.to_i >= 2016 + ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + else + ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] + end before(:all) do - remove_sql_features(host, features: features, version: sql_version) - end - - after(:all) do - remove_sql_features(host, features: features, version: sql_version) + ensure_sql_features(features, 'absent') end - it 'all possible features', tier_low: true do + it 'all possible features' do ensure_sql_features(features) - validate_sql_install(host, version: sql_version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).to match(%r{Client Tools Connectivity}) expect(r.stdout).to match(%r{Client Tools Backwards Compatibility}) expect(r.stdout).to match(%r{Client Tools SDK}) @@ -57,21 +66,16 @@ def ensure_sql_features(features, ensure_val = 'present') end context 'can remove' do - features = ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + features = if version.to_i >= 2016 + ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + else + ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] + end - before(:all) do - ensure_sql_features(features) - end - - after(:all) do - # redundant but necessary in case our manifest fails - remove_sql_features(host, features: features, version: sql_version) - end - - it 'all possible features', tier_low: true do + it 'all possible features' do ensure_sql_features(features, 'absent') - validate_sql_install(host, version: sql_version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).not_to match(%r{Client Tools Connectivity}) expect(r.stdout).not_to match(%r{Client Tools Backwards Compatibility}) expect(r.stdout).not_to match(%r{Client Tools SDK}) @@ -82,48 +86,32 @@ def ensure_sql_features(features, ensure_val = 'present') end context 'can remove independent feature' do - if sql_version.to_i >= 2016 - all_possible_features = ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] - features = ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] - else - all_possible_features = ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] - features = ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] - end + features = if version.to_i >= 2016 + ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + else + ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] + end before(:all) do - remove_sql_features(host, features: all_possible_features, version: sql_version) - end - - before(:each) do ensure_sql_features(features) end after(:all) do - # only lower-level should be installed, but wipe all in case manifest misbehaves - remove_sql_features(host, features: all_possible_features, version: sql_version) + ensure_sql_features(features, 'absent') end - it "'BC'", tier_low: true do + it "'BC'" do ensure_sql_features(features - ['BC']) - validate_sql_install(host, version: sql_version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).not_to match(%r{Client Tools Backwards Compatibility}) end end - it "'Conn'", tier_low: true do - ensure_sql_features(features - ['Conn']) - - validate_sql_install(host, version: sql_version) do |r| - expect(r.stdout).not_to match(%r{Client Tools Connectivity}) - end - end - - # TODO: Guard on SQL 2016 and 2017 - it "'ADV_SSMS'", unless: sql_version.to_i >= 2016, tier_low: true do + it "'ADV_SSMS'", unless: version.to_i >= 2016 do ensure_sql_features(features - ['ADV_SSMS']) - validate_sql_install(host, version: sql_version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).not_to match(%r{Management Tools - Complete}) # also verify SSMS is still present @@ -131,98 +119,63 @@ def ensure_sql_features(features, ensure_val = 'present') end end - it "'SDK'", tier_low: true do - ensure_sql_features(features - ['SDK']) + it "'SDK' + 'IS" do + ensure_sql_features(features - ['SDK', 'IS']) - validate_sql_install(host, version: sql_version) do |r| + validate_sql_install(version: version) do |r| expect(r.stdout).not_to match(%r{Client Tools SDK}) end end - - it "'IS'", tier_low: true do - ensure_sql_features(features - ['IS']) - - validate_sql_install(host, version: sql_version) do |r| - expect(r.stdout).not_to match(%r{Integration Services}) - end - end - - it "'MDS'", tier_low: true do - ensure_sql_features(features - ['MDS']) - - validate_sql_install(host, version: sql_version) do |r| - expect(r.stdout).not_to match(%r{Master Data Services}) - end - end - - it "'DQC'", tier_low: true do - ensure_sql_features(features - ['DQC']) - - validate_sql_install(host, version: sql_version) do |r| - expect(r.stdout).not_to match(%r{Data Quality Client}) - end - end end context 'with negative test cases' do - def bind_and_apply_failing_manifest(features, ensure_val = 'present') - failing_manifest = <<-MANIFEST - sqlserver::config{ 'MSSQLSERVER': - admin_pass => '<%= SQL_ADMIN_PASS %>', - admin_user => '<%= SQL_ADMIN_USER %>', - } - sqlserver_features{ 'MSSQLSERVER': - ensure => <%= ensure_value %>, - source => 'H:', - is_svc_account => "$::hostname\\\\Administrator", - features => [ <%= mssql_features %> ], - } - MANIFEST - - ensure_value = ensure_val - mssql_features = features.map { |x| "'#{x}'" }.join(', ') - - pp = ERB.new(failing_manifest).result(binding) - - execute_manifest(pp) do |r| - expect(r.stderr).to match(%r{error}i) - end - end - - it 'fails when an is_svc_account is supplied and a password is not', tier_low: true do + it 'fails when an is_svc_account is supplied and a password is not' do features = ['IS'] bind_and_apply_failing_manifest(features) end - it 'fails when ADV_SSMS is supplied but SSMS is not', tier_low: true do - skip('This test is blocked by FM-2712') + it 'fails when ADV_SSMS is supplied but SSMS is not - FM-2712' do + pending('error not shown on Sql Server 2014') if version .to_i == 2014 features = ['BC', 'Conn', 'ADV_SSMS', 'SDK'] - ensure_sql_features(features) + bind_and_apply_failing_manifest(features) end end context 'with no installed instances' do + # Currently this test can only be run on a machine once and will error if run a second time context 'can install' do features = ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + def remove_sql_instance + pp = <<-MANIFEST + sqlserver_instance{'MSSQLSERVER': + ensure => absent, + source => 'H:', + sql_sysadmin_accounts => ['Administrator'], + } + MANIFEST + idempotent_apply(pp) + end + before(:all) do - json_result = JSON.parse((on host, puppet('facts --render-as json')).raw_output)['values']['sqlserver_instances'] - names = json_result.map { |k, _v| json_result[k].keys }.flatten - remove_sql_instances(host, version: sql_version, instance_names: names) + remove_sql_instance end after(:all) do - remove_sql_features(host, features: features, version: sql_version) + ensure_sql_features(features, 'absent') end - it 'all possible features', tier_low: true do + it 'all possible features' do ensure_sql_features(features) - validate_sql_install(host, version: sql_version) do |r| + validate_sql_install(version: version) do |r| # SQL Server 2016 will not install the client tools features. - expect(r.stdout).to match(%r{Client Tools Connectivity}) unless sql_version.to_i >= 2016 - expect(r.stdout).to match(%r{Client Tools Backwards Compatibility}) unless sql_version.to_i >= 2016 - expect(r.stdout).to match(%r{Client Tools SDK}) unless sql_version.to_i >= 2016 + expect(r.stdout).not_to match(%r{MSSQLSERVER\s+Database Engine Services}) + expect(r.stdout).not_to match(%r{MSSQLSERVER\s+SQL Server Replication}) + expect(r.stdout).not_to match(%r{MSSQLSERVER\s+Data Quality Services}) + expect(r.stdout).to match(%r{Client Tools Connectivity}) unless version.to_i >= 2016 + expect(r.stdout).to match(%r{Client Tools Backwards Compatibility}) unless version.to_i >= 2016 + expect(r.stdout).to match(%r{Client Tools SDK}) unless version.to_i >= 2016 expect(r.stdout).to match(%r{Integration Services}) expect(r.stdout).to match(%r{Master Data Services}) end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 7ccffae5..4ac8d7e0 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,112 +1,6 @@ -require 'beaker-pe' -require 'beaker-puppet' -require 'beaker-rspec/spec_helper' -require 'beaker-rspec/helpers/serverspec' -require 'sql_testing_helpers' -require 'beaker/puppet_install_helper' -require 'beaker/testmode_switcher' -require 'beaker/testmode_switcher/dsl' +# frozen_string_literal: true -WIN_ISO_ROOT = 'https://artifactory.delivery.puppetlabs.net/artifactory/generic__iso/iso/windows'.freeze -WIN_2012R2_ISO = 'en_windows_server_2012_r2_with_update_x64_dvd_6052708.iso'.freeze -QA_RESOURCE_ROOT = 'https://artifactory.delivery.puppetlabs.net/artifactory/generic__iso/iso/SQLServer'.freeze -SQL_2019_ISO = 'SQLServer2019CTP2.4-x64-ENU.iso'.freeze -SQL_2017_ISO = 'SQLServer2017-x64-ENU.iso'.freeze -SQL_2016_ISO = 'en_sql_server_2016_enterprise_with_service_pack_1_x64_dvd_9542382.iso'.freeze -SQL_2014_ISO = 'SQLServer2014SP3-FullSlipstream-x64-ENU.iso'.freeze -SQL_2012_ISO = 'SQLServer2012SP1-FullSlipstream-ENU-x64.iso'.freeze -SQL_ADMIN_USER = 'sa'.freeze -SQL_ADMIN_PASS = 'Pupp3t1@'.freeze +require 'puppet_litmus' +require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_acceptance_local.rb')) -RSpec.configure do |c| - # Readable test descriptions - c.formatter = :documentation - c.before(:suite) do - host = find_only_one('sql_host') - base_install(host['sql_version']) - # Verify that the version in the host config file is indeed the version on the machine - execute_powershell_script_on(host, 'Invoke-Sqlcmd -Query "SELECT @@VERSION;" -QueryTimeout 3') do |result| - unless result.stdout.include?(host[:sql_version].to_s) - raise "Version in host config #{host[:sql_version]} does not match SQL version #{result}" - end - end - end -end - -# Install PE -run_puppet_install_helper -configure_type_defaults_on(hosts) - -# Install PE License onto Master, if one exists. -install_pe_license(master) unless hosts_as('master').empty? - -# Determine root path of local module source. -proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) -# In CI install from staging forge, otherwise from local -staging = { module_name: 'puppetlabs-sqlserver' } -local = { module_name: 'sqlserver', source: proj_root } - -unless ENV['MODULE_provision'] == 'no' - hosts_as('sql_host').each do |agent| - # Emit CommonProgramFiles environment variable - common_program_files = agent.get_env_var('CommonProgramFiles') - - # Workarounds due to BKR-914 - # - newline chars indicate matching more than one env var - # - env var key matching is very loose. e.g. CommonProgramFiles(x86) can be returned - common_program_files = '' if common_program_files.include?("\n") - common_program_files = '' unless common_program_files.start_with?('CommonProgramFiles=') - # If the env var is not found use a workaround to inject regex into the grep call - common_program_files = agent.get_env_var('^CommonProgramFiles=') if common_program_files == '' - - if common_program_files == '' - program_files = agent.get_env_var('PROGRAMFILES') - - # Workarounds due to BKR-914 - # - newline chars indicate matching more than one env var - # - env var key matching is very loose. e.g. ProgramFiles(x86) can be returned - program_files = '' if program_files.include?("\n") - program_files = '' unless program_files.start_with?('PROGRAMFILES=') - # If the env var is not found use a workaround to inject regex into the grep call - program_files = agent.get_env_var('^PROGRAMFILES=') if program_files == '' - - program_files = program_files.split('=')[1] - agent.add_env_var('CommonProgramFiles', "#{program_files}\\Common Files") - end - - # Install Forge certs to allow for PMT installation. - install_ca_certs - - # Install test helper modules onto agent. - ['puppetlabs-mount_iso', 'cyberious-pget'].each do |dep| - on(agent, puppet("module install #{dep}")) - end - - # Install sqlserver dependencies. - on(agent, puppet('module install puppetlabs-stdlib')) - on(agent, puppet('module install puppetlabs-powershell')) - - # Mount windows 2012R2 ISO to allow install of .NET 3.5 Windows Feature - iso_opts = { - folder: WIN_ISO_ROOT, - file: WIN_2012R2_ISO, - drive_letter: 'I', - } - mount_iso(agent, iso_opts) - - # Install sqlserver module from local source. - # See FM-5062 for more details. - copy_module_to(agent, local) - end - - hosts_as('master').each do |host| - # Install sqlserver dependencies. - on(host, puppet('module install puppetlabs-stdlib')) - on(host, puppet('module install puppetlabs-powershell')) - - # Install sqlserver module from local source. - # See FM-5062 for more details. - local = { module_name: 'sqlserver', source: proj_root } - copy_module_to(host, local) - end -end +PuppetLitmus.configure! diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb new file mode 100644 index 00000000..33a225d7 --- /dev/null +++ b/spec/spec_helper_acceptance_local.rb @@ -0,0 +1,217 @@ +require 'puppet_litmus' +require 'singleton' + +class Helper + include Singleton + include PuppetLitmus +end + +WIN_ISO_ROOT = 'https://artifactory.delivery.puppetlabs.net/artifactory/generic__iso/iso/windows'.freeze +WIN_2012R2_ISO = 'en_windows_server_2012_r2_with_update_x64_dvd_6052708.iso'.freeze +QA_RESOURCE_ROOT = 'https://artifactory.delivery.puppetlabs.net/artifactory/generic__iso/iso/SQLServer'.freeze +SQL_2019_ISO = 'SQLServer2019CTP2.4-x64-ENU.iso'.freeze +SQL_2017_ISO = 'SQLServer2017-x64-ENU.iso'.freeze +SQL_2016_ISO = 'en_sql_server_2016_enterprise_with_service_pack_1_x64_dvd_9542382.iso'.freeze +SQL_2014_ISO = 'SQLServer2014SP3-FullSlipstream-x64-ENU.iso'.freeze +SQL_2012_ISO = 'SQLServer2012SP1-FullSlipstream-ENU-x64.iso'.freeze +SQL_ADMIN_USER = 'sa'.freeze +SQL_ADMIN_PASS = 'Pupp3t1@'.freeze + +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 puppet/archive') + + iso_opts = { + folder: WIN_ISO_ROOT, + file: WIN_2012R2_ISO, + drive_letter: 'I', + } + mount_iso(iso_opts) + + base_install(sql_version?) + end +end + +def node_vars? + hash = Helper.instance.inventory_hash_from_inventory_file + + hash['groups'].each do |group| + group['targets'].each do |node| + if ENV['TARGET_HOST'] == node['uri'] + return node['vars'] + end + end + end +end + +def sql_version? + vars = node_vars? + + if vars['sqlversion'] + return vars['sqlversion'].match(%r{sqlserver_(.*)})[1] + end + # Return's a default version if none was given + '2016' +end + +def mount_iso(opts = {}) + folder = opts[:folder] + file = opts[:file] + drive_letter = opts[:drive_letter] + + pp = <<-MANIFEST + $p_src = '#{folder}/#{file}' + $source = 'C:\\#{file}' + archive { $source: + ensure => present, + source => $p_src, + user => 0, + group => 0, + } + mount_iso{$source: + require => Archive[$source], + drive_letter => '#{drive_letter}', + } + MANIFEST + Helper.instance.apply_manifest(pp) +end + +def base_install(sql_version) + case sql_version.to_i + when 2012 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2012_ISO, + drive_letter: 'H', + } + when 2014 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2014_ISO, + drive_letter: 'H', + } + when 2016 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2016_ISO, + drive_letter: 'H', + } + when 2017 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2017_ISO, + drive_letter: 'H', + } + when 2019 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2019_ISO, + drive_letter: 'H', + } + end + # Mount the ISO on the agent + mount_iso(iso_opts) + # Install Microsoft SQL on the agent before running any tests + features = ['DQ', 'FullText', 'Replication', 'SQLEngine'] + install_sqlserver(features) +end + +def install_sqlserver(features) + # this method installs SQl server on a given host + pp = <<-MANIFEST + sqlserver_instance{'MSSQLSERVER': + source => 'H:', + features => #{features}, + security_mode => 'SQL', + sa_pwd => 'Pupp3t1@', + sql_sysadmin_accounts => ['Administrator'], + install_switches => { + 'TCPENABLED' => 1, + 'SQLBACKUPDIR' => 'C:\\MSSQLSERVER\\backupdir', + 'SQLTEMPDBDIR' => 'C:\\MSSQLSERVER\\tempdbdir', + 'INSTALLSQLDATADIR' => 'C:\\MSSQLSERVER\\datadir', + 'INSTANCEDIR' => 'C:\\Program Files\\Microsoft SQL Server', + 'INSTALLSHAREDDIR' => 'C:\\Program Files\\Microsoft SQL Server', + 'INSTALLSHAREDWOWDIR' => 'C:\\Program Files (x86)\\Microsoft SQL Server', + }, + windows_feature_source => 'I:\\sources\\sxs', + } + MANIFEST + Helper.instance.apply_manifest(pp) +end + +def run_sql_query(opts = {}, &block) + query = opts[:query] + server = opts[:server] + instance = opts[:instance] + sql_admin_pass = opts[:sql_admin_pass] ||= SQL_ADMIN_PASS + 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}\" + 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 + + Tempfile.open 'tmp.ps1' do |tempfile| + File.open(tempfile.path, 'w') { |file| file.puts powershell } + bolt_upload_file(tempfile.path, 'C:/cygwin64/home/Administrator/tmp.ps1') + end + # create_remote_file('tmp.ps1', powershell) + + Helper.instance.run_shell('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_given? + case block.arity + when 0 + yield self + else + yield r + end +end + +def validate_sql_install(opts = {}, &block) + bootstrap_dir, setup_dir = get_install_paths(opts[:version]) + + # NOTE: executing a fully qualified setup.exe quoted this way fails + # but that can be circumvented by first changing directories + cmd = "cd \"#{setup_dir}\" && setup.exe /Action=RunDiscovery /q" + Helper.instance.run_shell("cmd.exe /c '#{cmd}'") + + cmd = "type \"#{bootstrap_dir}\\Log\\Summary.txt\"" + result = Helper.instance. run_shell("cmd.exe /c '#{cmd}'") + return unless block_given? + case block.arity + when 0 + yield self + else + yield result + end +end + +def get_install_paths(version) + vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150' } + + raise _('Valid version must be specified') unless vers.keys.include?(version) + + dir = "%ProgramFiles%/Microsoft SQL Server/#{vers[version]}/Setup Bootstrap" + sql_directory = 'SQL' + sql_directory += 'Server' if version != '2017' + + [dir, "#{dir}\\#{sql_directory}#{version}"] +end