-
Notifications
You must be signed in to change notification settings - Fork 21
(FM-2577) - Change from sqlcmd.exe to win32ole connector #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,5 @@ fixtures: | |
forge_modules: | ||
acl: "puppetlabs/acl" | ||
stdlib: "puppetlabs/stdlib" | ||
acl: "puppetlabs/acl" | ||
symlinks: | ||
sqlserver: "#{source_dir}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this actually work now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Symlinking on Windows that is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does if you have puppetlabs_spec_helper > 0.9 and puppet > 3.5 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ def try_execute(command, msg = nil) | |
## | ||
def self.run_authenticated_sqlcmd(query, opts) | ||
b = binding | ||
@sql_instance_config = "C:/Program Files/Microsoft SQL Server/.puppet/.#{opts[:instance_name]}.cfg" | ||
@sql_instance_config = File.join(Puppet[:vardir], "cache/sqlserver/.#{resource[:instance]}.cfg") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if File.exists?(@sql_instance_config) | ||
@sql_instance_config = native_path(@sql_instance_config) | ||
else | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,33 @@ | ||
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver')) | ||
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/sql_connection')) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wheeeeee. I've never understood when and why things go in puppet_x There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a convention I believe that came out of moving non puppet related code out. @hunner maybe you could give a better history of this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds great! I would like to understand the history of this. |
||
|
||
Puppet::Type::type(:sqlserver_tsql).provide(:mssql, :parent => Puppet::Provider::Sqlserver) do | ||
|
||
def run(query, opts) | ||
debug("Running resource #{query} against #{resource[:instance]} with failonfail set to #{opts[:failonfail]}") | ||
opts[:instance_name] = resource[:instance] | ||
result = Puppet::Provider::Sqlserver.run_authenticated_sqlcmd(query, opts) | ||
return result | ||
|
||
def run(query) | ||
debug("Running resource #{query} against #{resource[:instance]}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the removal of failonfail isn't mentioned here - why removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not an execution of sqlcmd.exe and as a result does not take a failonfail param as is the case with command execution. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right on. |
||
config = get_instance_config | ||
sqlconn = PuppetX::Sqlserver::SqlConnection.new | ||
|
||
sqlconn.open_and_run_command(query, config) | ||
end | ||
|
||
def run_update | ||
result = self.run(resource[:command], {:failonfail => true}) | ||
return result | ||
def get_instance_config | ||
config_file = File.join(Puppet[:vardir], "cache/sqlserver/.#{resource[:instance]}.cfg") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While I'm thinking about this, what does instance equate to? Could it possible have any non-legit characters like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No it is not. Instance is the Named Instance. https://msdn.microsoft.com/en-us/library/ms143531.aspx
|
||
if !File.exists? (config_file) | ||
fail('Required config file missing, add the appropriate sqlserver::config and rerun') | ||
end | ||
if !File.readable?(config_file) | ||
fail('Unable to read config file, ensure proper permissions and please try again') | ||
end | ||
JSON.parse(File.read(config_file)) | ||
end | ||
|
||
def run_check | ||
return self.run(resource[:onlyif]) | ||
end | ||
|
||
def run_update | ||
return self.run(resource[:command]) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,9 +31,7 @@ def self.checks | |
newcheck(:onlyif, :parent => Puppet::Property::SqlserverTsql) do | ||
#Runs in the event that our TSQL exits with anything other than 0 | ||
def check(value) | ||
begin | ||
output = provider.run(value, :failonfail => false) | ||
end | ||
output = provider.run(value) | ||
debug("OnlyIf returned exitstatus of #{output.exitstatus}") | ||
output.exitstatus != 0 | ||
end | ||
|
@@ -61,7 +59,10 @@ def output | |
|
||
def refresh | ||
if self.check_all_attributes(true) | ||
provider.run_update | ||
result = provider.run_update | ||
if result.has_errors | ||
fail("Unable to apply changes, failed with error message #{result.error_message}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This appears to pass along the error if something goes wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct if we are unable to apply the update we raise a failure and give the user the error message have received from sqlserver |
||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
module PuppetX | ||
module Sqlserver | ||
|
||
CONNECTION_CLOSED = 0 | ||
|
||
class SqlConnection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a doc that links back to our original source for this code? Let's also make sure we follow the licensing policy as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I got this almost entirely from http://rubyonwindows.blogspot.com/2007/03/ruby-ado-and-sqlserver.html, I glanced at the other but it had so much abstraction that it didn't even go down that path. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok - I'm not sure how this works then given this SO answer about snippet licensing - http://meta.stackexchange.com/a/12537 Maybe @stahnma has an opinion on this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The amount of code we used from there was so minor, we took the oh yeah, that's how you create a win32ole adodb.connection, all the rest is really stuff I added for error handling. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I know you added a bunch of additional work here. Unfortunately it doesn't really matter how little / much if it was copied from somewhere initially. I think we're OK, but I just want to make sure we're in legal accordance here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, we need some sort of credit to that post and David Mullet. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am all for given credit where credit is due. However how would you go about this? |
||
attr_reader :exception_caught | ||
|
||
|
||
def initialize | ||
@connection = nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you. |
||
@data = nil | ||
end | ||
|
||
def open_and_run_command(query, config) | ||
begin | ||
open(config) | ||
command(query) | ||
ensure | ||
close | ||
end | ||
|
||
result | ||
end | ||
|
||
private | ||
def connection | ||
@connection ||= create_connection | ||
end | ||
|
||
def open(config) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this move to private? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? We might want to use it for other things other than open_and_run_command. We could use it for getting data fields later on. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could, later on, also move it out of private. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure why this diff hasn't updated but it was moved inside the private call. |
||
connection_string = get_connection_string(config) | ||
connection.Open(connection_string) unless !connection_closed? | ||
end | ||
|
||
def get_connection_string(config) | ||
config = {'database' => 'master'}.merge(config) | ||
# Open ADO connection to the SQL Server database | ||
connection_string = "Provider=SQLOLEDB.1;" | ||
connection_string << "Persist Security Info=False;" | ||
connection_string << "User ID=#{config['admin']};" | ||
connection_string << "password=#{config['pass']};" | ||
connection_string << "Initial Catalog=#{config['database']};" | ||
connection_string << "Application Name=Puppet;" | ||
if config['instance'] !~ /^MSSQLSERVER$/ | ||
connection_string << "Data Source=localhost\\#{config['instance']};" | ||
else | ||
connection_string << "Data Source=localhost;" | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this? As in why am I seeing localhost here on either side of the config? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Data source should not always be localhost unless I'm missing something. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So for example we have a named instance on the localhost you have to have \Instance name, if it is however the default instance of MSSQLSERVER and you add localhost\MSSQLSERVER it will fail the connection. |
||
end | ||
|
||
def command(sql) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this move to private then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's change method signature so that the block is required. def command(sql, &block) |
||
reset_instance | ||
begin | ||
r = execute(sql) | ||
yield(r) if block_given? | ||
rescue win32_exception => e | ||
@exception_caught = e | ||
end | ||
nil | ||
end | ||
|
||
def result | ||
ResultOutput.new(has_errors, error_message) | ||
end | ||
|
||
def has_errors | ||
@exception_caught != nil | ||
end | ||
|
||
def error_message | ||
@exception_caught.message unless @exception_caught == nil | ||
end | ||
|
||
def close | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this move to private then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all except initialize and open_and_run_command have been moved to private There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
begin | ||
connection.Close unless connection_closed? | ||
rescue win32_exception => e | ||
end | ||
end | ||
|
||
def reset_instance | ||
@data = nil | ||
@fields = nil | ||
@exception_caught = nil | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. I think I would call this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mostly because it's called the first time and every time, not just after it has previously run. |
||
|
||
def connection_closed? | ||
connection.State == CONNECTION_CLOSED | ||
end | ||
|
||
def create_connection | ||
require 'win32ole' | ||
WIN32OLE.new('ADODB.Connection') | ||
end | ||
|
||
def execute (sql) | ||
connection.Execute(sql, nil, nil) | ||
end | ||
|
||
def parse_column_names(result) | ||
result.Fields.extend(Enumerable).map { |column| column.Name } | ||
end | ||
|
||
# having as a method instead of hard coded allows us to stub and test outside of Windows | ||
def win32_exception | ||
::WIN32OLERuntimeError | ||
end | ||
|
||
def connection=(conn) | ||
@connection = conn | ||
end | ||
end | ||
|
||
class ResultOutput | ||
attr_reader :exitstatus, :error_message, :raw_error_message | ||
|
||
def initialize(has_errors, error_message) | ||
@exitstatus = has_errors ? 1 : 0 | ||
if error_message | ||
@raw_error_message = error_message | ||
@error_message = parse_for_error(error_message) | ||
end | ||
end | ||
|
||
def has_errors | ||
@exitstatus != 0 | ||
end | ||
|
||
private | ||
def parse_for_error(result) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can be |
||
match = result.match(/SQL Server\n\s+(.*)/i) | ||
match[1] unless match == nil | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,14 +24,10 @@ | |
$instance_name = $title, | ||
) { | ||
#possible future parameter if we do end up supporting different install directories | ||
$install_dir ='C:/Program Files/Microsoft SQL Server' | ||
$config_dir = "${install_dir}/.puppet" | ||
$config_dir = "${::puppet_vardir}/cache/sqlserver" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
$config_file = "${config_dir}/.${instance_name}.cfg" | ||
if !defined(File[$config_dir]){ | ||
file{ $config_dir: | ||
ensure => directory | ||
} | ||
} | ||
ensure_resource('file', ["${::puppet_vardir}/cache",$config_dir], { 'ensure' => 'directory','recurse' => 'true' }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Magic? I think I understand what this is doing... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where does ensure_resource come from? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is part of stdlib and will ensure a file resource exists if not already defined. Great helper so we don't double declare the same resource if we have multiple configs being specified. https://github.com/puppetlabs/puppetlabs-stdlib#ensure_resource There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
file{ $config_file: | ||
content => template('sqlserver/instance_config.erb'), | ||
require => File[$config_dir], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,15 +4,15 @@ | |
RSpec.describe 'sqlserver::config', :type => :define do | ||
let(:title) { 'MSSQLSERVER' } | ||
let(:params) { { | ||
:instance_name => 'MSSQLSERVER', | ||
:admin_user => 'sa', | ||
:admin_pass => 'Pupp3t1@', | ||
:instance_name => 'MSSQLSERVER', | ||
:admin_user => 'sa', | ||
:admin_pass => 'Pupp3t1@', | ||
} } | ||
let(:facts) { {:osfamily => 'windows', :platform => :windows} } | ||
let(:facts) { {:osfamily => 'windows', :platform => :windows, :puppet_vardir => 'C:/ProgramData/PuppetLabs/puppet/var'} } | ||
describe 'compile' do | ||
it { | ||
should contain_file('C:/Program Files/Microsoft SQL Server/.puppet/.MSSQLSERVER.cfg') | ||
should contain_file('C:/Program Files/Microsoft SQL Server/.puppet') | ||
should contain_file('C:/ProgramData/PuppetLabs/puppet/var/cache/sqlserver/.MSSQLSERVER.cfg') | ||
should contain_file('C:/ProgramData/PuppetLabs/puppet/var/cache/sqlserver') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Except this might need to also point to the variable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have mocked out the variable in the top scope
so we shouldn't need it for the test case. |
||
} | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
#! /usr/bin/env ruby -S rspec | ||
require 'spec_helper' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
describe "the sqlserver_upcase function" do | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
#! /usr/bin/env ruby -S rspec | ||
require 'spec_helper' | ||
|
||
describe "the sqlserver_validate_hash_uniq_values" do | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
require 'rspec' | ||
require 'spec_helper' | ||
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib/puppet_x/sqlserver/sql_connection')) | ||
|
||
RSpec.describe PuppetX::Sqlserver::SqlConnection do | ||
let(:subject) { PuppetX::Sqlserver::SqlConnection.new } | ||
let(:config) { {'admin' => 'sa', 'pass' => 'Pupp3t1@', 'instance' => 'MSSQLSERVER'} } | ||
|
||
def stub_connection | ||
@connection = mock() | ||
subject.stubs(:create_connection).returns(@connection) | ||
subject.stubs(:win32_exception).returns(Exception) | ||
end | ||
|
||
def stub_no_errors | ||
subject.stubs(:has_errors).returns(false) | ||
subject.stubs(:error_message).returns(nil) | ||
end | ||
|
||
describe 'open_and_run_command' do | ||
context 'command' do | ||
before :each do | ||
stub_connection | ||
@connection.stubs(:State).returns(0) | ||
@connection.stubs(:Open).with('Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;password=Pupp3t1@;Initial Catalog=master;Application Name=Puppet;Data Source=localhost;') | ||
end | ||
it 'should not raise an error but populate has_errors with message' do | ||
subject.stubs(:win32_exception).returns(Exception) | ||
subject.stubs(:execute).raises(Exception.new("SQL Server\n error has happened")) | ||
expect { | ||
result = subject.open_and_run_command('whacka whacka whacka', config) | ||
expect(result.exitstatus).to eq(1) | ||
expect(result.error_message).to eq('error has happened') | ||
}.to_not raise_error(Exception) | ||
|
||
end | ||
it 'should yield when passed a block' do | ||
subject.stubs(:execute).returns('results') | ||
subject.open_and_run_command('myquery', config) do |r| | ||
expect(r).to eq('results') | ||
end | ||
end | ||
end | ||
context 'closed connection' do | ||
before :each do | ||
stub_connection | ||
stub_no_errors | ||
@connection.stubs(:State).returns(0) | ||
end | ||
it 'should not add MSSQLSERVER to connection string' do | ||
@connection.stubs(:Open).with('Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;password=Pupp3t1@;Initial Catalog=master;Application Name=Puppet;Data Source=localhost;') | ||
subject.open_and_run_command('query', {'admin' => 'sa', 'pass' => 'Pupp3t1@', 'instance' => 'MSSQLSERVER'}) | ||
end | ||
it 'should add a non default instance to connection string' do | ||
@connection.stubs(:Open).with('Provider=SQLOLEDB.1;Persist Security Info=False;User ID=superuser;password=puppetTested;Initial Catalog=master;Application Name=Puppet;Data Source=localhost\LOGGING;') | ||
subject.open_and_run_command('query', {'admin' => 'superuser', 'pass' => 'puppetTested', 'instance' => 'LOGGING'}) | ||
end | ||
end | ||
context 'open connection' do | ||
it 'should not reopen an existing connection' do | ||
stub_connection | ||
@connection.expects(:open).never | ||
@connection.stubs(:State).returns(1) | ||
@connection.expects(:Execute).with('query', nil, nil) | ||
subject.open_and_run_command('query', {'admin' => 'sa', 'pass' => 'Pupp3t1@', 'instance' => 'MSSQLSERVER'}) | ||
end | ||
end | ||
context 'return result with errors' do | ||
it { | ||
subject.expects(:open).with({'admin' => 'sa', 'pass' => 'Pupp3t1@', 'instance' => 'MSSQLSERVER'}) | ||
subject.expects(:command).with('SELECT * FROM sys.databases') | ||
subject.expects(:close).once | ||
subject.stubs(:has_errors).returns(:true) | ||
subject.stubs(:error_message).returns( | ||
'SQL Server | ||
invalid syntax provider') | ||
result = | ||
subject.open_and_run_command('SELECT * FROM sys.databases', | ||
{'instance' => 'MSSQLSERVER', 'admin' => 'sa', 'pass' => 'Pupp3t1@'}) | ||
expect(result.exitstatus).to eq(1) | ||
expect(result.error_message).to eq('invalid syntax provider') | ||
} | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,4 +47,3 @@ BEGIN | |
<% end -%> | ||
END | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line ending noise |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{ 'instance': '<%= @instance_name %>','admin':'<%= @admin_user %>','pass':'<%= @admin_pass %>' } | ||
{ "instance": "<%= @instance_name %>","admin":"<%= @admin_user %>","pass":"<%= @admin_pass %>" } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we don't support integrated security at all? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be clear we are talking about passing the current users credentials from a command window, through ruby to an adodb. I don't see this as an optimal pattern. Accepting a windows login might be more likely however. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, integrated security is just telling SQL server to go get the Windows login context and use it. It's just "Integrated Security=SSPI" and part of the connection string. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be the benefit of it? Does it cost anything to add it to the connection string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not worry about the integrated security bit here, but let's file another ticket. I have a feeling there will be a few more touch points to support that (including at initial SQL install time) if we want to do it. There are some tradeoffs Pros
Cons
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would totally love to see that file have some sort of encryption, even if we figure out dpapi. ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Iristyle the additional installation config is already there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting... duplicate eh?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think this came from a merge conflict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right on.