smart_proxy_salt 2.1.8 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3617d7030f84c637b456820c2ed126a46a0891f8
4
- data.tar.gz: e38b6cbe39839ac23e9b734fd1b72ee5baeb10fb
2
+ SHA256:
3
+ metadata.gz: 5c5e6d0a2348b06d27789269578966ec1b2ae1413341ca1dc5bb318630653c44
4
+ data.tar.gz: 8238c8469d73c893ead9a9cba3692652b9227a5aa6bdc400cc53e1c83e28e7db
5
5
  SHA512:
6
- metadata.gz: 5b4b844c9a4463aa77ca9769028fd5d32d9efa933c4ecc6cf90391ab437f78936a7882583f548bfa338c33dfd4731e27fba5f1d233e650521aaf3411888cf824
7
- data.tar.gz: 657c0199e6aea9a2fefdcc4847f2a7107ba4dd1fbf28c2e7413a4119a09c79680e69a5ed569e13f2e854a07096ba82bc8e8e69752ea5e3b1b9fbf26f47f57c45
6
+ metadata.gz: 2873b74a8f42b9e979c38da137674d92e3d0cccdfea62924d27b89ca3c76f4ffc3a5ed961c3e9935311ca1ca51868e44f4315d3cd4d86752d315de0434955b62
7
+ data.tar.gz: '091bdeb081d90458404ad84baba32db5830b170a28678f554174030722563935186e7fd9abcb52fa743edf5148aae76b65177e7e13e5b2113f48fb0f8f1c8b75'
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  # This is the external nodes script to allow Salt to retrieve info about a host
3
5
  # from Foreman. It also uploads a node's grains to Foreman, if the setting is
4
6
  # enabled.
5
7
 
6
8
  require 'yaml'
7
9
 
8
- $settings_file = '/etc/salt/foreman.yaml'
9
- SETTINGS = YAML.load_file($settings_file)
10
+ settings_file = '/etc/salt/foreman.yaml'
11
+ SETTINGS = YAML.load_file(settings_file)
10
12
 
11
13
  require 'net/http'
12
14
  require 'net/https'
@@ -19,9 +21,13 @@ rescue LoadError
19
21
  # Debian packaging guidelines state to avoid needing rubygems, so
20
22
  # we only try to load it if the first require fails (for RPMs)
21
23
  begin
22
- require 'rubygems' rescue nil
24
+ begin
25
+ require 'rubygems'
26
+ rescue Exception
27
+ nil
28
+ end
23
29
  require 'json'
24
- rescue LoadError => e
30
+ rescue LoadError
25
31
  puts 'You need the `json` gem to use the Foreman ENC script'
26
32
  # code 1 is already used below
27
33
  exit 2
@@ -37,66 +43,33 @@ def valid_hostname?(hostname)
37
43
  end
38
44
 
39
45
  def get_grains(minion)
40
- begin
41
- grains = {
42
- :name => minion,
43
- :facts => plain_grains(minion).merge({:_timestamp => Time.now, :_type => 'foreman_salt'})
44
- }
45
-
46
- grains[:facts][:operatingsystem] = grains[:facts]['os']
47
- grains[:facts][:operatingsystemrelease] = grains[:facts]['osrelease']
48
-
49
- JSON.pretty_generate(grains)
50
- rescue => e
51
- puts "Could not get grains: #{e}"
52
- exit 1
53
- end
46
+ grains = {
47
+ :name => minion,
48
+ :facts => plain_grains(minion).merge(:_timestamp => Time.now, :_type => 'foreman_salt')
49
+ }
50
+
51
+ grains[:facts][:operatingsystem] = grains[:facts]['os']
52
+ grains[:facts][:operatingsystemrelease] = grains[:facts]['osrelease']
53
+
54
+ JSON.pretty_generate(grains)
55
+ rescue Exception => e
56
+ puts "Could not get grains: #{e}"
57
+ exit 1
54
58
  end
55
59
 
56
60
  def plain_grains(minion)
57
61
  # We have to get the grains from the cache, because the client
58
62
  # is probably running 'state.highstate' right now.
59
- #
60
- # salt-run doesn't support directly outputting to json,
61
- # so we have resort to python to extract the grains.
62
- # Based on https://github.com/saltstack/salt/issues/9444
63
-
64
- script = <<-EOF
65
- #!/usr/bin/env python
66
- import json
67
- import os
68
- import sys
69
-
70
- import salt.config
71
- import salt.runner
72
-
73
- if __name__ == '__main__':
74
- __opts__ = salt.config.master_config(
75
- os.environ.get('SALT_MASTER_CONFIG', '/etc/salt/minion'))
76
- runner = salt.runner.Runner(__opts__)
77
-
78
- stdout_bak = sys.stdout
79
- with open(os.devnull, 'wb') as f:
80
- sys.stdout = f
81
- ret = runner.cmd('cache.grains', ['#{minion}'])
82
- sys.stdout = stdout_bak
83
-
84
- print json.dumps(ret)
85
- EOF
86
-
87
- result = IO.popen('python 2>/dev/null', mode='r+') do |python|
88
- python.write script
89
- python.close_write
90
- result = python.read
63
+
64
+ result = IO.popen(['salt-run', '-l', 'quiet', '--output=json', 'cache.grains', minion]) do |io|
65
+ io.read
91
66
  end
92
67
 
93
- grains = JSON.load(result)
68
+ grains = JSON.parse(result)
94
69
 
95
- if grains
96
- plainify(grains[minion]).flatten.inject(&:merge)
97
- else
98
- raise 'No grains received from Salt master'
99
- end
70
+ raise 'No grains received from Salt master' unless grains
71
+
72
+ plainify(grains[minion]).flatten.inject(&:merge)
100
73
  end
101
74
 
102
75
  def plainify(hash, prefix = nil)
@@ -126,33 +99,31 @@ def get_key(key, prefix)
126
99
  end
127
100
 
128
101
  def upload_grains(minion)
129
- begin
130
- grains = get_grains(minion)
131
- uri = URI.parse("#{foreman_url}/api/hosts/facts")
132
- req = Net::HTTP::Post.new(uri.request_uri)
133
- req.add_field('Accept', 'application/json,version=2' )
134
- req.content_type = 'application/json'
135
- req.body = grains
136
- res = Net::HTTP.new(uri.host, uri.port)
137
- res.use_ssl = uri.scheme == 'https'
138
- if res.use_ssl?
139
- if SETTINGS[:ssl_ca] && !SETTINGS[:ssl_ca].empty?
140
- res.ca_file = SETTINGS[:ssl_ca]
141
- res.verify_mode = OpenSSL::SSL::VERIFY_PEER
142
- else
143
- res.verify_mode = OpenSSL::SSL::VERIFY_NONE
144
- end
145
- if SETTINGS[:ssl_cert] && !SETTINGS[:ssl_cert].empty? && SETTINGS[:ssl_key] && !SETTINGS[:ssl_key].empty?
146
- res.cert = OpenSSL::X509::Certificate.new(File.read(SETTINGS[:ssl_cert]))
147
- res.key = OpenSSL::PKey::RSA.new(File.read(SETTINGS[:ssl_key]), nil)
148
- end
149
- elsif SETTINGS[:username] && SETTINGS[:password]
150
- req.basic_auth(SETTINGS[:username], SETTINGS[:password])
102
+ grains = get_grains(minion)
103
+ uri = URI.parse("#{foreman_url}/api/hosts/facts")
104
+ req = Net::HTTP::Post.new(uri.request_uri)
105
+ req.add_field('Accept', 'application/json,version=2')
106
+ req.content_type = 'application/json'
107
+ req.body = grains
108
+ res = Net::HTTP.new(uri.host, uri.port)
109
+ res.use_ssl = uri.scheme == 'https'
110
+ if res.use_ssl?
111
+ if SETTINGS[:ssl_ca] && !SETTINGS[:ssl_ca].empty?
112
+ res.ca_file = SETTINGS[:ssl_ca]
113
+ res.verify_mode = OpenSSL::SSL::VERIFY_PEER
114
+ else
115
+ res.verify_mode = OpenSSL::SSL::VERIFY_NONE
151
116
  end
152
- res.start { |http| http.request(req) }
153
- rescue => e
154
- raise "Could not send facts to Foreman: #{e}"
117
+ if SETTINGS[:ssl_cert] && !SETTINGS[:ssl_cert].empty? && SETTINGS[:ssl_key] && !SETTINGS[:ssl_key].empty?
118
+ res.cert = OpenSSL::X509::Certificate.new(File.read(SETTINGS[:ssl_cert]))
119
+ res.key = OpenSSL::PKey::RSA.new(File.read(SETTINGS[:ssl_key]), nil)
120
+ end
121
+ elsif SETTINGS[:username] && SETTINGS[:password]
122
+ req.basic_auth(SETTINGS[:username], SETTINGS[:password])
155
123
  end
124
+ res.start { |http| http.request(req) }
125
+ rescue Exception => e
126
+ raise "Could not send facts to Foreman: #{e}"
156
127
  end
157
128
 
158
129
  def enc(minion)
@@ -176,7 +147,7 @@ def enc(minion)
176
147
  req.basic_auth(SETTINGS[:username], SETTINGS[:password])
177
148
  end
178
149
 
179
- res = http.start { |http| http.request(req) }
150
+ res = http.start { |conn| conn.request(req) }
180
151
 
181
152
  raise "Error retrieving node #{minion}: #{res.class}\nCheck Foreman's /var/log/foreman/production.log for more information." unless res.code == '200'
182
153
  res.body
@@ -198,7 +169,7 @@ begin
198
169
  result = enc(minion)
199
170
  end
200
171
  puts result
201
- rescue => e
172
+ rescue Exception => e
202
173
  puts "Couldn't retrieve ENC data: #{e}"
203
174
  exit 1
204
175
  end
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  gem 'smart_proxy_salt'
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'smart_proxy_salt/version'
2
4
  require 'smart_proxy_salt/salt'
@@ -1,44 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'net/http'
3
5
  require 'net/https'
4
6
  require 'uri'
5
7
 
6
- module Proxy::Salt
7
- class ApiError < RuntimeError; end
8
-
9
- class ApiRequest
10
- attr_reader :url, :username, :password, :auth
11
-
12
- def initialize
13
- @url = Proxy::Salt::Plugin.settings.api_url
14
- @auth = Proxy::Salt::Plugin.settings.api_auth
15
- @username = Proxy::Salt::Plugin.settings.api_username
16
- @password = Proxy::Salt::Plugin.settings.api_password
17
-
18
- begin
19
- URI.parse(url)
20
- rescue URI::InvalidURIError => e
21
- raise ConfigurationError.new("Invalid Salt api_url setting: #{e}")
8
+ module Proxy
9
+ module Salt
10
+ class ApiError < RuntimeError; end
11
+ class ConfigurationError < RuntimeError; end
12
+
13
+ # SaltStack's Rest API
14
+ class ApiRequest
15
+ attr_reader :url, :username, :password, :auth
16
+
17
+ def initialize
18
+ @url = Proxy::Salt::Plugin.settings.api_url
19
+ @auth = Proxy::Salt::Plugin.settings.api_auth
20
+ @username = Proxy::Salt::Plugin.settings.api_username
21
+ @password = Proxy::Salt::Plugin.settings.api_password
22
+
23
+ begin
24
+ URI.parse(url)
25
+ rescue URI::InvalidURIError => e
26
+ raise ConfigurationError.new("Invalid Salt api_url setting: #{e}")
27
+ end
22
28
  end
23
- end
24
29
 
25
- def post(path, options = {})
26
- uri = URI.parse(url)
27
- http = Net::HTTP.new(uri.host, uri.port)
28
- http.use_ssl = uri.scheme == 'https'
29
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
30
- path = [uri.path, path].join('/') unless uri.path.empty?
30
+ def post(path, options = {})
31
+ uri = URI.parse(url)
32
+ http = Net::HTTP.new(uri.host, uri.port)
33
+ http.use_ssl = uri.scheme == 'https'
34
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
35
+ path = [uri.path, path].join unless uri.path.empty?
36
+
37
+ request = Net::HTTP::Post.new(URI.join(uri.to_s, path).path)
38
+ request.add_field('Accept', 'application/json')
39
+ request.set_form_data(options.merge(:username => username, :password => password, :eauth => auth))
31
40
 
32
- request = Net::HTTP::Post.new(URI.join(uri.to_s, path).path)
33
- request.add_field('Accept', 'application/json')
34
- request.set_form_data(options.merge(:username => username, :password => password, :eauth => auth))
41
+ response = http.request(request)
35
42
 
36
- response = http.request(request)
43
+ raise NotFound.new("Received 404 from Salt API: #{response.body}") if response.is_a?(Net::HTTPNotFound)
44
+ raise ApiError.new("Failed to query Salt API (#{response.code}): #{response.body}") unless response.is_a?(Net::HTTPOK)
37
45
 
38
- if response.is_a? Net::HTTPOK
39
- JSON.load(response.body)
40
- else
41
- raise ApiError.new("Failed to query Salt API (#{response.code}): #{response.body}")
46
+ JSON.parse(response.body)
42
47
  end
43
48
  end
44
49
  end
@@ -1,163 +1,168 @@
1
- module Proxy::Salt::CLI
2
- extend ::Proxy::Log
3
- extend ::Proxy::Util
1
+ # frozen_string_literal: true
4
2
 
5
- class << self
6
- def autosign_file
7
- Proxy::Salt::Plugin.settings.autosign_file
8
- end
3
+ require 'English'
9
4
 
10
- def autosign_create(host)
11
- FileUtils.touch(autosign_file) unless File.exist?(autosign_file)
5
+ module Proxy
6
+ module Salt
7
+ # CLI methods
8
+ module CLI
9
+ extend ::Proxy::Log
10
+ extend ::Proxy::Util
12
11
 
13
- autosign = open(autosign_file, File::RDWR)
12
+ class << self
13
+ def autosign_file
14
+ Proxy::Salt::Plugin.settings.autosign_file
15
+ end
14
16
 
15
- found = false
16
- autosign.each_line { |line| found = true if line.chomp == host }
17
- autosign.puts host unless found
18
- autosign.close
17
+ def autosign_create(host)
18
+ FileUtils.touch(autosign_file) unless File.exist?(autosign_file)
19
19
 
20
- result = {:message => "Added #{host} to autosign"}
21
- logger.info result[:message]
22
- result
23
- end
20
+ autosign = open(autosign_file, File::RDWR)
24
21
 
25
- def autosign_remove(host)
26
- raise "No such file #{autosign_file}" unless File.exists?(autosign_file)
22
+ found = false
23
+ autosign.each_line { |line| found = true if line.chomp == host }
24
+ autosign.puts host unless found
25
+ autosign.close
27
26
 
28
- found = false
29
- entries = open(autosign_file, File::RDONLY).readlines.collect do |l|
30
- if l.chomp != host
31
- l
32
- else
33
- found = true
34
- nil
27
+ result = { :message => "Added #{host} to autosign" }
28
+ logger.info result[:message]
29
+ result
35
30
  end
36
- end.uniq.compact
37
- if found
38
- autosign = open(autosign_file, File::TRUNC|File::RDWR)
39
- autosign.write entries.join("\n")
40
- autosign.write "\n"
41
- autosign.close
42
- result = {:message => "Removed #{host} from autosign"}
43
- logger.info result[:message]
44
- result
45
- else
46
- logger.info "Attempt to remove nonexistant client autosign for #{host}"
47
- raise Proxy::Salt::NotFound, "Attempt to remove nonexistant client autosign for #{host}"
48
- end
49
- end
50
-
51
- def autosign_list
52
- return [] unless File.exist?(autosign_file)
53
- File.read(autosign_file).split("\n").reject { |v|
54
- v =~ /^\s*#.*|^$/ ## Remove comments and empty lines
55
- }.map { |v|
56
- v.chomp ## Strip trailing spaces
57
- }
58
- end
59
31
 
60
- def highstate(host)
61
- find_salt_binaries
62
- cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt, '--async', escape_for_shell(host), 'state.highstate']
63
- logger.info "Will run state.highstate for #{host}. Full command: #{cmd.join(' ')}"
64
- shell_command(cmd)
65
- end
66
-
67
- def key_delete(host)
68
- find_salt_binaries
69
- cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt_key, '--yes', '-d', escape_for_shell(host)]
70
- shell_command(cmd)
71
- end
72
-
73
- def key_reject(host)
74
- find_salt_binaries
75
- cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt_key, '--yes', '-r', escape_for_shell(host)]
76
- shell_command(cmd)
77
- end
32
+ def autosign_remove(host)
33
+ raise "No such file #{autosign_file}" unless File.exist?(autosign_file)
34
+
35
+ found = false
36
+ entries = open(autosign_file, File::RDONLY).readlines.collect do |l|
37
+ if l.chomp != host
38
+ l
39
+ else
40
+ found = true
41
+ nil
42
+ end
43
+ end.uniq.compact
44
+ if found
45
+ autosign = open(autosign_file, File::TRUNC | File::RDWR)
46
+ autosign.write entries.join("\n")
47
+ autosign.write "\n"
48
+ autosign.close
49
+ result = { :message => "Removed #{host} from autosign" }
50
+ logger.info result[:message]
51
+ result
52
+ else
53
+ logger.info "Attempt to remove nonexistant client autosign for #{host}"
54
+ raise Proxy::Salt::NotFound.new("Attempt to remove nonexistant client autosign for #{host}")
55
+ end
56
+ end
78
57
 
79
- def key_accept(host)
80
- find_salt_binaries
81
- cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt_key, '--yes', '-a', escape_for_shell(host)]
82
- shell_command(cmd)
83
- end
58
+ def autosign_list
59
+ return [] unless File.exist?(autosign_file)
60
+ File.read(autosign_file).split("\n").reject do |v|
61
+ v =~ /^\s*#.*|^$/ ## Remove comments and empty lines
62
+ end.map(&:chomp)
63
+ end
84
64
 
85
- def key_list
65
+ def highstate(host)
66
+ find_salt_binaries
67
+ cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt, '--async', escape_for_shell(host), 'state.highstate']
68
+ logger.info "Will run state.highstate for #{host}. Full command: #{cmd.join(' ')}"
69
+ shell_command(cmd)
70
+ end
86
71
 
87
- find_salt_binaries
88
- command = "#{@sudo} -u #{Proxy::Salt::Plugin.settings.salt_command_user} #{@salt_key} --finger-all --output=json"
89
- logger.debug "Executing #{command}"
90
- response = `#{command}`
91
- unless $? == 0
92
- logger.warn "Failed to run salt-key: #{response}"
93
- raise 'Execution of salt-key failed, check log files'
94
- end
72
+ def key_delete(host)
73
+ find_salt_binaries
74
+ cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt_key, '--yes', '-d', escape_for_shell(host)]
75
+ shell_command(cmd)
76
+ end
95
77
 
96
- keys_hash = {}
78
+ def key_reject(host)
79
+ find_salt_binaries
80
+ cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt_key, '--include-accepted', '--yes', '-r', escape_for_shell(host)]
81
+ shell_command(cmd)
82
+ end
97
83
 
98
- sk_hash = JSON.parse(response)
84
+ def key_accept(host)
85
+ find_salt_binaries
86
+ cmd = [@sudo, '-u', Proxy::Salt::Plugin.settings.salt_command_user, @salt_key, '--include-rejected', '--yes', '-a', escape_for_shell(host)]
87
+ shell_command(cmd)
88
+ end
99
89
 
100
- accepted_minions = sk_hash['minions']
101
- accepted_minions.keys.each { | accepted_minion | keys_hash[accepted_minion] = { 'state' => 'accepted', 'fingerprint' => accepted_minions[accepted_minion]} } if sk_hash.key? 'minions'
90
+ def key_list
91
+ find_salt_binaries
92
+ command = "#{@sudo} -u #{Proxy::Salt::Plugin.settings.salt_command_user} #{@salt_key} --finger-all --output=json"
93
+ logger.debug "Executing #{command}"
94
+ response = `#{command}`
95
+ unless $CHILD_STATUS == 0
96
+ logger.warn "Failed to run salt-key: #{response}"
97
+ raise 'Execution of salt-key failed, check log files'
98
+ end
102
99
 
103
- rejected_minions = sk_hash['minions_rejected']
104
- rejected_minions.keys.each { | rejected_minion | keys_hash[rejected_minion] = { 'state' => 'rejected', 'fingerprint' => rejected_minions[rejected_minion] } } if sk_hash.key? 'minions_rejected'
100
+ keys_hash = {}
105
101
 
106
- unaccepted_minions = sk_hash['minions_pre']
107
- unaccepted_minions.keys.each { | unaccepted_minion | keys_hash[unaccepted_minion] = { 'state' => 'unaccepted', 'fingerprint' => unaccepted_minions[unaccepted_minion] } } if sk_hash.key? 'minions_pre'
102
+ sk_hash = JSON.parse(response)
108
103
 
109
- keys_hash
104
+ accepted_minions = sk_hash['minions']
105
+ accepted_minions.each_key { |accepted_minion| keys_hash[accepted_minion] = { 'state' => 'accepted', 'fingerprint' => accepted_minions[accepted_minion] } } if sk_hash.key? 'minions'
110
106
 
111
- end
107
+ rejected_minions = sk_hash['minions_rejected']
108
+ rejected_minions.each_key { |rejected_minion| keys_hash[rejected_minion] = { 'state' => 'rejected', 'fingerprint' => rejected_minions[rejected_minion] } } if sk_hash.key? 'minions_rejected'
112
109
 
113
- private
110
+ unaccepted_minions = sk_hash['minions_pre']
111
+ unaccepted_minions.each_key { |unaccepted_minion| keys_hash[unaccepted_minion] = { 'state' => 'unaccepted', 'fingerprint' => unaccepted_minions[unaccepted_minion] } } if sk_hash.key? 'minions_pre'
114
112
 
115
- def shell_command(cmd, wait = true)
116
- begin
117
- c = popen(cmd)
118
- unless wait
119
- Process.detach(c.pid)
120
- return 0
113
+ keys_hash
121
114
  end
122
- Process.wait(c.pid)
123
- logger.info("Result: #{c.read}")
124
- rescue Exception => e
125
- logger.error("Exception '#{e}' when executing '#{cmd}'")
126
- return false
127
- end
128
- logger.warn("Non-null exit code when executing '#{cmd}'") if $?.exitstatus != 0
129
- $?.exitstatus == 0
130
- end
131
115
 
132
- def popen(cmd)
133
- # 1.8.7 note: this assumes that cli options are space-separated
134
- cmd = cmd.join(' ') unless RUBY_VERSION > '1.8.7'
135
- logger.debug("about to execute: #{cmd}")
136
- IO.popen(cmd)
137
- end
138
-
139
- def find_salt_binaries
140
- @salt_key = which('salt-key')
141
- unless File.exists?("#{@salt_key}")
142
- logger.warn 'unable to find salt-key binary'
143
- raise 'unable to find salt-key'
144
- end
145
- logger.debug "Found salt-key at #{@salt_key}"
116
+ private
117
+
118
+ def shell_command(cmd, wait = true)
119
+ begin
120
+ c = popen(cmd)
121
+ unless wait
122
+ Process.detach(c.pid)
123
+ return 0
124
+ end
125
+ Process.wait(c.pid)
126
+ logger.info("Result: #{c.read}")
127
+ rescue Exception => e
128
+ logger.error("Exception '#{e}' when executing '#{cmd}'")
129
+ return false
130
+ end
131
+ logger.warn("Non-null exit code when executing '#{cmd}'") unless $CHILD_STATUS.success?
132
+ $CHILD_STATUS.success?
133
+ end
146
134
 
147
- @salt = which('salt')
148
- unless File.exists?("#{@salt}")
149
- logger.warn 'unable to find salt binary'
150
- raise 'unable to find salt'
151
- end
152
- logger.debug "Found salt at #{@salt}"
135
+ def popen(cmd)
136
+ # 1.8.7 note: this assumes that cli options are space-separated
137
+ cmd = cmd.join(' ') unless RUBY_VERSION > '1.8.7'
138
+ logger.debug("about to execute: #{cmd}")
139
+ IO.popen(cmd)
140
+ end
153
141
 
154
- @sudo = which('sudo')
155
- unless File.exists?(@sudo)
156
- logger.warn 'unable to find sudo binary'
157
- raise 'Unable to find sudo'
142
+ def find_salt_binaries
143
+ @salt_key = which('salt-key')
144
+ unless File.exist?(@salt_key.to_s)
145
+ logger.warn 'unable to find salt-key binary'
146
+ raise 'unable to find salt-key'
147
+ end
148
+ logger.debug "Found salt-key at #{@salt_key}"
149
+
150
+ @salt = which('salt')
151
+ unless File.exist?(@salt.to_s)
152
+ logger.warn 'unable to find salt binary'
153
+ raise 'unable to find salt'
154
+ end
155
+ logger.debug "Found salt at #{@salt}"
156
+
157
+ @sudo = which('sudo')
158
+ unless File.exist?(@sudo)
159
+ logger.warn 'unable to find sudo binary'
160
+ raise 'Unable to find sudo'
161
+ end
162
+ logger.debug "Found sudo at #{@sudo}"
163
+ @sudo = @sudo.to_s
164
+ end
158
165
  end
159
- logger.debug "Found sudo at #{@sudo}"
160
- @sudo = "#{@sudo}"
161
166
  end
162
167
  end
163
168
  end