diff --git a/CHANGELOG.md b/CHANGELOG.md index dad8a762..6f3776fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,10 @@ +##2015-03-10 - 1.1.0 +###Summary + +Add ability to provide unmaged install switches + +####Features +- `sqlserver_instance` and `sqlserver_features` have new parameter `install_switches` which takes a hash of install switches and writes them to a temp configuration file for the the install process + ##2014-12-08 - 1.0.0 Initial release diff --git a/README.md b/README.md index ce55c4dd..6da716d3 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ ##Overview -The sqlserver module installs and manages Microsoft SQL Server 2012 and 2014 on Windows systems. +The sqlserver module installs and manages Microsoft SQL Server 2012 and 2014 on Windows systems. ##Module Description - -The sqlserver module adds defined types to install and manage Microsoft SQL Server 2012 and 2014 on Windows Server 2012. The module can install SQL Server clients, multiple instances, and SQL features, as well as create and manage new databases and logins. + +The sqlserver module adds defined types to install and manage Microsoft SQL Server 2012 and 2014 on Windows Server 2012. The module can install SQL Server clients, multiple instances, and SQL features, as well as create and manage new databases and logins. ##Setup @@ -27,7 +27,7 @@ The sqlserver module adds defined types to install and manage Microsoft SQL Serv This module requires .NET 3.5 and installs it if it's not already on your system. This might require an internet connection. -###Setup Requirements +###Setup Requirements The sqlserver module requires the following: @@ -36,10 +36,10 @@ The sqlserver module requires the following: * .NET 3.5 * ISO, mounted or expanded either locally or on a network share * Windows Server 2012 or 2012R2 - + ###Beginning with sqlserver -To get started with the sqlserver module, include these settings in your manifest: +To get started with the sqlserver module, include these settings in your manifest: ``` sqlserver_instance{'MSSQLSERVER': @@ -79,7 +79,7 @@ sqlserver::database{ 'minviable': } ``` -###To set up a new login: +###To set up a new login: ``` SQL Login @@ -88,7 +88,7 @@ sqlserver::login{'vagrant': password => 'Pupp3t1@', } -Windows Login +Windows Login sqlserver::login{'WIN-D95P1A3V103\localAccount': instance => 'MSSQLSERVER', login_type => 'WINDOWS_LOGIN', @@ -114,10 +114,15 @@ Terminology differs somewhat between various database systems; please refer to t * `ensure`: Ensures that the resource is present. Valid values are 'present', 'absent'. * `features`: Specifies features to install or uninstall. The list of top-level features include IS, MDS, and Tools. The Tools feature will install Management Tools, SQL Server Data Tools, and other shared components. Valid values are 'Tools', 'BC', 'Conn', 'SSMS', 'ADV_SSMS', 'SDK', 'IS', 'MDS'. * `is_svc_account`: Either domain user name or system account. Defaults to 'NT AUTHORITY\NETWORK SERVICE'. -* `is_svc_password`: Password for domain user. +* `is_svc_password`: Password for domain user. * `pid`: Specify the SQL Server product key to configure which edition you would like to use. Can be left empty for evaluation versions. -* `provider`: The specific backend to use for this `sqlserver_features` resource. You seldom need to specify this---Puppet will usually discover the appropriate provider for your platform. Available providers are: `mssql`, `source`. - +* `install_switches`: Hash of install switches you would like to be based to a config file during installation. + +** Please not that any duplicates from what we provide on the command line will be ignored. For more information see the links below + +* [Installer switches](https://msdn.microsoft.com/en-us/library/ms144259.aspx) +* [Configuration File](https://msdn.microsoft.com/en-us/library/dd239405.aspx) + #### sqlserver_instance * `agt_svc_account`: Either domain user name or system account. @@ -138,15 +143,21 @@ Terminology differs somewhat between various database systems; please refer to t * `sql_svc_account`: Account for SQL Server service: Domain\User or system account. * `sql_svc_password`: The SQL Server service password; required only for a domain account. * `sql_sysadmin_accounts`: The Windows or SQL account(s) to provision as SQL Server system administrators. +* `install_switches`: Hash of install switches you would like to be based to a config file during installation. + +** Please not that any duplicates from what we provide on the command line will be ignored. For more information see the links below + +* [Installer switches](https://msdn.microsoft.com/en-us/library/ms144259.aspx) +* [Configuration File](https://msdn.microsoft.com/en-us/library/dd239405.aspx) ### Defined Types #### `sqlserver::config` -Stores the config file that allows Puppet to access and modify the instance. +Stores the config file that allows Puppet to access and modify the instance. * `instance_name`: The instance name you want to manage. Defaults to the name of the define. -* `admin_user`: The SQL login with sysadmin rights on the server, can only be login of SQL_Login type. +* `admin_user`: The SQL login with sysadmin rights on the server, can only be login of SQL_Login type. * `admin_pass`: The password to access the server to be managed. ``` @@ -154,7 +165,7 @@ Stores the config file that allows Puppet to access and modify the instance. admin_user => 'sa', admin_pass => 'PuppetP@ssword1', } - ``` + ``` #### `sqlserver::database` @@ -165,23 +176,23 @@ Creates, destroys, or updates databases, but does not move or modify files. Requ * `ensure`: Ensures that the resource is present. Valid values are 'present', 'absent'. Defaults to 'present'. * `compatibility`: Numeric representation of the SQL Server version with which the database should be compatible. For example, 100 = SQL Server 2008 through SQL Server 2012. For a complete list of values, refer to [http://msdn.microsoft.com/en-us/library/bb510680.aspx](http://msdn.microsoft.com/en-us/library/bb510680.aspx). * `collation_name`: Modifies dictionary default sort rules for the datatbase. Defaults to 'Latin1_General'. To find out what other values your system supports, run the query `SELECT * FROM sys.fn_helpcollations() WHERE name LIKE 'SQL%'`. -* `filestream_non_transacted_access`: Specifies the level of non-transactional FILESTREAM access to the database. This parameter is affected only at creation; updates will not change this setting. Valid values are 'OFF', 'READ_ONLY', 'FULL'. Requires defined type `sqlserver::sp_configure`. -* `filestream_directory_name`: Accepts a Windows-compatible directory name. This name should be unique among all the Database_Directory names in the SQL Server instance. Uniqueness comparison is case-insensitive, regardless of SQL Server collation settings. This option should be set before creating a FileTable in this database. This parameter is affected only at creation; updates will not change this setting. Requires defined type `sqlserver::sp_configure`. -* `filespec_name`: Specifies the logical name for the file. NAME is required when FILENAME is specified, except when specifying one of the FOR ATTACH clauses. A FILESTREAM filegroup cannot be named PRIMARY. This parameter is affected only at creation; updates will not change this setting. -* `filespec_filename`: Specifies the operating system (physical) file name. This parameter is affected only at creation; updates will not change this setting. -* `filespec_size`: Specifies the size of the file. The kilobyte (KB), megabyte (MB), gigabyte (GB), or terabyte (TB) suffixes can be used. The default is MB. Values can not be greater than 2147483647. This parameter is affected only at creation; updates will not change this setting. -* `filespec maxsize`: Specifies the maximum size to which the file can grow. MAXSIZE cannot be specified when the os_file_name is specified as a UNC path. This parameter is affected only at creation; updates will not change this setting. -* `filespec_filegrowth`: Specifies the automatic growth increment of the file. The FILEGROWTH setting for a file cannot exceed the MAXSIZE setting. FILEGROWTH cannot be specified when the os_file_name is specified as a UNC path. FILEGROWTH does not apply to a FILESTREAM filegroup. This parameter is affected only at creation; updates will not change this setting. -* `log_name`: Specifies the logical name for the file. NAME is required when FILENAME is specified, except when specifying one of the FOR ATTACH clauses. A FILESTREAM filegroup cannot be named PRIMARY. This parameter is affected only at creation; updates will not change this setting. -* `log_filename`: Specifies the operating system (physical) file name. This parameter is affected only at creation; updates will not change this setting. -* `log_size`: Specifies the size of the file. The kilobyte (KB), megabyte (MB), gigabyte (GB), or terabyte (TB) suffixes can be used. The default is MB. Values can not be greater than 2147483647. This parameter is affected only at creation; updates will not change this setting. -* `log_maxsize`: Specifies the maximum size to which the file can grow. MAXSIZE cannot be specified when the os_file_name is specified as a UNC path. This parameter is affected only at creation; updates will not change this setting. -* `log_filegrowth`: Specifies the automatic growth increment of the file. The FILEGROWTH setting for a file cannot exceed the MAXSIZE setting. FILEGROWTH cannot be specified when the os_file_name is specified as a UNC path. FILEGROWTH does not apply to a FILESTREAM filegroup. This parameter is affected only at creation; updates will not change this setting. +* `filestream_non_transacted_access`: Specifies the level of non-transactional FILESTREAM access to the database. This parameter is affected only at creation; updates will not change this setting. Valid values are 'OFF', 'READ_ONLY', 'FULL'. Requires defined type `sqlserver::sp_configure`. +* `filestream_directory_name`: Accepts a Windows-compatible directory name. This name should be unique among all the Database_Directory names in the SQL Server instance. Uniqueness comparison is case-insensitive, regardless of SQL Server collation settings. This option should be set before creating a FileTable in this database. This parameter is affected only at creation; updates will not change this setting. Requires defined type `sqlserver::sp_configure`. +* `filespec_name`: Specifies the logical name for the file. NAME is required when FILENAME is specified, except when specifying one of the FOR ATTACH clauses. A FILESTREAM filegroup cannot be named PRIMARY. This parameter is affected only at creation; updates will not change this setting. +* `filespec_filename`: Specifies the operating system (physical) file name. This parameter is affected only at creation; updates will not change this setting. +* `filespec_size`: Specifies the size of the file. The kilobyte (KB), megabyte (MB), gigabyte (GB), or terabyte (TB) suffixes can be used. The default is MB. Values can not be greater than 2147483647. This parameter is affected only at creation; updates will not change this setting. +* `filespec maxsize`: Specifies the maximum size to which the file can grow. MAXSIZE cannot be specified when the os_file_name is specified as a UNC path. This parameter is affected only at creation; updates will not change this setting. +* `filespec_filegrowth`: Specifies the automatic growth increment of the file. The FILEGROWTH setting for a file cannot exceed the MAXSIZE setting. FILEGROWTH cannot be specified when the os_file_name is specified as a UNC path. FILEGROWTH does not apply to a FILESTREAM filegroup. This parameter is affected only at creation; updates will not change this setting. +* `log_name`: Specifies the logical name for the file. NAME is required when FILENAME is specified, except when specifying one of the FOR ATTACH clauses. A FILESTREAM filegroup cannot be named PRIMARY. This parameter is affected only at creation; updates will not change this setting. +* `log_filename`: Specifies the operating system (physical) file name. This parameter is affected only at creation; updates will not change this setting. +* `log_size`: Specifies the size of the file. The kilobyte (KB), megabyte (MB), gigabyte (GB), or terabyte (TB) suffixes can be used. The default is MB. Values can not be greater than 2147483647. This parameter is affected only at creation; updates will not change this setting. +* `log_maxsize`: Specifies the maximum size to which the file can grow. MAXSIZE cannot be specified when the os_file_name is specified as a UNC path. This parameter is affected only at creation; updates will not change this setting. +* `log_filegrowth`: Specifies the automatic growth increment of the file. The FILEGROWTH setting for a file cannot exceed the MAXSIZE setting. FILEGROWTH cannot be specified when the os_file_name is specified as a UNC path. FILEGROWTH does not apply to a FILESTREAM filegroup. This parameter is affected only at creation; updates will not change this setting. * `containment`: Defaults to 'NONE'.Other possible values are 'PARTIAL'. Setting `containment` =>'PARTIAL' requires defined type `sqlserver::sp_configure`. See [http://msdn.microsoft.com/en-us/library/ff929071.aspx](http://msdn.microsoft.com/en-us/library/ff929071.aspx) for complete documentation about containment. * `default_fulltext_language`: Sets default fulltext language. Only applicable if `containment` => ‘PARTIAL’. Valid values are documented at [http://msdn.microsoft.com/en-us/library/ms190303.aspx](http://msdn.microsoft.com/en-us/library/ms190303.aspx). Defaults to 'us_english'. * `default_language`: Sets default language. Only applicable if `containment` => ‘PARTIAL’. Valid values are documented at http://msdn.microsoft.com/en-us/library/ms190303.aspx. Defaults to 'us_english'. * `nested_triggers`: Enables cascading triggers. Only applicable if `containment` => ‘PARTIAL’. Valid values are 'ON', 'OFF'. See [http://msdn.microsoft.com/en-us/library/ms178101.aspx](http://msdn.microsoft.com/en-us/library/ms178101.aspx) for complete documentation. -* `transform_noise_words`: Removes noise or stop words, such as “is”, “the”, “this”. Only applicable if `containment` => ‘PARTIAL’. Valid values are 'ON', 'OFF'. +* `transform_noise_words`: Removes noise or stop words, such as “is”, “the”, “this”. Only applicable if `containment` => ‘PARTIAL’. Valid values are 'ON', 'OFF'. * `two_digit_year_cutoff`: The year at which the system will treat the year as four digits instead of two. For example, if set to '1999', 1998 would be abbreviated to '98', while 2014 would be '2014'. Only applicable if `containment` => ‘PARTIAL’. Valid values are any year between 1753 and 9999. Defaults to 2049. * `db_chaining`: Whether the database can be the source or target of a cross-database ownership chain. Only applicable if `containment` => ‘PARTIAL’. Valid values are 'ON', 'OFF'. Defaults to 'OFF'. * `trustworthy`: Whether database modules (such as views, user-defined functions, or stored procedures) that use an impersonation context can access resources outside the database. Only applicable if `containment` => ‘PARTIAL’. Valid values are 'ON', 'OFF'. Defaults to 'OFF'. @@ -208,13 +219,13 @@ Requires defined type `sqlserver::config`. * `default_database`: Sets the database the login should default to when connecting. Defaults to 'master'. * `default_language`: Sets default language. Valid values are documented at http://msdn.microsoft.com/en-us/library/ms190303.aspx. Defaults to 'us_english'. * `check_expiration`: For SQL logins, checks to see if password has expired and user should be forced to change the password. Only applicable when Login_Type = 'SQL_LOGIN'. Valid values are 'true', 'false'. Default value is 'false'. -* `check_policy`: Checks the password policy. Only applicable when Login_Type = 'SQL_LOGIN'. Valid values are 'true', 'false'. Defaults to 'true'. -* `disabled`: Valid values are 'true', 'false'. Defaults to 'false'. +* `check_policy`: Checks the password policy. Only applicable when Login_Type = 'SQL_LOGIN'. Valid values are 'true', 'false'. Defaults to 'true'. +* `disabled`: Valid values are 'true', 'false'. Defaults to 'false'. **For more information about these settings and configuration in Microsoft SQL Server, please see:** * [Server Role Members](http://msdn.microsoft.com/en-us/library/ms186320.aspx) -* [Create Login](http://technet.microsoft.com/en-us/library/ms189751.aspx) +* [Create Login](http://technet.microsoft.com/en-us/library/ms189751.aspx) * [Alter Login](http://technet.microsoft.com/en-us/library/ms189828.aspx) #### sqlserver::sp_configure @@ -230,12 +241,12 @@ This defined type configures the instance to allow usage of filestream parameter **For more information about these settings and configuration in Microsoft SQL Server, please see:** -* [Reconfigure](http://msdn.microsoft.com/en-us/library/ms176069.aspx) +* [Reconfigure](http://msdn.microsoft.com/en-us/library/ms176069.aspx) * [Server Configuration Options](http://msdn.microsoft.com/en-us/library/ms189631.aspx) ##Limitations -This module is available only for Puppet Enterprise 3.7 and later. +This module is available only for Puppet Enterprise 3.7 and later. ##Development diff --git a/lib/puppet/provider/sqlserver_features/mssql.rb b/lib/puppet/provider/sqlserver_features/mssql.rb index 3002b94c..b3d1387a 100644 --- a/lib/puppet/provider/sqlserver_features/mssql.rb +++ b/lib/puppet/provider/sqlserver_features/mssql.rb @@ -11,8 +11,8 @@ def self.instances existing_instance = {:name => "Generic Features", :ensure => :present, :features => - PuppetX::Sqlserver::ServerHelper.translate_features( - jsonResult['Generic Features']).sort! + PuppetX::Sqlserver::ServerHelper.translate_features( + jsonResult['Generic Features']).sort! } debug "Parsed features = #{existing_instance[:features]}" @@ -59,8 +59,42 @@ def modify_features(action, features) cmd_args << "/PID=#{@resource[:pid]}" end end - try_execute(cmd_args, "Unable to #{action} features (#{features.join(', ')})") + begin + config_file = create_temp_for_install_switch unless action == 'uninstall' + cmd_args << "/ConfigurationFile=\"#{config_file.path}\"" unless config_file.nil? + try_execute(cmd_args, "Unable to #{action} features (#{features.join(', ')})") + ensure + if config_file + config_file.close + config_file.unlink + end + end + end + end + + def create_temp_for_install_switch + if not_nil_and_not_empty? @resource[:install_switches] + config_file = ["[OPTIONS]"] + @resource[:install_switches].each_pair do |k, v| + if RESERVED_SWITCHES.include? k + warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value +may be overridden by some command line arguments") + end + if v.is_a?(Numeric) || (v.is_a?(String) && v =~ /\d/) + config_file << "#{k}=#{v}" + elsif v.nil? + config_file << k + else + config_file << "#{k}=\"#{v}\"" + end + end + config_temp = Tempfile.new(['sqlconfig', '.ini']) + config_temp.write(config_file.join("\n")) + config_temp.flush + config_temp.close + return config_temp end + return nil end def installNet35 diff --git a/lib/puppet/provider/sqlserver_instance/mssql.rb b/lib/puppet/provider/sqlserver_instance/mssql.rb index 906f9ea8..0663bfbe 100644 --- a/lib/puppet/provider/sqlserver_instance/mssql.rb +++ b/lib/puppet/provider/sqlserver_instance/mssql.rb @@ -2,6 +2,9 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver')) Puppet::Type::type(:sqlserver_instance).provide(:mssql, :parent => Puppet::Provider::Sqlserver) do + RESERVED_SWITCHES = + %w(AGTSVCACCOUNT AGTSVCPASSWORD ASSVCACCOUNT AGTSVCPASSWORD PID + RSSVCACCOUNT RSSVCPASSWORD SAPWD SECURITYMODE SQLSYSADMINACCOUNTS FEATURES) def self.instances instances = [] @@ -12,8 +15,8 @@ def self.instances existing_instance = {:name => instance_name, :ensure => :present, :features => - PuppetX::Sqlserver::ServerHelper.translate_features( - jsonResult[instance_name]['features']).sort! + PuppetX::Sqlserver::ServerHelper.translate_features( + jsonResult[instance_name]['features']).sort! } instance = new(existing_instance) instances << instance @@ -42,7 +45,17 @@ def add_features(features) def modify_features(features, action) if not_nil_and_not_empty? features debug "#{action.capitalize}ing features '#{features.join(',')}'" - try_execute(build_cmd_args(features, action), "Error trying to #{action} features (#{features.join(', ')}") + cmd_args = build_cmd_args(features, action) + begin + config_file = create_temp_for_install_switch unless action == 'uninstall' + cmd_args << "/ConfigurationFile=\"#{config_file.path}\"" unless config_file.nil? + try_execute(cmd_args, "Error trying to #{action} features (#{features.join(', ')}") + ensure + if config_file + config_file.close + config_file.unlink + end + end end end @@ -56,9 +69,44 @@ def create destroy else installNet35 - cmd_args = build_cmd_args(@resource[:features]) - try_execute(cmd_args) + 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 + + def create_temp_for_install_switch + if not_nil_and_not_empty? @resource[:install_switches] + config_file = ["[OPTIONS]"] + @resource[:install_switches].each_pair do |k, v| + if RESERVED_SWITCHES.include? k + warn("Reserved switch [#{k}] found for `install_switches`, please know the provided value +may be overridden by some command line arguments") + end + if v.is_a?(Numeric) || (v.is_a?(String) && v =~ /\d/) + config_file << "#{k}=#{v}" + elsif v.nil? + config_file << k + else + config_file << "#{k}=\"#{v}\"" + end + end + config_temp = Tempfile.new(['sqlconfig', '.ini']) + config_temp.write(config_file.join("\n")) + config_temp.flush + config_temp.close + return config_temp end + return nil end def basic_cmd_args(features, action) @@ -73,7 +121,7 @@ def basic_cmd_args(features, action) def build_cmd_args(features, action="install") cmd_args = basic_cmd_args(features, action) if action == 'install' - (@resource.parameters.keys - %w(ensure loglevel features name provider source sql_sysadmin_accounts sql_security_mode).map(&:to_sym)).sort.collect do |key| + (@resource.parameters.keys - %w(ensure loglevel features name provider source sql_sysadmin_accounts sql_security_mode install_switches).map(&:to_sym)).sort.collect do |key| cmd_args << "/#{key.to_s.gsub(/_/, '').upcase}=\"#{@resource[key]}\"" end if not_nil_and_not_empty? @resource[:sql_sysadmin_accounts] diff --git a/lib/puppet/type/sqlserver_features.rb b/lib/puppet/type/sqlserver_features.rb index a58b3c83..508009be 100644 --- a/lib/puppet/type/sqlserver_features.rb +++ b/lib/puppet/type/sqlserver_features.rb @@ -43,6 +43,13 @@ end end + newparam(:install_switches) do + desc 'A hash of switches you want to pass to the installer' + validate do |value| + fail ArguemntError, 'install_switch must be in the form of a Hash' unless value.is_a?(Hash) + end + end + def validate if set?(:features) self[:features] = self[:features].flatten.sort.uniq diff --git a/lib/puppet/type/sqlserver_instance.rb b/lib/puppet/type/sqlserver_instance.rb index 58d19d34..fc5f0be7 100644 --- a/lib/puppet/type/sqlserver_instance.rb +++ b/lib/puppet/type/sqlserver_instance.rb @@ -2,7 +2,9 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'puppet_x/sqlserver/server_helper')) Puppet::Type::newtype(:sqlserver_instance) do + ensurable + newparam(:name, :namevar => true) do munge do |value| value.upcase @@ -114,6 +116,13 @@ newvalues('SQL') end + newparam(:install_switches) do + desc 'A hash of switches you want to pass to the installer' + validate do |value| + fail ArguemntError, 'install_switch must be in the form of a Hash' unless value.is_a?(Hash) + end + end + def validate if set?(:agt_svc_account) diff --git a/metadata.json b/metadata.json index d65fc8bc..d76f12e0 100644 --- a/metadata.json +++ b/metadata.json @@ -1,13 +1,13 @@ { "name": "puppetlabs-sqlserver", - "version": "1.0.0", + "version": "1.1.0", "author": "puppetlabs", "summary": "The `sqlserver` module installs and manages MS SQL Server 2012 and 2014 on Windows systems.", "license": "Puppet Labs Enterprise", "source": "PRIVATE", "project_page": "https://tickets.puppetlabs.com/browse/MODULES/component/12400", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES/component/12400", - "tags": ["ms sql", "mssql", "sql server", "microsoft sql server", "windows", "sql 2012", "sql 2014"], + "tags": ["sql", "mssql", "sqlserver", "microsoft", "sql2012", "sql2014", "tsql", "database"], "operatingsystem_support": [ { "operatingsystem": "Windows", diff --git a/spec/unit/puppet/provider/sqlserver__instance_spec.rb b/spec/unit/puppet/provider/sqlserver__instance_spec.rb index a9a6488e..0a5b1f0e 100644 --- a/spec/unit/puppet/provider/sqlserver__instance_spec.rb +++ b/spec/unit/puppet/provider/sqlserver__instance_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'mocha' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver_install_context.rb')) @@ -6,6 +7,7 @@ RSpec.describe provider_class do subject { provider_class } + let(:additional_install_switches) { [] } def stub_uninstall(args, installed_features) cmd_args = ["#{args[:source]}/setup.exe", @@ -32,7 +34,7 @@ def stub_uninstall(args, installed_features) '/IACCEPTSQLSERVERLICENSETERMS', "/INSTANCENAME=#{execute_args[:name]}", "/FEATURES=#{execute_args[:features].join(',')}",] - (execute_args.keys - %w(ensure loglevel features name source sql_sysadmin_accounts sql_security_mode).map(&:to_sym)).sort.collect do |key| + (execute_args.keys - %w(ensure loglevel features name source sql_sysadmin_accounts sql_security_mode install_switches).map(&:to_sym)).sort.collect do |key| cmd_args << "/#{key.to_s.gsub(/_/, '').upcase}=\"#{@resource[key]}\"" end if execute_args[:sql_security_mode] @@ -58,13 +60,16 @@ def stub_uninstall(args, installed_features) '/IACCEPTSQLSERVERLICENSETERMS', "/INSTANCENAME=#{execute_args[:name]}", "/FEATURES=#{execute_args[:features].join(',')}",] - (execute_args.keys - %w( ensure loglevel features name source sql_sysadmin_accounts sql_security_mode).map(&:to_sym)).sort.collect do |key| + (execute_args.keys - %w( ensure loglevel features name source sql_sysadmin_accounts sql_security_mode install_switches).map(&:to_sym)).sort.collect do |key| cmd_args << "/#{key.to_s.gsub(/_/, '').upcase}=\"#{@resource[key]}\"" end if execute_args[:sql_security_mode] cmd_args << "/SECURITYMODE=SQL" end cmd_args << "/SQLSYSADMINACCOUNTS=#{ Array.new(@resource[:sql_sysadmin_accounts]).collect { |account| "\"#{account}\"" }.join(' ')}" + additional_install_switches.each do |switch| + cmd_args << switch + end Puppet::Util::Execution.stubs(:execute).with(cmd_args.compact).returns(0) @provider.create } @@ -110,9 +115,9 @@ def stub_uninstall(args, installed_features) it_behaves_like 'destroy on create' do let(:installed_features) { %w(SQLEngine Replication) } let(:args) { { - :name => 'MYSQLSERVER', - :source => 'C:\myinstallexecs', - :features => [] + :name => 'MYSQLSERVER', + :source => 'C:\myinstallexecs', + :features => [] } } end end @@ -120,9 +125,9 @@ def stub_uninstall(args, installed_features) describe 'it should uninstall' do it_behaves_like 'destroy' do let(:args) { { - :name => 'MYSQLSERVER', - :source => 'C:\myinstallexecs', - :features => [] + :name => 'MYSQLSERVER', + :source => 'C:\myinstallexecs', + :features => [] } } let(:installed_features) { %w(SQLEngine Replication) } end @@ -131,11 +136,44 @@ def stub_uninstall(args, installed_features) describe 'installed features even if provided features' do it_behaves_like 'destroy' do let(:args) { { - :name => 'MYSQLSERVER', - :source => 'C:\myinstallexecs', - :features => ['SQL'] + :name => 'MYSQLSERVER', + :source => 'C:\myinstallexecs', + :features => ['SQL'] } } let(:installed_features) { %w(SQLEngine Replication) } end end + + describe 'install_switches' do + before :each do + @file_double = Tempfile.new(['sqlconfig', '.ini']) + @file_double.stubs(:write) + @file_double.stubs(:flush) + @file_double.stubs(:close) + Tempfile.stubs(:new).with(['sqlconfig', '.ini']).returns(@file_double) + end + + it_behaves_like 'create' do + args = get_basic_args + args[:install_switches] = {'ERRORREPORTING' => 1} + let(:additional_install_switches) { ["/ConfigurationFile=\"#{@file_double.path}\""] } + let(:args) { args } + munged = {:features => Array.new(args[:features])} + munged[:features].delete('SQL') + munged[:features] += %w(DQ FullText Replication SQLEngine) + munged[:features].sort! + let(:munged_values) { munged } + end + it_behaves_like 'create' do + args = get_basic_args + args[:install_switches] = {'ERRORREPORTING' => 1, 'SQLBACKUPDIR' => 'I:\DBbackup'} + let(:additional_install_switches) { ["/ConfigurationFile=\"#{@file_double.path}\""] } + let(:args) { args } + munged = {:features => Array.new(args[:features])} + munged[:features].delete('SQL') + munged[:features] += %w(DQ FullText Replication SQLEngine) + munged[:features].sort! + let(:munged_values) { munged } + end + end end diff --git a/spec/unit/puppet/provider/sqlserver_features_spec.rb b/spec/unit/puppet/provider/sqlserver_features_spec.rb index e43e27a8..f4aa21da 100644 --- a/spec/unit/puppet/provider/sqlserver_features_spec.rb +++ b/spec/unit/puppet/provider/sqlserver_features_spec.rb @@ -1,30 +1,39 @@ require 'spec_helper' require 'rspec' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver_spec_helper.rb')) +require 'mocha' provider_class = Puppet::Type.type(:sqlserver_features).provider(:mssql) RSpec.describe provider_class do subject { provider_class } - - shared_examples 'create' do |args, munged_args = {}| + let(:params) { { + :name => 'Base features', + :source => 'C:\myinstallexecs', + :features => %w(BC SSMS) + } } + let(:additional_params) { {} } + let(:munged_args) { {} } + let(:additional_switches) { [] } + shared_examples 'create' do it { - @resource = Puppet::Type::Sqlserver_features.new(args) + params.merge!(additional_params) + @resource = Puppet::Type::Sqlserver_features.new(params) @provider = provider_class.new(@resource) stub_powershell_call(subject) - executed_args = args.merge(munged_args) - stub_add_features(executed_args, executed_args[:features]) + executed_args = params.merge(munged_args) + stub_add_features(executed_args, executed_args[:features], additional_switches) @provider.create } end shared_context 'features' do @feature_params = { - :name => 'Base features', - :source => 'C:\myinstallexecs', - :features => %w(BC SSMS) + :name => 'Base features', + :source => 'C:\myinstallexecs', + :features => %w(BC SSMS) } let(:feature_remove) { [] } let(:feature_add) { [] } @@ -32,14 +41,28 @@ context 'it should provide the correct command default command' do include_context 'features' - it_should_behave_like 'create', @feature_params + it_should_behave_like 'create' + end + + context 'it should provide the correct command default command' do + before :each do + @file_double = Tempfile.new(['sqlconfig', '.ini']) + @file_double.stubs(:write) + @file_double.stubs(:flush) + @file_double.stubs(:close) + Tempfile.stubs(:new).with(['sqlconfig', '.ini']).returns(@file_double) + end + it_should_behave_like 'create' do + let(:additional_params) { {:install_switches => {'ERRORREPORTING' => 1, 'SQLBACKUPDIR' => 'I:\DBbackup'}} } + let(:additional_switches) { ["/ConfigurationFile=\"#{@file_double.path}\""] } + end end context 'it should expand the superset for features' do include_context 'features' - @feature_params[:features] = %w(Tools) - munged = {:features => %w(ADV_SSMS Conn SSMS)} - it_should_behave_like 'create', @feature_params, munged + let(:additional_params) { {:features => %w(Tools)} } + let(:munged_args) { {:features => %w(ADV_SSMS Conn SSMS)} } + it_should_behave_like 'create' end shared_examples 'features=' do |args| @@ -100,21 +123,21 @@ describe 'it should call destroy on empty array' do it { feature_params = { - :name => 'Base features', - :source => 'C:\myinstallexecs', - :features => [] + :name => 'Base features', + :source => 'C:\myinstallexecs', + :features => [] } @resource = Puppet::Type::Sqlserver_features.new(feature_params) @provider = provider_class.new(@resource) @provider.stubs(:current_installed_features).returns(%w(SSMS ADV_SSMS Conn)) Puppet::Util.stubs(:which).with("#{feature_params[:source]}/setup.exe").returns("#{feature_params[:source]}/setup.exe") Puppet::Util::Execution.expects(:execute).with( - ["#{feature_params[:source]}/setup.exe", - "/ACTION=uninstall", - '/Q', - '/IACCEPTSQLSERVERLICENSETERMS', - "/FEATURES=#{%w(SSMS ADV_SSMS Conn).join(',')}", - ]).returns(0) + ["#{feature_params[:source]}/setup.exe", + "/ACTION=uninstall", + '/Q', + '/IACCEPTSQLSERVERLICENSETERMS', + "/FEATURES=#{%w(SSMS ADV_SSMS Conn).join(',')}", + ]).returns(0) @provider.create } end diff --git a/spec/unit/puppet/sqlserver_spec_helper.rb b/spec/unit/puppet/sqlserver_spec_helper.rb index 8cce4d0a..141a4259 100644 --- a/spec/unit/puppet/sqlserver_spec_helper.rb +++ b/spec/unit/puppet/sqlserver_spec_helper.rb @@ -7,15 +7,15 @@ def stub_powershell_call(subject) Puppet::Provider::Sqlserver.stubs(:run_install_dot_net).returns() end -def stub_add_features(args, features) - stub_modify_features('install', args, features) +def stub_add_features(args, features, additional_switches = []) + stub_modify_features('install', args, features, additional_switches) end def stub_remove_features(args, features) stub_modify_features('uninstall', args, features) end -def stub_modify_features(action, args, features) +def stub_modify_features(action, args, features, additional_switches = []) cmds = ["#{args[:source]}/setup.exe", "/ACTION=#{action}", '/Q', @@ -28,5 +28,8 @@ def stub_modify_features(action, args, features) if args.has_key?(:is_svc_password) cmds << "/ISSVCPASSWORD=#{args[:is_svc_password]}" end + additional_switches.each do |switch| + cmds << switch + end Puppet::Util::Execution.stubs(:execute).with(cmds).returns(0) end