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` 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 34b1c5bb..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,19 +71,12 @@ 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]) - # 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 @@ -91,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/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 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/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 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