From 84f75b7136994f7347e1bd74033ad59c4270c77a Mon Sep 17 00:00:00 2001 From: Glenn Sarti Date: Fri, 2 Jun 2017 11:12:28 -0700 Subject: [PATCH 1/5] (MODULES-5031) Modify facts for SQL Server 2016 Previously the custom facts for the module only supported SQL Server 2012 and 2014. This commit updates the facts to support usage on SQL Server 2016, and adds additional feature detection for features that have been added in Server 2016, or missed out on Server 2014. --- lib/puppet_x/sqlserver/features.rb | 90 ++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/lib/puppet_x/sqlserver/features.rb b/lib/puppet_x/sqlserver/features.rb index bd3a3f02..57a8cf61 100644 --- a/lib/puppet_x/sqlserver/features.rb +++ b/lib/puppet_x/sqlserver/features.rb @@ -1,5 +1,8 @@ SQL_2012 ||= 'SQL_2012' SQL_2014 ||= 'SQL_2014' +SQL_2016 ||= 'SQL_2016' + +ALL_SQL_VERSIONS = [SQL_2012, SQL_2014, SQL_2016] module PuppetX module Sqlserver @@ -7,9 +10,22 @@ module Sqlserver class Features private - SQL_WMI_PATH ||= { - SQL_2012 => 'ComputerManagement11', - SQL_2014 => 'ComputerManagement12', + SQL_CONFIGURATION ||= { + SQL_2012 => { + :major_version => 11, + :wmi_path => 'ComputerManagement11', + :registry_path => '110', + }, + SQL_2014 => { + :major_version => 12, + :wmi_path => 'ComputerManagement12', + :registry_path => '120', + }, + SQL_2016 => { + :major_version => 13, + :wmi_path => 'ComputerManagement13', + :registry_path => '130', + } } SQL_REG_ROOT ||= 'Software\Microsoft\Microsoft SQL Server' @@ -20,11 +36,12 @@ class Features def self.connect(version) require 'win32ole' - ver = SQL_WMI_PATH[version] + ver = SQL_CONFIGURATION[version][:wmi_path] context = WIN32OLE.new('WbemScripting.SWbemNamedValueSet') context.Add("__ProviderArchitecture", 64) locator = WIN32OLE.new('WbemScripting.SWbemLocator') - locator.ConnectServer('', "root/Microsoft/SqlServer/#{ver}", '', '', nil, nil, nil, context) + # WMI Path must use backslashes. Ruby 2.3 can cause crashes with forward slashes + locator.ConnectServer(nil, "root\\Microsoft\\SqlServer\\#{ver}", nil, nil, nil, nil, nil, context) end def self.get_parent_path(key_path) @@ -118,9 +135,11 @@ def self.get_instance_features(reg_root, instance_name) # also reg Replication/IsInstalled set to 1 'SQL_Replication_Core_Inst' => 'Replication', # SQL Server Replication # also WMI: SqlService WHERE SQLServiceType = 1 # MSSQLSERVER - 'SQL_Engine_Core_Inst' => 'SQLEngine', # Database Engine Services - 'SQL_FullText_Adv' => 'FullText', # Full-Text and Semantic Extractions for Search - 'SQL_DQ_Full' => 'DQ', # Data Quality Services + 'SQL_Engine_Core_Inst' => 'SQLEngine', # Database Engine Services + 'SQL_FullText_Adv' => 'FullText', # Full-Text and Semantic Extractions for Search + 'SQL_DQ_Full' => 'DQ', # Data Quality Services + 'sql_inst_mr' => 'ADVANCEDANALYTICS', # R Services (In-Database) + 'SQL_Polybase_Core_Inst' => 'POLYBASE', # PolyBase Query Service for External Data } feat_root = "#{reg_root}\\ConfigurationState" @@ -144,18 +163,25 @@ def self.get_instance_features(reg_root, instance_name) def self.get_shared_features(version) shared_features = { - 'Connectivity_Full' => 'Conn', # Client Tools Connectivity - 'SDK_Full' => 'SDK', # Client Tools SDK - 'MDSCoreFeature' => 'MDS', # Master Data Services - 'Tools_Legacy_Full' => 'BC', # Client Tools Backwards Compatibility - 'SQL_SSMS_Full' => 'ADV_SSMS', # Management Tools - Complete - 'SQL_SSMS_Adv' => 'SSMS', # Management Tools - Basic + 'Connectivity_Full' => 'Conn', # Client Tools Connectivity + 'SDK_Full' => 'SDK', # Client Tools SDK + 'MDSCoreFeature' => 'MDS', # Master Data Services + 'Tools_Legacy_Full' => 'BC', # Client Tools Backwards Compatibility + 'SQL_SSMS_Full' => 'ADV_SSMS', # Management Tools - Complete (Does not exist in SQL 2016) + 'SQL_SSMS_Adv' => 'SSMS', # Management Tools - Basic (Does not exist in SQL 2016) + 'SQL_DQ_CLIENT_Full' => 'DQC', # Data Quality Client + 'SQL_BOL_Components' => 'BOL', # Documentation Components + 'SQL_DReplay_Controller' => 'DREPLAY_CTLR', # Distributed Replay Controller + 'SQL_DReplay_Client' => 'DREPLAY_CLT', # Distributed Replay Client + 'sql_shared_mr' => 'SQL_SHARED_MR', # R Server (Standalone) + # also WMI: SqlService WHERE SQLServiceType = 4 # MsDtsServer - 'SQL_DTS_Full' => 'IS', # Integration Services + 'SQL_DTS_Full' => 'IS', # Integration Services # currently ignoring Reporting Services Shared + # currently ignoring R Server Standalone } - reg_ver = (version == SQL_2014 ? '120' : '110') + reg_ver = SQL_CONFIGURATION[version][:registry_path] reg_root = "#{SQL_REG_ROOT}\\#{reg_ver}\\ConfigurationState" get_sql_reg_val_features(reg_root, shared_features) @@ -185,11 +211,27 @@ def self.get_shared_features(version) # } # } def self.get_instances - version_instance_map = [SQL_2012, SQL_2014] + version_instance_map = ALL_SQL_VERSIONS .map do |version| + major_version = SQL_CONFIGURATION[version][:major_version] + instances = get_instance_names_by_ver(version) .map { |name| [ name, get_instance_info(version, name) ] } + # Instance names are unique on a single host, but not for a particular SQL Server version therefore + # it's possible to request information for a valid instance_name but not for version. In this case + # we just reject any instances that have no information + instances.reject! { |value| value[1].nil? } + + # Unfortunately later SQL versions can return previous version SQL instances. We can weed these out + # by inspecting the major version of the instance_version + instances.reject! do |value| + return true if value[1]['version'].nil? + ver = Gem::Version.new(value[1]['version']) + # Segment 0 is the major version number of the SQL Instance + ver.segments[0] != major_version + end + [ version, Hash[instances] ] end @@ -203,10 +245,9 @@ def self.get_instances # "SQL_2014" => [] # } def self.get_features - { - SQL_2012 => get_shared_features(SQL_2012), - SQL_2014 => get_shared_features(SQL_2014), - } + features = {} + ALL_SQL_VERSIONS.each { |version| features[version] = get_shared_features(version) } + features end # returns a hash containing instance details @@ -225,8 +266,13 @@ def self.get_features # "RS" # ] # } - def self.get_instance_info(version = SQL_2014, instance_name) + def self.get_instance_info(version, instance_name) + return nil if version.nil? sql_instance = get_wmi_instance_info(version, instance_name) + # Instance names are unique on a single host, but not for a particular SQL Server version therefore + # it's possible to request information for a valid instance_name but not for version. In this case + # we just return nil. + return nil if sql_instance['reg_root'].nil? feats = get_instance_features(sql_instance['reg_root'], sql_instance['name']) sql_instance.merge({'features' => feats}) end From 1e3398356af06b16d6cf114d895234be70dc8503 Mon Sep 17 00:00:00 2001 From: Glenn Sarti Date: Fri, 2 Jun 2017 15:53:06 -0700 Subject: [PATCH 2/5] (maint) Delete commented out code This commit deletes code which has been commented out for some time and serves no purpose. --- lib/puppet/provider/sqlserver_instance/mssql.rb | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/puppet/provider/sqlserver_instance/mssql.rb b/lib/puppet/provider/sqlserver_instance/mssql.rb index 34b1c5bb..e32a3695 100644 --- a/lib/puppet/provider/sqlserver_instance/mssql.rb +++ b/lib/puppet/provider/sqlserver_instance/mssql.rb @@ -72,17 +72,6 @@ def create else installNet35(@resource[:windows_feature_source]) add_features(@resource[:features]) - # cmd_args = build_cmd_args(@resource[:features]) - # begin - # config_file = create_temp_for_install_switch - # cmd_args << "/ConfigurationFile=\"#{config_file.path}\"" unless config_file.nil? - # try_execute(cmd_args) - # ensure - # if config_file - # config_file.close - # config_file.unlink - # end - # end end end From 987261619ef010cfc0016a53041992f807d4ea68 Mon Sep 17 00:00:00 2001 From: Glenn Sarti Date: Fri, 2 Jun 2017 17:22:30 -0700 Subject: [PATCH 3/5] (MODULES-4257) Modify instance and features for SQL Server 2016 Previously the sqlserver_instance and sqlserver_feature acceptance tests were failing. This was mainly due to SQL Server 2016 not having a feature for the SQL Management Studio (ADV_SSMS and SSMS). However it was later found that the super features called Tools and SQL were not providing an adequate abstraction e.g. they were not rolled up in the Facter facts. This commit adds support for SQL Server 2016 by the following: - Deprecating the use of 'Tools' in the sqlserver_features and 'SQL' in the sqlserver_instance custom types. These super features will continue to function however use of them will generate a deprecation warning - The acceptance tests for the super features was removed - Most tests which referred to ADV_SSMS and SSMS were removed. Where not possible, they were guarded to not be tested on SQL Server 2016. - An installation media version detection method was added as Dot Net 3.5 is not required for SQL Server 2016 installation. This is only applicable for SQL Server 2012 and 2014. - Refactored the instances method for sqlserver_features to support multiple server editions on a server but until MODULES-5060 is resolved, only the first set is returned. --- .../provider/sqlserver_features/mssql.rb | 32 ++++-- .../provider/sqlserver_instance/mssql.rb | 12 ++- lib/puppet/type/sqlserver_features.rb | 6 +- lib/puppet/type/sqlserver_instance.rb | 6 +- lib/puppet_x/sqlserver/server_helper.rb | 27 +++++ spec/acceptance/sqlserver_instance_spec.rb | 21 +--- .../z_last_sqlserver_features_spec.rb | 102 ++++++------------ .../provider/sqlserver_features_spec.rb | 31 +++--- .../puppet/type/sqlserver_features_spec.rb | 20 ++++ .../puppet/type/sqlserver_instance_spec.rb | 14 +++ 10 files changed, 140 insertions(+), 131 deletions(-) create mode 100644 spec/unit/puppet/type/sqlserver_features_spec.rb diff --git a/lib/puppet/provider/sqlserver_features/mssql.rb b/lib/puppet/provider/sqlserver_features/mssql.rb index e5c7ad79..41114dbe 100644 --- a/lib/puppet/provider/sqlserver_features/mssql.rb +++ b/lib/puppet/provider/sqlserver_features/mssql.rb @@ -1,5 +1,7 @@ require 'json' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver')) +require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/server_helper')) +require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/features')) FEATURE_RESERVED_SWITCHES = %w(AGTSVCACCOUNT AGTSVCPASSWORD ASSVCACCOUNT AGTSVCPASSWORD PID @@ -10,18 +12,25 @@ def self.instances instances = [] result = Facter.value(:sqlserver_features) debug "Parsing result #{result}" - result = !result[SQL_2014].empty? ? result[SQL_2014] : result[SQL_2012] - if !result.empty? - existing_instance = {:name => "Generic Features", - :ensure => :present, - :features => result.sort + + ALL_SQL_VERSIONS.each do |sql_version| + next if result[sql_version].empty? + instance_props = {:name => "Generic Features", + :ensure => :present, + :features => result[sql_version].sort } - debug "Parsed features = #{existing_instance[:features]}" + debug "Parsed features = #{instance_props[:features]}" - instance = new(existing_instance) + instance = new(instance_props) debug "Created instance #{instance}" instances << instance + + # Due to MODULES-5060 we can only output one feature set. If we output + # multiple then it is not possible to install or uninstall due to multiple + # resources with the same name. + break end + instances end @@ -82,8 +91,7 @@ def create_temp_for_install_switch config_file = ["[OPTIONS]"] @resource[:install_switches].each_pair do |k, v| if FEATURE_RESERVED_SWITCHES.include? k - warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value -may be overridden by some command line arguments") + warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value may be overridden by some command line arguments") end if v.is_a?(Numeric) || (v.is_a?(String) && v =~ /^(true|false|1|0)$/i) config_file << "#{k}=#{v}" @@ -111,7 +119,11 @@ def create warn "Uninstalling all sql server features not tied into an instance because an empty array was passed, please use ensure absent instead." destroy else - installNet35(@resource[:windows_feature_source]) + 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? + + installNet35(@resource[:windows_feature_source]) unless instance_version == SQL_2016 + debug "Installing features #{@resource[:features]}" add_features(@resource[:features]) @property_hash[:features] = @resource[:features] diff --git a/lib/puppet/provider/sqlserver_instance/mssql.rb b/lib/puppet/provider/sqlserver_instance/mssql.rb index e32a3695..78afe74b 100644 --- a/lib/puppet/provider/sqlserver_instance/mssql.rb +++ b/lib/puppet/provider/sqlserver_instance/mssql.rb @@ -1,6 +1,7 @@ require 'json' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver')) - +require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/server_helper')) +require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/features')) INSTANCE_RESERVED_SWITCHES = %w(AGTSVCACCOUNT AGTSVCPASSWORD ASSVCACCOUNT AGTSVCPASSWORD PID @@ -70,7 +71,11 @@ def create warn "Uninstalling all features for instance #{@resource[:name]} because an empty array was passed, please use ensure absent instead." destroy else - installNet35(@resource[:windows_feature_source]) + 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? + + installNet35(@resource[:windows_feature_source]) unless instance_version == SQL_2016 + add_features(@resource[:features]) end end @@ -80,8 +85,7 @@ def create_temp_for_install_switch config_file = ["[OPTIONS]"] @resource[:install_switches].each_pair do |k, v| if INSTANCE_RESERVED_SWITCHES.include? k - warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value -may be overridden by some command line arguments") + warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value may be overridden by some command line arguments") end if v.is_a?(Numeric) || (v.is_a?(String) && v =~ /^(true|false|1|0)$/i) config_file << "#{k}=#{v}" diff --git a/lib/puppet/type/sqlserver_features.rb b/lib/puppet/type/sqlserver_features.rb index 0e325ae0..166b295e 100644 --- a/lib/puppet/type/sqlserver_features.rb +++ b/lib/puppet/type/sqlserver_features.rb @@ -36,11 +36,11 @@ newproperty(:features, :array_matching => :all) do desc 'Specifies features to install, uninstall, or upgrade. The list of top-level features include - Tools, BC, Conn, SSMS, ADV_SSMS, SDK, IS and MDS. The Tools feature will install Management - Tools, Books online components, SQL Server Data Tools, and other shared components.' - newvalues(:Tools, :BC, :Conn, :SSMS, :ADV_SSMS, :SDK, :IS, :MDS) + BC, Conn, SSMS, ADV_SSMS, SDK, IS and MDS.' + newvalues(:Tools, :BC, :Conn, :SSMS, :ADV_SSMS, :SDK, :IS, :MDS, :BOL, :DREPLAY_CTLR, :DREPLAY_CLT) munge do |value| if PuppetX::Sqlserver::ServerHelper.is_super_feature(value) + Puppet.deprecation_warning("Using #{value} is deprecated for features in sql_features resources") PuppetX::Sqlserver::ServerHelper.get_sub_features(value).collect { |v| v.to_s } else value diff --git a/lib/puppet/type/sqlserver_instance.rb b/lib/puppet/type/sqlserver_instance.rb index 179ff6c8..026316f2 100644 --- a/lib/puppet/type/sqlserver_instance.rb +++ b/lib/puppet/type/sqlserver_instance.rb @@ -27,11 +27,11 @@ newproperty(:features, :array_matching => :all) do desc 'Specifies features to install, uninstall, or upgrade. The list of top-level features include - SQL, SQLEngine, Replication, FullText, DQ AS, and RS. The SQL feature will install the Database Engine, - Replication, Full-Text, and Data Quality Services (DQS) server.' - newvalues(:SQL, :SQLEngine, :Replication, :FullText, :DQ, :AS, :RS) + SQLEngine, Replication, FullText, DQ AS, and RS.' + newvalues(:SQL, :SQLEngine, :Replication, :FullText, :DQ, :AS, :RS, :POLYBASE, :ADVANCEDANALYTICS) munge do |value| if PuppetX::Sqlserver::ServerHelper.is_super_feature(value) + Puppet.deprecation_warning("Using #{value} is deprecated for features in sql_instance resources") PuppetX::Sqlserver::ServerHelper.get_sub_features(value).collect { |v| v.to_s } else value diff --git a/lib/puppet_x/sqlserver/server_helper.rb b/lib/puppet_x/sqlserver/server_helper.rb index 38eca0b4..2313c256 100644 --- a/lib/puppet_x/sqlserver/server_helper.rb +++ b/lib/puppet_x/sqlserver/server_helper.rb @@ -21,6 +21,33 @@ def self.is_domain_or_local_user?(user, hostname) true end end + + # Returns either SQL_2016, SQL_2014 or SQL_2012 if it can determine the SQL Version from the install source + # Returns nil if it can not be determined + def self.sql_version_from_install_source(source_dir) + # Attempt to read the Mediainfo.xml file in the root of the install media + media_file = File.expand_path("#{source_dir}/MediaInfo.xml") + return nil unless File.exist?(media_file) + # As we don't have a XML parser easily, just use simple text matching to find the following XML element. This + # also means we can just ignore BOM markers etc. + # + content = File.read(media_file) + index1 = content.index('"BaselineVersion"') + return nil if index1.nil? + index2 = content.index('/>',index1) + return nil if index2.nil? + content = content.slice(index1 + 18, index2 - index1 - 18) + # Extract the version number from the text snippet + # Value="xx.yyy.zz." + ver = content.match('"(.+)"') + return nil if ver.nil? + + return SQL_2016 if ver[1].start_with?('13.') + return SQL_2014 if ver[1].start_with?('12.') + return SQL_2012 if ver[1].start_with?('11.') + + nil + end end end end diff --git a/spec/acceptance/sqlserver_instance_spec.rb b/spec/acceptance/sqlserver_instance_spec.rb index db3ec01b..31a6928f 100644 --- a/spec/acceptance/sqlserver_instance_spec.rb +++ b/spec/acceptance/sqlserver_instance_spec.rb @@ -81,7 +81,7 @@ def sql_query_is_user_sysadmin(username) end inst_name = new_random_instance_name - features = ['SQL', 'SQLEngine', 'Replication', 'FullText', 'DQ'] + features = ['SQLEngine', 'Replication', 'FullText', 'DQ'] it "create #{inst_name} instance" do ensure_sqlserver_instance(host, features, inst_name,'present',"['Administrator','ExtraSQLAdmin']") @@ -114,25 +114,6 @@ def sql_query_is_user_sysadmin(username) end end - context "Feature has only one 'SQL'", {:testrail => ['89032']} do - inst_name = new_random_instance_name - features = ['SQL'] - - after(:all) do - ensure_sqlserver_instance(host, features, inst_name, 'absent') - end - - it "create #{inst_name} instance with only one SQL feature" do - ensure_sqlserver_instance(host, features, inst_name) - - validate_sql_install(host, {:version => version}) do |r| - expect(r.stdout).to match(/#{inst_name}\s+Database Engine Services/) - expect(r.stdout).to match(/#{inst_name}\s+SQL Server Replication/) - expect(r.stdout).to match(/#{inst_name}\s+Data Quality Services/) - end - end - end - context "Feature has only one 'RS'", {:testrail => ['89034']} do inst_name = new_random_instance_name features = ['RS'] diff --git a/spec/acceptance/z_last_sqlserver_features_spec.rb b/spec/acceptance/z_last_sqlserver_features_spec.rb index 3f5cb8b1..589b1e07 100644 --- a/spec/acceptance/z_last_sqlserver_features_spec.rb +++ b/spec/acceptance/z_last_sqlserver_features_spec.rb @@ -4,7 +4,7 @@ host = find_only_one("sql_host") describe "sqlserver_features", :node => host do - version = host['sql_version'].to_s + sql_version = host['sql_version'].to_s def ensure_sql_features(host, features, ensure_val = 'present') manifest = <<-MANIFEST @@ -33,23 +33,20 @@ def ensure_sql_features(host, features, ensure_val = 'present') end context 'can install' do - - features = ['Tools', 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] + features = ['BC', 'Conn', 'SDK', 'IS', 'MDS'] before(:all) do - remove_sql_features(host, {:features => features, :version => version}) + remove_sql_features(host, {:features => features, :version => sql_version}) end after(:all) do - remove_sql_features(host, {:features => features, :version => version}) + remove_sql_features(host, {:features => features, :version => sql_version}) end it 'all possible features' do ensure_sql_features(host, features) - validate_sql_install(host, {:version => version}) do |r| - expect(r.stdout).to match(/Management Tools - Basic/) - expect(r.stdout).to match(/Management Tools - Complete/) + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).to match(/Client Tools Connectivity/) expect(r.stdout).to match(/Client Tools Backwards Compatibility/) expect(r.stdout).to match(/Client Tools SDK/) @@ -61,7 +58,7 @@ def ensure_sql_features(host, features, ensure_val = 'present') context 'can remove' do - features = ['Tools', 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] + features = ['BC', 'Conn', 'SDK', 'IS', 'MDS'] before(:all) do ensure_sql_features(host, features) @@ -69,15 +66,13 @@ def ensure_sql_features(host, features, ensure_val = 'present') after(:all) do # redundant but necessary in case our manifest fails - remove_sql_features(host, {:features => features, :version => version}) + remove_sql_features(host, {:features => features, :version => sql_version}) end it 'all possible features' do ensure_sql_features(host, features, 'absent') - validate_sql_install(host, {:version => version}) do |r| - expect(r.stdout).not_to match(/Management Tools - Basic/) - expect(r.stdout).not_to match(/Management Tools - Complete/) + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Client Tools Connectivity/) expect(r.stdout).not_to match(/Client Tools Backwards Compatibility/) expect(r.stdout).not_to match(/Client Tools SDK/) @@ -87,54 +82,18 @@ def ensure_sql_features(host, features, ensure_val = 'present') end end - context 'can remove aggregate feature' do - - all_possible_features = ['Tools', 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] - aggregate_features = ['Tools', 'ADV_SSMS'] - - before(:all) do - remove_sql_features(host, {:features => all_possible_features, :version => version}) - end - - before(:each) do - ensure_sql_features(host, aggregate_features) - end - - after(:all) do - # only aggregate should be installed, but wipe all in case manifest misbehaves - remove_sql_features(host, {:features => all_possible_features, :version => version}) - end - - it "'Tools', which includes the 'Conn', 'SDK', 'BC', 'SSMS' and 'ADV_SSMS' features" do - ensure_sql_features(host, ['Tools'], 'absent') - - validate_sql_install(host, {:version => version}) do |r| - expect(r.stdout).not_to match(/Client Tools Connectivity/) - expect(r.stdout).not_to match(/Client Tools SDK/) - expect(r.stdout).not_to match(/Client Tools Backwards Compatibility/) - expect(r.stdout).not_to match(/Management Tools - Basic/) - expect(r.stdout).not_to match(/Management Tools - Complete/) - end - end - - it "'SSMS', which removes the dependent 'ADV_SSMS' feature" do - ensure_sql_features(host, ['SSMS'], 'absent') - - validate_sql_install(host, {:version => version}) do |r| - expect(r.stdout).to_not match(/Management Tools - Basic/) - expect(r.stdout).to_not match(/Management Tools - Complete/) - end - end - - end context 'can remove independent feature' do - - all_possible_features = ['Tools', 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] - features = ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] + if sql_version == '2016' + all_possible_features = ['BC', 'Conn', 'SDK', 'IS', 'MDS'] + features = ['BC', 'Conn', 'SDK', 'IS', 'MDS'] + else + all_possible_features = ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] + features = ['BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] + end before(:all) do - remove_sql_features(host, {:features => all_possible_features, :version => version}) + remove_sql_features(host, {:features => all_possible_features, :version => sql_version}) end before(:each) do @@ -143,13 +102,13 @@ def ensure_sql_features(host, features, ensure_val = 'present') 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 => version}) + remove_sql_features(host, {:features => all_possible_features, :version => sql_version}) end it "'BC'" do ensure_sql_features(host, features - ['BC']) - validate_sql_install(host, {:version => version}) do |r| + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Client Tools Backwards Compatibility/) end end @@ -157,15 +116,16 @@ def ensure_sql_features(host, features, ensure_val = 'present') it "'Conn'" do ensure_sql_features(host, features - ['Conn']) - validate_sql_install(host, {:version => version}) do |r| + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Client Tools Connectivity/) end end - it "'ADV_SSMS'" do + # TODO: Guard on SQL 2016 + it "'ADV_SSMS'", :unless => sql_version == '2016' do ensure_sql_features(host, features - ['ADV_SSMS']) - validate_sql_install(host, {:version => version}) do |r| + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Management Tools - Complete/) # also verify SSMS is still present @@ -176,7 +136,7 @@ def ensure_sql_features(host, features, ensure_val = 'present') it "'SDK'" do ensure_sql_features(host, features - ['SDK']) - validate_sql_install(host, {:version => version}) do |r| + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Client Tools SDK/) end end @@ -184,7 +144,7 @@ def ensure_sql_features(host, features, ensure_val = 'present') it "'IS'" do ensure_sql_features(host, features - ['IS']) - validate_sql_install(host, {:version => version}) do |r| + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Integration Services/) end end @@ -192,7 +152,7 @@ def ensure_sql_features(host, features, ensure_val = 'present') it "'MDS'" do ensure_sql_features(host, features - ['MDS']) - validate_sql_install(host, {:version => version}) do |r| + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).not_to match(/Master Data Services/) end end @@ -225,7 +185,7 @@ def bind_and_apply_failing_manifest(host, features, ensure_val = 'present') end it 'fails when an is_svc_account is supplied and a password is not' do - features = ['Tools', 'IS'] + features = ['IS'] bind_and_apply_failing_manifest(host, features) end @@ -240,7 +200,7 @@ def bind_and_apply_failing_manifest(host, features, ensure_val = 'present') context 'can install' do - features = ['Tools', 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'] + features = ['BC', 'Conn', 'SDK', 'IS', 'MDS'] before(:all) do puppet_version = (on host, puppet('--version')).stdout.chomp @@ -255,19 +215,17 @@ def bind_and_apply_failing_manifest(host, features, ensure_val = 'present') names = eval(fact_on(host, 'sqlserver_instances', facter_opts)).values.inject(:merge).keys end - remove_sql_instances(host, {:version => version, :instance_names => names}) + remove_sql_instances(host, {:version => sql_version, :instance_names => names}) end after(:all) do - remove_sql_features(host, {:features => features, :version => version}) + remove_sql_features(host, {:features => features, :version => sql_version}) end it 'all possible features' do ensure_sql_features(host, features) - validate_sql_install(host, {:version => version}) do |r| - expect(r.stdout).to match(/Management Tools - Basic/) - expect(r.stdout).to match(/Management Tools - Complete/) + validate_sql_install(host, {:version => sql_version}) do |r| expect(r.stdout).to match(/Client Tools Connectivity/) expect(r.stdout).to match(/Client Tools Backwards Compatibility/) expect(r.stdout).to match(/Client Tools SDK/) diff --git a/spec/unit/puppet/provider/sqlserver_features_spec.rb b/spec/unit/puppet/provider/sqlserver_features_spec.rb index 2d33646a..f5d7c9c6 100644 --- a/spec/unit/puppet/provider/sqlserver_features_spec.rb +++ b/spec/unit/puppet/provider/sqlserver_features_spec.rb @@ -59,12 +59,12 @@ end end - context 'it should expand the superset for features' do - include_context 'features' - let(:additional_params) { {:features => %w(Tools)} } - let(:munged_args) { {:features => %w(ADV_SSMS BC Conn SDK SSMS)} } - it_should_behave_like 'create' - end + # context 'it should expand the superset for features' do + # include_context 'features' + # let(:additional_params) { {:features => %w(Tools)} } + # let(:munged_args) { {:features => %w(ADV_SSMS BC Conn SDK SSMS)} } + # it_should_behave_like 'create' + # end shared_examples 'features=' do |args, exit_code, warning_matcher| it { @@ -124,20 +124,13 @@ it_should_behave_like 'features=', @feature_params, 3010, /reboot required/i end - context 'it should install the expanded tools set' do - include_context 'features' - @feature_params[:features] = %w(Tools) - let(:feature_add) { %w(ADV_SSMS BC Conn SDK SSMS) } - it_should_behave_like 'features=', @feature_params - end + # context 'it should install the expanded tools set' do + # include_context 'features' + # @feature_params[:features] = %w(Tools) + # let(:feature_add) { %w(ADV_SSMS BC Conn SDK SSMS) } + # it_should_behave_like 'features=', @feature_params + # end - context 'it should' do - include_context 'features' - @feature_params[:features] = %w(Tools IS) - @feature_params[:is_svc_account] = 'nexus/domainuser' - # let(:feature_params) { @feature_params } - it_should_behave_like 'fail on', @feature_params - end describe 'it should call destroy on empty array' do it { feature_params = { diff --git a/spec/unit/puppet/type/sqlserver_features_spec.rb b/spec/unit/puppet/type/sqlserver_features_spec.rb new file mode 100644 index 00000000..fb0e0923 --- /dev/null +++ b/spec/unit/puppet/type/sqlserver_features_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver_install_context.rb')) + +RSpec.describe Puppet::Type.type(:sqlserver_features) do + let(:error_class) { Puppet::Error } + + describe "features" do + ['Tools'].each do |feature_name| + it "should raise deprecation warning with super feature #{feature_name}" do + args = { + :name => 'Generic Features', + :ensure => 'present', + :features => [feature_name], + } + Puppet.expects(:deprecation_warning).at_least_once + subject = Puppet::Type.type(:sqlserver_features).new(args) + end + end + end +end diff --git a/spec/unit/puppet/type/sqlserver_instance_spec.rb b/spec/unit/puppet/type/sqlserver_instance_spec.rb index dd8638a6..fb93d3dd 100644 --- a/spec/unit/puppet/type/sqlserver_instance_spec.rb +++ b/spec/unit/puppet/type/sqlserver_instance_spec.rb @@ -31,6 +31,20 @@ end end + describe "features" do + ['SQL'].each do |feature_name| + it "should raise deprecation warning with super feature #{feature_name}" do + args = { + :name => 'MSSQLSERVER', + :ensure => 'present', + :features => [feature_name], + } + Puppet.expects(:deprecation_warning).at_least_once + subject = Puppet::Type.type(:sqlserver_instance).new(args) + end + end + end + describe "agt_svc_password required when using domain account" do it_should_behave_like 'fail validation' do args = get_basic_args From 165fa9caaa1102f72d8c612128d30c1f6ad3b8b5 Mon Sep 17 00:00:00 2001 From: Glenn Sarti Date: Thu, 8 Jun 2017 15:40:58 -0700 Subject: [PATCH 4/5] (maint) Fix typo in test file name This commit removes the double underscore type error in the file names for the puppet provider tests. --- .../{sqlserver__instance_spec.rb => sqlserver_instance_spec.rb} | 0 .../provider/{sqlserver__tsql_spec.rb => sqlserver_tsql_spec.rb} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename spec/unit/puppet/provider/{sqlserver__instance_spec.rb => sqlserver_instance_spec.rb} (100%) rename spec/unit/puppet/provider/{sqlserver__tsql_spec.rb => sqlserver_tsql_spec.rb} (100%) diff --git a/spec/unit/puppet/provider/sqlserver__instance_spec.rb b/spec/unit/puppet/provider/sqlserver_instance_spec.rb similarity index 100% rename from spec/unit/puppet/provider/sqlserver__instance_spec.rb rename to spec/unit/puppet/provider/sqlserver_instance_spec.rb diff --git a/spec/unit/puppet/provider/sqlserver__tsql_spec.rb b/spec/unit/puppet/provider/sqlserver_tsql_spec.rb similarity index 100% rename from spec/unit/puppet/provider/sqlserver__tsql_spec.rb rename to spec/unit/puppet/provider/sqlserver_tsql_spec.rb From dc14cb47e182f8020a78f60252724b89d5bad9db Mon Sep 17 00:00:00 2001 From: Glenn Sarti Date: Thu, 8 Jun 2017 16:13:58 -0700 Subject: [PATCH 5/5] (MODULES-4257) Update README with SQL Server 2016 features This commit updates the README with new features available for SQL Server 2016, and adds notes about the deprecation of the super features. --- README.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 35a54b36..ebabe8ad 100644 --- a/README.md +++ b/README.md @@ -80,13 +80,6 @@ This example creates the same MS SQL instance as shown above with additional opt ### Install SQL Server tools and features not specific to a SQL Server instance -```puppet -sqlserver_features { 'Generic Features': - source => 'E:/', - features => ['Tools'], -} -``` - ```puppet sqlserver_features { 'Generic Features': source => 'E:/', @@ -203,8 +196,10 @@ Default: 'present'. ##### `features` *Required.* - -Specifies one or more features to manage. Valid options: 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', and 'Tools' (the Tools feature includes SSMS, ADV_SSMS, and Conn). + +Specifies one or more features to manage. Valid options: 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS', 'BOL', 'DREPLAY_CTLR', 'DREPLAY_CLT'. + +The 'Tools' feature is deprecated. Instead specify 'BC', 'SSMS', 'ADV_SSMS', 'Conn', and 'SDK' explicitly. ##### `install_switches` @@ -294,7 +289,9 @@ Default: 'present'. ##### `features` -*Required.* Specifies one or more features to manage. The list of top-level features includes 'SQL', 'AS', and 'RS'. The 'SQL' feature includes the Database Engine, Replication, Full-Text, and Data Quality Services (DQS) server. Valid options: an array containing one or more of the strings 'SQL', 'SQLEngine', 'Replication', 'FullText', 'DQ', 'AS', and 'RS'. +*Required.* Specifies one or more features to manage. The list of top-level features includes 'AS' and 'RS'. Valid options: an array containing one or more of the strings 'SQL', 'SQLEngine', 'Replication', 'FullText', 'DQ', 'AS', 'RS', 'POLYBASE', and 'ADVANCEDANALYTICS'. + +The 'SQL' feature is deprecated. Instead specify 'DQ', 'FullText', 'Replication', and 'SQLEngine' explicitly. ##### `install_switches`