diff --git a/README.md b/README.md index 3625ee7f..bb86804a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ## Overview -The sqlserver module installs and manages Microsoft SQL Server 2012, 2014, 2016, 2017, 2019 on Windows systems. +The sqlserver module installs and manages Microsoft SQL Server 2012, 2014, 2016, 2017, 2019 and 2022 on Windows systems. ## Module Description @@ -272,9 +272,9 @@ For information on the classes and types, see the [REFERENCE.md](https://github. ## Limitations -SQL 2017 and 2019 detection support has been added. This support is limited to functionality already present for other versions. No new SQL 2017 or above specific functionality has been added in this release. +SQL 2017, 2019 and 2022 detection support has been added. This support is limited to functionality already present for other versions. -This module can manage only a single version of SQL Server on a given host (one and only one of SQL Server 2012, 2014, 2016, 2017, or 2019). The module is able to manage multiple SQL Server instances of the same version. +This module can manage only a single version of SQL Server on a given host (one and only one of SQL Server 2012, 2014, 2016, 2017, 2019 or 2022). The module is able to manage multiple SQL Server instances of the same version. This module cannot manage the SQL Server Native Client SDK (also known as SNAC_SDK). The SQL Server installation media can install the SDK, but it is not able to uninstall the SDK. Note that the 'sqlserver_features' fact detects the presence of the SDK. diff --git a/lib/puppet/provider/sqlserver_features/mssql.rb b/lib/puppet/provider/sqlserver_features/mssql.rb index 64e4e559..cbcfb415 100644 --- a/lib/puppet/provider/sqlserver_features/mssql.rb +++ b/lib/puppet/provider/sqlserver_features/mssql.rb @@ -128,7 +128,7 @@ def create instance_version = PuppetX::Sqlserver::ServerHelper.sql_version_from_install_source(@resource[:source]) Puppet.debug("Installation source detected as version #{instance_version}") unless instance_version.nil? - install_net_35(@resource[:windows_feature_source]) unless [SQL_2016, SQL_2017, SQL_2019].include? instance_version + install_net_35(@resource[:windows_feature_source]) if [SQL_2012, SQL_2014].include? instance_version debug "Installing features #{@resource[:features]}" add_features(@resource[:features]) diff --git a/lib/puppet/provider/sqlserver_instance/mssql.rb b/lib/puppet/provider/sqlserver_instance/mssql.rb index 4fd04c8a..e3733915 100644 --- a/lib/puppet/provider/sqlserver_instance/mssql.rb +++ b/lib/puppet/provider/sqlserver_instance/mssql.rb @@ -105,7 +105,7 @@ def create instance_version = PuppetX::Sqlserver::ServerHelper.sql_version_from_install_source(@resource[:source]) Puppet.debug("Installation source detected as version #{instance_version}") unless instance_version.nil? - install_net_35(@resource[:windows_feature_source]) unless [SQL_2016, SQL_2017, SQL_2019].include? instance_version + install_net_35(@resource[:windows_feature_source]) if [SQL_2012, SQL_2014].include? instance_version add_features(@resource[:features]) end diff --git a/lib/puppet_x/sqlserver/features.rb b/lib/puppet_x/sqlserver/features.rb index b388ed77..1cb249c8 100644 --- a/lib/puppet_x/sqlserver/features.rb +++ b/lib/puppet_x/sqlserver/features.rb @@ -7,8 +7,9 @@ SQL_2016 ||= 'SQL_2016' SQL_2017 ||= 'SQL_2017' SQL_2019 ||= 'SQL_2019' +SQL_2022 ||= 'SQL_2022' -ALL_SQL_VERSIONS ||= [SQL_2012, SQL_2014, SQL_2016, SQL_2017, SQL_2019].freeze +ALL_SQL_VERSIONS ||= [SQL_2012, SQL_2014, SQL_2016, SQL_2017, SQL_2019, SQL_2022].freeze # rubocop:disable Style/ClassAndModuleChildren module PuppetX @@ -39,6 +40,10 @@ class Features # rubocop:disable Style/Documentation major_version: 15, registry_path: '150', }, + SQL_2022 => { + major_version: 16, + registry_path: '160', + }, }.freeze SQL_REG_ROOT ||= 'Software\Microsoft\Microsoft SQL Server' @@ -145,6 +150,8 @@ def self.get_instance_features(reg_root, instance_name) def self.get_shared_features(version) shared_features = { + # Client tools support removed with SQLServer 2022 + # (ref https://learn.microsoft.com/en-us/sql/database-engine/install-windows/install-sql-server-on-server-core?view=sql-server-ver16#BK_SupportedFeatures) 'Connectivity_Full' => 'Conn', # Client Tools Connectivity 'SDK_Full' => 'SDK', # Client Tools SDK 'MDSCoreFeature' => 'MDS', # Master Data Services @@ -156,7 +163,7 @@ def self.get_shared_features(version) 'SQL_DReplay_Controller' => 'DREPLAY_CTLR', # Distributed Replay Controller 'SQL_DReplay_Client' => 'DREPLAY_CLT', # Distributed Replay Client 'sql_shared_mr' => 'SQL_SHARED_MR', # R Server (Standalone) - + # SQL Client Connectivity SDK (Installed by default) # also WMI: SqlService WHERE SQLServiceType = 4 # MsDtsServer 'SQL_DTS_Full' => 'IS', # Integration Services # currently ignoring Reporting Services Shared diff --git a/lib/puppet_x/sqlserver/server_helper.rb b/lib/puppet_x/sqlserver/server_helper.rb index e2733d39..26128485 100644 --- a/lib/puppet_x/sqlserver/server_helper.rb +++ b/lib/puppet_x/sqlserver/server_helper.rb @@ -44,6 +44,7 @@ def self.sql_version_from_install_source(source_dir) ver = content.match('"(.+)"') return nil if ver.nil? + return SQL_2022 if ver[1].start_with?('16.') return SQL_2019 if ver[1].start_with?('15.') return SQL_2017 if ver[1].start_with?('14.') return SQL_2016 if ver[1].start_with?('13.') diff --git a/metadata.json b/metadata.json index 2506bcf8..3efb850c 100644 --- a/metadata.json +++ b/metadata.json @@ -2,7 +2,7 @@ "name": "puppetlabs-sqlserver", "version": "3.2.1", "author": "puppetlabs", - "summary": "The `sqlserver` module installs and manages MS SQL Server 2012, 2014, 2016, 2017, and 2019 on Windows systems.", + "summary": "The `sqlserver` module installs and manages MS SQL Server 2012, 2014, 2016, 2017, 2019 and 2022 on Windows systems.", "license": "proprietary", "source": "https://github.com/puppetlabs/puppetlabs-sqlserver", "project_page": "https://github.com/puppetlabs/puppetlabs-sqlserver", @@ -44,7 +44,8 @@ "sql2014", "sql2016", "sql2017", - "sql2019", + "sql2019", + "sql2022", "tsql", "database" ], diff --git a/spec/acceptance/z_last_sqlserver_features_spec.rb b/spec/acceptance/z_last_sqlserver_features_spec.rb index 7ea29b7c..6c5bf20f 100644 --- a/spec/acceptance/z_last_sqlserver_features_spec.rb +++ b/spec/acceptance/z_last_sqlserver_features_spec.rb @@ -15,8 +15,8 @@ def ensure_sql_features(features, ensure_val = 'present') pp = <<-MANIFEST sqlserver::config{ 'MSSQLSERVER': - admin_pass => '<%= SQL_ADMIN_PASS %>', - admin_user => '<%= SQL_ADMIN_USER %>', + admin_pass => '<%= SQL_ADMIN_PASS %>', + admin_user => '<%= SQL_ADMIN_USER %>', } sqlserver_features{ 'MSSQLSERVER': ensure => #{ensure_val}, @@ -35,8 +35,8 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') user = Helper.instance.run_shell('$env:UserName').stdout.chomp pp = <<-MANIFEST sqlserver::config{ 'MSSQLSERVER': - admin_pass => '<%= SQL_ADMIN_PASS %>', - admin_user => '<%= SQL_ADMIN_USER %>', + admin_pass => '<%= SQL_ADMIN_PASS %>', + admin_user => '<%= SQL_ADMIN_USER %>', } sqlserver_features{ 'MSSQLSERVER': ensure => #{ensure_val}, @@ -50,7 +50,10 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') end context 'can install' do - features = if version.to_i >= 2016 + # Client Tools removed in Server2022 (Backwards Compatibility, Connectivity, SDK) + features = if version.to_i == 2022 + ['IS', 'MDS', 'DQC'] + elsif version.to_i >= 2016 && version.to_i < 2022 ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] else ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] @@ -64,9 +67,12 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') ensure_sql_features(features) 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}) + # Client Tools removed in Server2022 + unless version.to_i == 2022 + 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}) + end expect(r.stdout).to match(%r{Integration Services}) expect(r.stdout).to match(%r{Master Data Services}) end @@ -74,7 +80,9 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') end context 'can remove' do - features = if version.to_i >= 2016 + features = if version.to_i == 2022 + ['IS', 'MDS', 'DQC'] + elsif version.to_i >= 2016 && version.to_i < 2022 ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] else ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] @@ -84,9 +92,12 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') ensure_sql_features(features, 'absent') 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}) + # Client Tools removed in Server2022 + unless version.to_i == 2022 + 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}) + end expect(r.stdout).not_to match(%r{Integration Services}) expect(r.stdout).not_to match(%r{Master Data Services}) end @@ -94,7 +105,9 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') end context 'can remove independent feature' do - features = if version.to_i >= 2016 + features = if version.to_i == 2022 + ['IS', 'MDS', 'DQC'] + elsif version.to_i >= 2016 && version.to_i < 2022 ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] else ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] @@ -108,7 +121,7 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') ensure_sql_features(features, 'absent') end - it "'BC'" do + it "'BC'", unless: version.to_i == 2022 do ensure_sql_features(features - ['BC']) validate_sql_install(version: version) do |r| @@ -127,7 +140,7 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') end end - it "'SDK' + 'IS" do + it "'SDK' + 'IS", unless: version.to_i == 2022 do ensure_sql_features(features - ['SDK', 'IS']) validate_sql_install(version: version) do |r| @@ -152,7 +165,13 @@ def bind_and_apply_failing_manifest(features, ensure_val = 'present') 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'] + features = if version.to_i == 2022 + ['IS', 'MDS', 'DQC'] + elsif version.to_i >= 2016 && version.to_i < 2022 + ['BC', 'Conn', 'SDK', 'IS', 'MDS', 'DQC'] + else + ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'DQC'] + end def remove_sql_instance user = Helper.instance.run_shell('$env:UserName').stdout.chomp diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb index 5a827a27..eb68be52 100644 --- a/spec/spec_helper_acceptance_local.rb +++ b/spec/spec_helper_acceptance_local.rb @@ -11,6 +11,7 @@ class Helper WIN_ISO_ROOT = 'https://artifactory.delivery.puppetlabs.net/artifactory/generic__iso/iso/windows' WIN_2019_ISO = 'en_windows_server_2019_updated_july_2020_x64_dvd_94453821.iso' QA_RESOURCE_ROOT = 'https://artifactory.delivery.puppetlabs.net/artifactory/generic__iso/iso/SQLServer' +SQL_2022_ISO = 'SQLServer2022-x64-ENU-Dev.iso' SQL_2019_ISO = 'SQLServer2019CTP2.4-x64-ENU.iso' SQL_2017_ISO = 'SQLServer2017-x64-ENU.iso' SQL_2016_ISO = 'en_sql_server_2016_enterprise_with_service_pack_1_x64_dvd_9542382.iso' @@ -120,6 +121,12 @@ def base_install(sql_version) file: SQL_2019_ISO, drive_letter: 'H', } + when 2022 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2022_ISO, + drive_letter: 'H' + } end # Mount the ISO on the agent mount_iso(iso_opts) @@ -217,12 +224,14 @@ def validate_sql_install(opts = {}, &block) end def get_install_paths(version) - vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150' } + vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150', '2022' => '160' } raise _('Valid version must be specified') unless vers.keys.include?(version) dir = "C://Program Files/Microsoft SQL Server/#{vers[version]}/Setup Bootstrap" sql_directory = case version + when '2022' + "SQL#{version}" when '2019' "SQL#{version}CTP2.4" when '2017' diff --git a/spec/sql_testing_helpers.rb b/spec/sql_testing_helpers.rb index 4f147bf5..79d215f6 100644 --- a/spec/sql_testing_helpers.rb +++ b/spec/sql_testing_helpers.rb @@ -120,6 +120,12 @@ def base_install(sql_version) file: SQL_2019_ISO, drive_letter: 'H', } + when 2022 + iso_opts = { + folder: QA_RESOURCE_ROOT, + file: SQL_2022_ISO, + drive_letter: 'H' + } end host = find_only_one('sql_host') # Mount the ISO on the agent @@ -162,15 +168,23 @@ def remove_sql_instances(host, opts = {}) end def get_install_paths(version) - vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150' } + vers = { '2012' => '110', '2014' => '120', '2016' => '130', '2017' => '140', '2019' => '150', '2022' => '160' } 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}"] + dir = "C://Program Files/Microsoft SQL Server/#{vers[version]}/Setup Bootstrap" + sql_directory = case version + when '2022' + "SQL#{version}" + when '2019' + "SQL#{version}CTP2.4" + when '2017' + "SQL#{version}" + else + "SQLServer#{version}" + end + + [dir, "#{dir}\\#{sql_directory}"] end def install_pe_license(host) diff --git a/spec/unit/puppet_x/sql_connection_spec.rb b/spec/unit/puppet_x/sql_connection_spec.rb index cca63f48..e685715f 100644 --- a/spec/unit/puppet_x/sql_connection_spec.rb +++ b/spec/unit/puppet_x/sql_connection_spec.rb @@ -24,7 +24,7 @@ def stub_connection context 'command execution' do before :each do stub_connection - allow(@connection).to receive(:Open).with('Provider=MSOLEDBSQL;Initial Catalog=master;Application Name=Puppet;Data Source=.;DataTypeComptibility=80;User ID=sa;Password=Pupp3t1@') + allow(@connection).to receive(:Open).with('Provider=MSOLEDBSQL;Initial Catalog=master;Application Name=Puppet;Data Source=.;DataTypeComptibility=80;UID=sa;PWD=Pupp3t1@') end it 'does not raise an error but populate has_errors with message' do allow(@connection.Errors).to receive(:count).and_return(2)