Skip to content

(FM-2577) - Change from sqlcmd.exe to win32ole connector #96

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

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
861c0da
add geppetto-rc file to ignore examples (you should fix your examples…
justinstoller Dec 17, 2014
f70c409
Merge pull request #61 from justinstoller/maint/lint-fixes
cyberious Dec 17, 2014
6cd4997
FM-2122: Deleted irrelevant contribution information
Dec 18, 2014
7311ead
FM-2122: Added new PE-only development paragraph to readme
Dec 19, 2014
45c7ec5
Merge pull request #62 from jbondpdx/readme-fix-contribute
Dec 19, 2014
72d0d83
Fix metadata.json and capture back puppet module build metadata.json
Dec 15, 2014
b9c03a8
Merge pull request #60 from cyberious/Anubis
Dec 23, 2014
404c2d3
FM-2102 fix examples/sp_configure.pp
Jan 6, 2015
71f0870
Merge pull request #63 from cyberious/FM-2102
cmurphy Jan 6, 2015
3fd2931
FM-2110 Prep TSQL provider to be released and backport for all existi…
Jan 16, 2015
ce95060
Merge pull request #64 from cyberious/FM2110
hunner Jan 18, 2015
d3b8730
FM-2110 TSQL Predocs
Jan 16, 2015
ffadfd2
Merge pull request #65 from cyberious/FM2110-readme
Jan 22, 2015
27c79e3
DOC-1510: edit tsql additions
Jan 22, 2015
ec001fd
Fix bug with TSQL provider rework
Jan 28, 2015
4684578
Merge pull request #67 from cyberious/master
Jan 28, 2015
ac27cfc
Merge pull request #66 from jbondpdx/master
cyberious Feb 3, 2015
6056a42
FM-1900 SQLServer Add User provider
Feb 2, 2015
58be6dd
Merge pull request #68 from cyberious/FM1900
ferventcoder Feb 4, 2015
ae28a21
FM-1901 SQL Server Delete User from existing database, also added err…
Feb 4, 2015
675f974
Merge pull request #69 from cyberious/FM1901
ferventcoder Feb 9, 2015
b80ce9e
FM-1898 Add sqlserver::user::permission with Grant, Revoke and Deny
Feb 11, 2015
dc0a5a0
Merge pull request #70 from cyberious/FM-2246
hunner Feb 18, 2015
a8f7f56
Update sqlserver_validate_range to take array
Feb 25, 2015
5249370
Merge pull request #74 from cyberious/validateRange
hunner Feb 25, 2015
461ba1b
FM-2236 Add with_grant_option for user permission
Feb 18, 2015
0b97c1d
FM-1556 Add ability to manage login server level permissions
Feb 20, 2015
12de69b
FM-1556 Change permission to permissions and allow for array
Feb 25, 2015
0a99b81
FM-2236 Change to permissions and allow user to pass an array instead…
Feb 25, 2015
f553284
Merge remote-tracking branch 'cyberious/FM-2236'
Iristyle Feb 27, 2015
bff63fe
Merge remote-tracking branch 'cyberious/FM-1556'
Iristyle Feb 27, 2015
25ac79c
Fixed a bug with sqlserver_validate_instance_name that was not catchi…
Feb 25, 2015
bd8d2fa
FM-2286 Create/Drop Roles with Authorization
Feb 25, 2015
043b2fa
Create Upcase functionality in module until released in Stdlib
Mar 3, 2015
311fd63
FM-2287 - Role Permissions - Add define and hash for role to pass to …
Feb 26, 2015
ff9ad36
Add docs for the code changes
Mar 2, 2015
9983ce2
FM-2303 Add install switches to sqlserver_install and sqlserver_features
Mar 3, 2015
1f1503c
Merge pull request #78 from cyberious/FM-2303
Mar 3, 2015
3e921d1
Merge pull request #76 from cyberious/RolePermissions
hunner Mar 3, 2015
02645b1
FM-2288 Add Role Members with Purge support
Mar 3, 2015
a3c800c
Merge pull request #77 from cyberious/RoleMembers
hunner Mar 3, 2015
23faa7c
Add function to test for uniq values in hash
Mar 4, 2015
7130984
FM-2299 Login - Allow for permissions hash
Mar 4, 2015
4010ba2
FM-2298 - User - Add permissions hash to allow user to pass all permi…
Mar 4, 2015
00f3758
Merge pull request #79 from cyberious/LoginPermissions
Mar 4, 2015
4075b12
(BKR-147) add Gemfile setting for BEAKER_VERSION for puppet...
Mar 24, 2015
eeb0c78
Merge pull request #84 from anodelman/master
justinstoller Mar 26, 2015
3da8d96
(fix) remove provider parameter from README.md
Iristyle May 4, 2015
6d91983
(maint) fix metadata.json tags
Iristyle May 4, 2015
1b57c9e
Fix spec tests raise_error check
Mar 19, 2015
93b61a6
(FM-2575) - Fixed bug with login exists, and creation
Mar 19, 2015
3cf0d27
Revert "FM-2303 Add install switches to sqlserver_install and sqlserv…
Iristyle May 4, 2015
431de18
Prepare for 1.1.0 release
Mar 5, 2015
484a997
Add readme updates to reflect changes
Mar 5, 2015
3047fb2
FM-2328: document install_switches param in sqlserver
Mar 9, 2015
45bed60
DOCS: Improved example for install_switches param
Mar 9, 2015
c5fceca
Merge branch 'release'
Iristyle May 4, 2015
eebed97
(FM-2577) - Change from sqlcmd.exe to win32ole connector
Apr 27, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ fixtures:
forge_modules:
acl: "puppetlabs/acl"
stdlib: "puppetlabs/stdlib"
acl: "puppetlabs/acl"
symlinks:
"sqlserver": "#{source_dir}"
sqlserver: "#{source_dir}"
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
---
sudo: false
language: ruby
bundler_args: --without development
script: "bundle exec rake spec SPEC_OPTS='--format documentation'"
rvm:
- 1.9.3
- 2.0.0
- 2.1.5
env:
matrix:
- PUPPET_GEM_VERSION="~> 3.7.1"
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,39 @@ sqlserver::login{'WIN-D95P1A3V103\localAccount':
}
```

###To run custom TSQL statements:

To use `sqlserver_tsql` to trigger other classes or defined types:

```
sqlserver_tsql{ 'Query Logging DB Status':
instance => 'MSSQLSERVER',
onlyif => "IF (SELECT count(*) FROM myDb.dbo.logging_table WHERE
message like 'FATAL%') > 1000 THROW 50000, 'Fatal Exceptions in Logging', 10",
notify => Exec['Too Many Fatal Errors']
}
```

To clean up regular logs with conditional checks:

```
sqlserver_tsql{ 'Cleanup Old Logs':
instance => 'MSSQLSERVER',
command => "DELETE FROM myDb.dbo.logging_table WHERE log_date < '${log_max_date}'",
onlyif => "IF exists(SELECT * FROM myDb.dbo.logging_table WHERE log_date < '${log_max_date}')
THROW 50000, 'need log cleanup', 10",
}
```

If you want something to always execute, you can leave out the `onlyif` parameter:

```
sqlserver_tsql{ 'Always running':
instance => 'MSSQLSERVER',
command => 'EXEC notified_executor()',
}
```

#### Windows SQL Server Terms

Terminology differs somewhat between various database systems; please refer to this list of terms for clarification.
Expand Down
28 changes: 28 additions & 0 deletions lib/puppet/parser/functions/sqlserver_upcase.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Puppet::Parser::Functions
newfunction(:sqlserver_upcase, :type => :rvalue, :arity => 1) do |arguments|

raise(Puppet::ParseError, "upcase(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size != 1

value = arguments[0]

unless value.is_a?(Array) || value.is_a?(Hash) || value.respond_to?(:upcase)
raise(Puppet::ParseError, 'upcase(): Requires an ' +
'array, hash or object that responds to upcase in order to work')
end

if value.is_a?(Array)
# Numbers in Puppet are often string-encoded which is troublesome ...
result = value.collect { |i| function_sqlserver_upcase([i]) }
elsif value.is_a?(Hash)
result = {}
value.each_pair do |k, v|
result[function_sqlserver_upcase([k])] = function_sqlserver_upcase([v])
end
else
result = value.upcase
end

return result
end
end
21 changes: 21 additions & 0 deletions lib/puppet/parser/functions/sqlserver_validate_hash_uniq_values.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# === Defined Parser Function: sqlserver_validate_hash_uniq_values
#
# [args*] A hash, that contains string or string[] for values
#
# @raise [Puppet::ParserError] When duplicates are found
#
module Puppet::Parser::Functions
newfunction(:sqlserver_validate_hash_uniq_values) do |arguments|

raise(Puppet::ParseError, 'Expect a Hash as an argument') unless arguments[0].is_a?(Hash)

value = arguments[0].each_value.collect { |v| v }.flatten

total_count = value.count
uniq_count = value.uniq.count
msg = arguments[1] ? arguments[1] : "Duplicate values passed to hash #{value}"
if uniq_count != total_count
raise(Puppet::ParseError, msg)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ module Puppet::Parser::Functions
end
value = args[0]
errors = []
if value.length < 1 || value.empty?
errors << "Instance name must be between 1 to 16 characters"
end
if value.length > 16
errors << "Instance name can not be larger than 16 characters, you provided #{value}"
end
Expand Down
20 changes: 13 additions & 7 deletions lib/puppet/parser/functions/sqlserver_validate_range.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@ module Puppet::Parser::Functions
if (args.length < 3) or (args.length > 4) then
raise Puppet::ParseError, ("validate_range(): wrong number of arguments (#{args.length}; must be 3)")
end
value, lower, upper, msg = args
values, lower, upper, msg = args

msg = msg || "validate_range(): #{args[0].inspect} is not between #{args[1].inspect} and #{args[2].inspect}"

if /^\d+(|\.\d+)$/.match(value)
raise(Puppet::ParseError, msg) unless Float(value).between?(Float(lower), Float(upper))
else
value.strip!
raise(Puppet::ParseError, msg) unless value.length >= Integer(lower) && value.length <= Integer(upper)
if values.is_a? String
values = Array.new << values
end

values.each do |value|
msg = msg || "validate_range(): #{args[0].inspect} is not between #{args[1].inspect} and #{args[2].inspect}"
if /^\d+(|\.\d+)$/.match(value)
raise(Puppet::ParseError, msg) unless Float(value).between?(Float(lower), Float(upper))
else
value.strip!
raise(Puppet::ParseError, msg) unless value.length >= Integer(lower) && value.length <= Integer(upper)
end
end
end
end
File renamed without changes.
19 changes: 19 additions & 0 deletions lib/puppet/property/sqlserver_tsql.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'puppet/property'

class Puppet::Property::SqlserverTsql < Puppet::Property
desc 'TSQL property that we are going to wrap with a try catch'
munge do |value|
erb_template = <<-TEMPLATE
BEGIN TRY
#{value}
END TRY
BEGIN CATCH
DECLARE @msg as VARCHAR(max);
SELECT @msg = 'THROW CAUGHT: ' + ERROR_MESSAGE();
THROW 51000, @msg, 10
END CATCH
TEMPLATE
value = erb_template
end

end
9 changes: 8 additions & 1 deletion lib/puppet/provider/sqlserver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,15 @@ def self.run_authenticated_sqlcmd(query, opts)
temp_ps1.write(ps1.result(b))
temp_ps1.flush
temp_ps1.close
#We want to not fail the exec but fail the overall process once we get the clean result back, otherwise we report the temp file which is meaningless
result = Puppet::Util::Execution.execute(['powershell.exe', '-noprofile', '-executionpolicy', 'unrestricted', temp_ps1.path], {:failonfail => false}) #We expect some things to fail in order to run as an only if
debug("Return result #{result.exitstatus}")
debug("Return result #{result}")
if opts[:failonfail] && result.match(/THROW CAUGHT/)
fail(result.gsub('THROW CAUGHT:', ''))
end
if result.match(/Msg \d+, Level 16/)
fail(result)
end
return result
ensure
temp_ps1.close
Expand Down
52 changes: 46 additions & 6 deletions lib/puppet/provider/sqlserver_tsql/mssql.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,61 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sqlserver'))
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x/sqlserver/sql_connection'))

Puppet::Type::type(:sqlserver_tsql).provide(:mssql, :parent => Puppet::Provider::Sqlserver) do


def run(query)
debug("Running resource #{query} against #{resource[:instance]}")
result = Puppet::Provider::Sqlserver.run_authenticated_sqlcmd(query, {:instance_name => resource[:instance]})
return result
config = get_instance_config
begin
sqlconn = PuppetX::Sqlserver::SqlConnection.new
sqlconn.open(config["admin"], config["pass"], resource[:instance])
sqlconn.command(query)
result = ResultOutput.new(sqlconn)
if result.has_errors
debug("Returned a result of #{result.exitstatus}, with #{parse_for_error(result.error_message)}")
end
return result
ensure
sqlconn.close
end
end

def get_instance_config
config_file = File.join(Puppet[:vardir], "cache/sqlserver/.#{resource[:instance]}.cfg")
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
result = self.run(resource[:onlyif])
return result
return self.run(resource[:onlyif])
end

def run_update
result = self.run(resource[:command])
return result
return self.run(resource[:command])

end

def parse_for_error(result)
match = result.match(/SQL Server\n\s+(.*)/i)
match[1] unless match == nil
end

class ResultOutput
attr_reader :exitstatus, :error_message

def initialize(sqlconn)
@exitstatus = sqlconn.has_errors ? 1 : 0
@error_message = sqlconn.error_message
end

def has_errors
@exitstatus != 0
end
end
end
12 changes: 10 additions & 2 deletions lib/puppet/templates/authenticated_query.ps1.erb
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,22 @@ if (!(Get-Command 'sqlcmd.exe' -ErrorAction SilentlyContinue)){
}

$result = sqlcmd.exe -i '<%= input_file %>' -h-1 -W -s ',' <% if @instance != 'MSSQLSERVER' %>-S localhost\<%= @instance %><%end%>
if($result -match "ERROR"){
Write-Error -Message ($result | where {$_ -match "ERROR"} | select -First 1)
if($result -match "THROW CAUGHT"){
Write-Host ($result | where {$_ -match "THROW CAUGHT"} | select -First 1)
Write-Error -Message ($result | where {$_ -match "THROW CAUGHT"} | select -First 1)
exit(10)
}
if($result -match "Incorrect syntax near "){
Write-Host ($result | where {$_ -match "Incorrect syntax near"} | select -First 1)
Write-Error -Message ($result | where {$_ -match "Incorrect syntax"} | select -First 1)
exit(10)
}
if($result -match "Msg \d+, Level 16"){
$msg = $result -join ' '
Write-Host $msg
Write-Error -Message "ERROR: $msg"
exit(10)
}
}
catch{
Write-Host $_
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/type/sqlserver_features.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'property/login'))
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'property/sqlserver_login'))
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'puppet_x/sqlserver/server_helper'))

Puppet::Type::newtype(:sqlserver_features) do
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/type/sqlserver_instance.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'property/login'))
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'property/sqlserver_login'))
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'puppet_x/sqlserver/server_helper'))

Puppet::Type::newtype(:sqlserver_instance) do
Expand Down
18 changes: 12 additions & 6 deletions lib/puppet/type/sqlserver_tsql.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'puppet'
require 'puppet/property/sqlserver_tsql'

Puppet::Type::newtype(:sqlserver_tsql) do
newparam :name, :namevar => true
Expand All @@ -15,21 +16,23 @@ def self.checks
end

desc 'command to run against an instance with the authenticated credentials used in sqlserver::config'
newparam(:command) do
newparam(:command, :parent => Puppet::Property::SqlserverTsql) do

end

desc 'requires the usage of sqlserver::config with the user and password'
newparam(:instance) do

munge do |value|
value.upcase
end
end

desc 'SQL Query to run and only run if exits with non-zero'
newcheck(:onlyif) do
# Return true if the command returns 0.
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)
output = provider.run(value, :failonfail => false)
end
debug("OnlyIf returned exitstatus of #{output.exitstatus}")
output.exitstatus != 0
Expand Down Expand Up @@ -58,7 +61,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}")
end
end
end

Expand Down
Loading