-
Notifications
You must be signed in to change notification settings - Fork 611
/
postgresql_psql.rb
169 lines (135 loc) · 5.24 KB
/
postgresql_psql.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# frozen_string_literal: true
Puppet::Type.newtype(:postgresql_psql) do # rubocop:disable Metrics/BlockLength
newparam(:name) do
desc 'An arbitrary tag for your own reference; the name of the message.'
isnamevar
end
newproperty(:command) do
desc 'The SQL command to execute via psql.'
defaultto { @resource[:name] }
# If needing to run the SQL command, return a fake value that will trigger
# a sync, else return the expected SQL command so no sync takes place
def retrieve
if @resource.should_run_sql
:notrun
else
should
end
end
def sync
output, status = provider.run_sql_command(value)
raise("Error executing SQL; psql returned #{status}: '#{output}'") unless status.to_i.zero?
end
end
newparam(:unless) do
desc <<-DOC
An optional SQL command to execute prior to the main :command;
this is generally intended to be used for idempotency, to check
for the existence of an object in the database to determine whether
or not the main SQL command needs to be executed at all.'
DOC
# Return true if a matching row is found
def matches(value)
output, status = provider.run_unless_sql_command(value)
fail("Error evaluating 'unless' clause, returned #{status}: '#{output}'") unless status.to_i.zero? # rubocop:disable Style/SignalException
result_count = output.strip.to_i
debug("Found #{result_count} row(s) executing 'unless' clause")
result_count.positive?
end
end
newparam(:onlyif) do
desc <<-DOC
An optional SQL command to execute prior to the main :command;
this is generally intended to be used for idempotency, to check
for the existence of an object in the database to determine whether
or not the main SQL command needs to be executed at all.
DOC
# Return true if a matching row is found
def matches(value)
output, status = provider.run_unless_sql_command(value)
status = output.exitcode if status.nil?
raise("Error evaluating 'onlyif' clause, returned #{status}: '#{output}'") unless status.to_i.zero?
result_count = output.strip.to_i
debug("Found #{result_count} row(s) executing 'onlyif' clause")
result_count.positive?
end
end
newparam(:connect_settings) do
desc 'Connection settings that will be used when connecting to postgres'
end
newparam(:db) do
desc 'The name of the database to execute the SQL command against, this overrides any PGDATABASE value in connect_settings'
end
newparam(:port) do
desc 'The port of the database server to execute the SQL command against, this overrides any PGPORT value in connect_settings.'
end
newparam(:search_path) do
desc 'The schema search path to use when executing the SQL command'
end
newparam(:psql_path) do
desc 'The path to psql executable.'
defaultto('psql')
end
newparam(:psql_user) do
desc 'The system user account under which the psql command should be executed.'
defaultto('postgres')
end
newparam(:psql_group) do
desc 'The system user group account under which the psql command should be executed.'
defaultto('postgres')
end
newparam(:cwd, parent: Puppet::Parameter::Path) do
desc 'The working directory under which the psql command should be executed.'
defaultto('/tmp')
end
newparam(:environment) do
desc "Any additional environment variables you want to set for a
SQL command. Multiple environment variables should be
specified as an array."
validate do |values|
Array(values).each do |value|
raise ArgumentError, "Invalid environment setting '#{value}'" unless %r{\w+=}.match?(value)
end
end
end
newparam(:refreshonly, boolean: true) do
desc "If 'true', then the SQL will only be executed via a notify/subscribe event."
defaultto(:false)
newvalues(:true, :false)
end
newparam(:instance) do
desc 'The postgresql instance under which the psql command should be executed.'
defaultto('main')
end
newparam(:sensitive, boolean: true) do
desc "If 'true', then the executed command will not be echoed into the log. Use this to protect sensitive information passing through."
defaultto(:false)
newvalues(:true, :false)
end
autorequire(:anchor) do
["postgresql::server::service::begin::#{self[:instance]}"]
end
autorequire(:service) do
["postgresqld_instance_#{self[:instance]}"]
end
def should_run_sql(refreshing = false)
onlyif_param = @parameters[:onlyif]
unless_param = @parameters[:unless]
return false if !onlyif_param.nil? && !onlyif_param.value.nil? && !onlyif_param.matches(onlyif_param.value)
return false if !unless_param.nil? && !unless_param.value.nil? && unless_param.matches(unless_param.value)
return false if !refreshing && @parameters[:refreshonly].value == :true
true
end
def refresh
property(:command).sync if should_run_sql(true)
end
private
def set_sensitive_parameters(sensitive_parameters) # rubocop:disable Naming/AccessorMethodName
# Respect sensitive commands
if sensitive_parameters.include?(:unless)
sensitive_parameters.delete(:unless)
parameter(:unless).sensitive = true
end
super(sensitive_parameters)
end
end