choria-mcorpc-support 2.23.0.pre → 2.24.0

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.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/lib/mcollective.rb +3 -3
  3. data/lib/mcollective/agent/bolt_tasks.ddl +18 -0
  4. data/lib/mcollective/agent/bolt_tasks.json +18 -0
  5. data/lib/mcollective/agent/bolt_tasks.rb +4 -2
  6. data/lib/mcollective/agent/rpcutil.ddl +2 -2
  7. data/lib/mcollective/agent/rpcutil.json +2 -2
  8. data/lib/mcollective/application/choria.rb +3 -63
  9. data/lib/mcollective/application/facts.rb +2 -67
  10. data/lib/mcollective/application/federation.rb +1 -3
  11. data/lib/mcollective/application/find.rb +1 -1
  12. data/lib/mcollective/application/ping.rb +31 -3
  13. data/lib/mcollective/application/plugin.rb +2 -15
  14. data/lib/mcollective/application/tasks.rb +9 -0
  15. data/lib/mcollective/client.rb +1 -1
  16. data/lib/mcollective/config.rb +135 -103
  17. data/lib/mcollective/discovery.rb +12 -65
  18. data/lib/mcollective/discovery/broadcast.ddl +11 -0
  19. data/lib/mcollective/discovery/choria.ddl +6 -4
  20. data/lib/mcollective/discovery/delegate.ddl +13 -0
  21. data/lib/mcollective/discovery/delegate.rb +73 -0
  22. data/lib/mcollective/discovery/external.ddl +13 -0
  23. data/lib/mcollective/discovery/file.ddl +13 -0
  24. data/lib/mcollective/discovery/flatfile.ddl +7 -5
  25. data/lib/mcollective/discovery/inventory.ddl +13 -0
  26. data/lib/mcollective/discovery/mc.ddl +3 -3
  27. data/lib/mcollective/message.rb +0 -24
  28. data/lib/mcollective/optionparser.rb +2 -2
  29. data/lib/mcollective/pluginpackager/forge_packager.rb +1 -1
  30. data/lib/mcollective/rpc/client.rb +6 -4
  31. data/lib/mcollective/security/base.rb +1 -37
  32. data/lib/mcollective/util.rb +23 -31
  33. data/lib/mcollective/util/choria.rb +0 -157
  34. data/lib/mcollective/util/tasks_support.rb +22 -3
  35. metadata +11 -29
  36. data/lib/mcollective/application/describe_filter.rb +0 -87
  37. data/lib/mcollective/data.rb +0 -96
  38. data/lib/mcollective/data/agent_data.ddl +0 -22
  39. data/lib/mcollective/data/agent_data.rb +0 -17
  40. data/lib/mcollective/data/base.rb +0 -68
  41. data/lib/mcollective/data/bolt_task_data.ddl +0 -90
  42. data/lib/mcollective/data/bolt_task_data.rb +0 -32
  43. data/lib/mcollective/data/collective_data.ddl +0 -20
  44. data/lib/mcollective/data/collective_data.rb +0 -9
  45. data/lib/mcollective/data/fact_data.ddl +0 -28
  46. data/lib/mcollective/data/fact_data.rb +0 -55
  47. data/lib/mcollective/data/fstat_data.ddl +0 -89
  48. data/lib/mcollective/data/fstat_data.rb +0 -54
  49. data/lib/mcollective/data/result.rb +0 -50
  50. data/lib/mcollective/ddl/dataddl.rb +0 -56
  51. data/lib/mcollective/discovery/choria.rb +0 -223
  52. data/lib/mcollective/discovery/flatfile.rb +0 -47
  53. data/lib/mcollective/discovery/stdin.ddl +0 -11
  54. data/lib/mcollective/discovery/stdin.rb +0 -67
  55. data/lib/mcollective/generators/data_generator.rb +0 -50
  56. data/lib/mcollective/generators/templates/data_input_snippet.erb +0 -7
  57. data/lib/mcollective/matcher.rb +0 -220
  58. data/lib/mcollective/matcher/parser.rb +0 -118
  59. data/lib/mcollective/matcher/scanner.rb +0 -236
@@ -0,0 +1,13 @@
1
+ metadata :name => "delegate",
2
+ :description => "Choria CLI based delegated discovery",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "Apache-2.0",
5
+ :version => "0.1",
6
+ :url => "https://choria.io/",
7
+ :timeout => 2
8
+
9
+ discovery do
10
+ capabilities [:classes, :facts, :identity, :agents, :compound]
11
+ end
12
+
13
+
@@ -0,0 +1,73 @@
1
+ module MCollective
2
+ class Discovery
3
+ class Delegate
4
+ def self.binary_name
5
+ "choria"
6
+ end
7
+
8
+ def self.discover(filter, timeout, limit, client)
9
+ raise("Cannot find the choria binary in your path") unless Util.command_in_path?("choria")
10
+
11
+ cmd = [binary_name, "discover", "-j", "--silent"]
12
+
13
+ cmd << "-T" << filter["collective"] if filter["collective"]
14
+
15
+ filter.fetch("identity", []).each do |i|
16
+ cmd << "-I" << i
17
+ end
18
+
19
+ filter.fetch("cf_class", []).each do |c|
20
+ cmd << "-C" << c
21
+ end
22
+
23
+ filter.fetch("fact", []).each do |f|
24
+ cmd << "-F" << "%s%s%s" % [f[:fact], f[:operator], f[:value]]
25
+ end
26
+
27
+ filter.fetch("agent", []).each do |a|
28
+ cmd << "-A" << a
29
+ end
30
+
31
+ filter.fetch("compound", []).each do |c|
32
+ next unless c.is_a?(Array)
33
+
34
+ cmd << "-S" << c.first["expr"]
35
+ end
36
+
37
+ client.options.fetch(:discovery_options, []).each do |opt|
38
+ cmd << "--do" << opt
39
+ end
40
+
41
+ cmd << "--dm" << (client.options.fetch(:discovery_method, "broadcast") rescue "broadcast")
42
+
43
+ run_discover(cmd, timeout)
44
+ end
45
+
46
+ def self.run_discover(cmd, timeout)
47
+ nodes = []
48
+
49
+ Log.debug("Executing choria for discovery using: %s" % cmd.join(" "))
50
+
51
+ Open3.popen3(ENV, *cmd) do |stdin, stdout, stderr, wait_thr|
52
+ stdin.close
53
+
54
+ begin
55
+ Timeout.timeout(timeout + 0.5) do
56
+ status = wait_thr.value
57
+
58
+ raise("Choria discovery failed: %s" % stderr.read) unless status.exitstatus == 0
59
+ end
60
+ rescue Timeout::Error
61
+ Log.warn("Timeout waiting for Choria to perform discovery")
62
+ Process.kill("KILL", wait_thr[:pid])
63
+ raise("Choria failed to complete discovery within %d timeout" % timeout)
64
+ end
65
+
66
+ nodes.concat(JSON.parse(stdout.read))
67
+ end
68
+
69
+ nodes
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,13 @@
1
+ metadata :name => "external",
2
+ :description => "External executable based discovery",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "Apache-2.0",
5
+ :version => "0.1",
6
+ :url => "https://choria.io/",
7
+ :timeout => 2
8
+
9
+ discovery do
10
+ capabilities [:classes, :facts, :identity, :agents, :compound]
11
+ end
12
+
13
+
@@ -0,0 +1,13 @@
1
+ metadata :name => "file",
2
+ :description => "Discovers from JSON, YAML and Text files",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "Apache-2.0",
5
+ :version => "0.1",
6
+ :url => "https://choria.io/",
7
+ :timeout => 2
8
+
9
+ discovery do
10
+ capabilities [:identity]
11
+ end
12
+
13
+
@@ -1,11 +1,13 @@
1
1
  metadata :name => "flatfile",
2
- :description => "Flatfile based discovery for node identities",
2
+ :description => "Discovers from JSON, YAML and Text files",
3
3
  :author => "R.I.Pienaar <rip@devco.net>",
4
- :license => "ASL 2.0",
4
+ :license => "Apache-2.0",
5
5
  :version => "0.1",
6
- :url => "https://docs.puppetlabs.com/mcollective/",
7
- :timeout => 0
6
+ :url => "https://choria.io/",
7
+ :timeout => 2
8
8
 
9
9
  discovery do
10
- capabilities :identity
10
+ capabilities [:identity]
11
11
  end
12
+
13
+
@@ -0,0 +1,13 @@
1
+ metadata :name => "delegate",
2
+ :description => "Choria CLI based delegated discovery",
3
+ :author => "R.I.Pienaar <rip@devco.net>",
4
+ :license => "Apache 2.0",
5
+ :version => "0.1",
6
+ :url => "https://choria.io/",
7
+ :timeout => 2
8
+
9
+ discovery do
10
+ capabilities [:classes, :facts, :identity, :agents, :compound]
11
+ end
12
+
13
+
@@ -1,9 +1,9 @@
1
1
  metadata :name => "mc",
2
- :description => "MCollective Broadcast based discovery",
2
+ :description => "Choria Broadcast based discovery",
3
3
  :author => "R.I.Pienaar <rip@devco.net>",
4
- :license => "ASL 2.0",
4
+ :license => "Apache-2.0",
5
5
  :version => "0.1",
6
- :url => "https://docs.puppetlabs.com/mcollective/",
6
+ :url => "https://choria.io",
7
7
  :timeout => 2
8
8
 
9
9
  discovery do
@@ -148,8 +148,6 @@ module MCollective
148
148
  @requestid = request.payload[:requestid]
149
149
  @payload = PluginManager["security_plugin"].encodereply(agent, payload, requestid, request.payload[:callerid])
150
150
  when :request, :direct_request
151
- validate_compound_filter(@filter["compound"]) unless @filter["compound"].empty?
152
-
153
151
  @requestid ||= create_reqid
154
152
  @payload = PluginManager["security_plugin"].encoderequest(Config.instance.identity, payload, requestid, filter, agent, collective, ttl)
155
153
  else
@@ -157,28 +155,6 @@ module MCollective
157
155
  end
158
156
  end
159
157
 
160
- def validate_compound_filter(compound_filter)
161
- compound_filter.each do |filter|
162
- filter.each do |statement|
163
- next unless statement["fstatement"]
164
-
165
- functionname = statement["fstatement"]["name"]
166
- pluginname = Data.pluginname(functionname)
167
- value = statement["fstatement"]["value"]
168
-
169
- ddl = DDL.new(pluginname, :data)
170
-
171
- # parses numbers and booleans entered as strings into proper
172
- # types of data so that DDL validation will pass
173
- statement["fstatement"]["params"] = Data.ddl_transform_input(ddl, statement["fstatement"]["params"])
174
-
175
- Data.ddl_validate(ddl, statement["fstatement"]["params"])
176
-
177
- raise(DDLValidationError, "Data plugin '%s()' does not return a '%s' value" % [functionname, value]) unless value && Data.ddl_has_output?(ddl, value)
178
- end
179
- end
180
- end
181
-
182
158
  def decode!
183
159
  raise "Cannot decode message type #{type}" unless [:request, :reply].include?(type)
184
160
 
@@ -86,7 +86,7 @@ module MCollective
86
86
  end
87
87
 
88
88
  @parser.on("-S", "--select FILTER", "Compound filter combining facts and classes") do |f|
89
- @options[:filter]["compound"] << Matcher.create_compound_callstack(f)
89
+ @options[:filter]["compound"] << [{"expr" => f}]
90
90
  end
91
91
 
92
92
  @parser.on("-F", "--wf", "--with-fact fact=val", "Match hosts with a certain fact") do |f|
@@ -168,7 +168,7 @@ module MCollective
168
168
  raise "Cannot read the discovery file #{v}" unless File.readable?(v)
169
169
 
170
170
  @options[:discovery_method] = "flatfile"
171
- @options[:discovery_options] << v
171
+ @options[:discovery_options] << "file=%s" % v
172
172
  end
173
173
 
174
174
  @parser.on("--publish_timeout TIMEOUT", Integer, "Timeout for publishing requests to remote agents.") do |pt|
@@ -191,7 +191,7 @@ module MCollective
191
191
  end
192
192
 
193
193
  def render_template(infile, outfile)
194
- erb = ERB.new(File.read(infile), 0, "%")
194
+ erb = ERB.new(File.read(infile), 0, "-")
195
195
  File.open(outfile, "w") do |f|
196
196
  f.puts erb.result(binding)
197
197
  end
@@ -442,7 +442,7 @@ module MCollective
442
442
 
443
443
  # Set a compound filter
444
444
  def compound_filter(filter)
445
- @filter["compound"] = @filter["compound"] | [Matcher.create_compound_callstack(filter)]
445
+ @filter["compound"] = @filter["compound"] | [[{"expr" => filter}]]
446
446
  reset
447
447
  end
448
448
 
@@ -533,6 +533,8 @@ module MCollective
533
533
 
534
534
  # All else fails we do it the hard way using a traditional broadcast
535
535
  unless @discovered_agents
536
+ raise("Invalid discovery method %s" % discovery_method) unless @client.discoverer.find_known_methods.include?(discovery_method)
537
+
536
538
  @stats.time_discovery :start
537
539
 
538
540
  @client.options = options
@@ -548,9 +550,9 @@ module MCollective
548
550
  actual_timeout = @client.discoverer.discovery_timeout(discovery_timeout, options[:filter])
549
551
 
550
552
  if actual_timeout > 0
551
- @stderr.print("Discovering hosts using the %s method for %d second(s) .... " % [@client.discoverer.discovery_method, actual_timeout])
553
+ @stderr.print("Discovering hosts using the %s method for %d second(s) .... " % [discovery_method, actual_timeout])
552
554
  else
553
- @stderr.print("Discovering hosts using the %s method .... " % [@client.discoverer.discovery_method])
555
+ @stderr.print("Discovering hosts using the %s method .... " % discovery_method)
554
556
  end
555
557
  end
556
558
 
@@ -822,7 +824,7 @@ module MCollective
822
824
  @stdout.print twirl.twirl(respcount, discovered.size)
823
825
  end
824
826
 
825
- if batch_size =~ /^(\d+)%$/
827
+ if batch_size.is_a?(String) && batch_size =~ /^(\d+)%$/
826
828
  # determine batch_size as a percentage of the discovered array's size
827
829
  batch_size = (discovered.size / 100.0 * Integer($1)).ceil
828
830
  else
@@ -72,43 +72,7 @@ module MCollective
72
72
  end
73
73
 
74
74
  when "compound"
75
- filter[key].each do |compound|
76
- result = false
77
- truth_values = []
78
-
79
- begin
80
- compound.each do |expression|
81
- case expression.keys.first
82
- when "statement"
83
- truth_values << Matcher.eval_compound_statement(expression).to_s
84
- when "fstatement"
85
- truth_values << Matcher.eval_compound_fstatement(expression.values.first)
86
- when "and"
87
- truth_values << "&&"
88
- when "or"
89
- truth_values << "||"
90
- when "("
91
- truth_values << "("
92
- when ")"
93
- truth_values << ")"
94
- when "not"
95
- truth_values << "!"
96
- end
97
- end
98
-
99
- result = eval(truth_values.join(" ")) # rubocop:disable Security/Eval
100
- rescue DDLValidationError
101
- result = false
102
- end
103
-
104
- if result
105
- Log.debug("Passing based on class and fact composition")
106
- passed += 1
107
- else
108
- Log.debug("Failing based on class and fact composition")
109
- failed += 1
110
- end
111
- end
75
+ # removed while rebuilding compound filters, this whole method is probably unused now
112
76
 
113
77
  when "agent"
114
78
  filter[key].each do |f|
@@ -156,19 +156,23 @@ module MCollective
156
156
  File.join(Dir::COMMON_APPDATA, "ChoriaIO", "choria")
157
157
  end
158
158
 
159
- def self.mcollective_config_paths_for_user
159
+ def self.config_paths_for_user
160
160
  config_paths = []
161
161
 
162
- begin
163
- # File.expand_path will raise if HOME isn't set, catch it
164
- user_path = File.expand_path("~/.mcollective")
165
- config_paths << user_path
166
- rescue Exception # rubocop:disable Lint/RescueException, Lint/SuppressedException
162
+ ["~/.choriarc", "~/.mcollective"].each do |f|
163
+ begin
164
+ # File.expand_path will raise if HOME isn't set, catch it
165
+ config_paths << File.expand_path(f)
166
+ rescue ArgumentError # rubocop:disable Lint/SuppressedException
167
+ end
167
168
  end
168
169
 
169
170
  if windows?
171
+ config_paths << File.join(choria_windows_prefix, "etc", "client.conf")
170
172
  config_paths << File.join(windows_prefix, "etc", "client.cfg")
171
173
  else
174
+ config_paths << "/etc/choria/client.conf"
175
+ config_paths << "/usr/local/etc/choria/client.conf"
172
176
  config_paths << "/etc/puppetlabs/mcollective/client.cfg"
173
177
  config_paths << "/etc/mcollective/client.cfg"
174
178
  config_paths << "/usr/local/etc/mcollective/client.cfg"
@@ -177,42 +181,30 @@ module MCollective
177
181
  config_paths
178
182
  end
179
183
 
180
- def self.choria_config_paths_for_user
181
- config_paths = []
182
-
183
- begin
184
- # File.expand_path will raise if HOME isn't set, catch it
185
- user_path = File.expand_path("~/.choriarc")
186
- config_paths << user_path
187
- rescue Exception # rubocop:disable Lint/RescueException, Lint/SuppressedException
188
- end
189
-
190
- if windows?
191
- config_paths << File.join(choria_windows_prefix, "etc", "client.conf")
192
- else
193
- config_paths << "/etc/choria/client.conf"
194
- config_paths << "/usr/local/etc/choria/client.conf"
195
- end
196
-
197
- config_paths
198
- end
199
-
200
184
  # Picks the default user config file, priorities are first Choria ones then old MCollective ones
201
185
  #
202
186
  # In roughly this order, first to exist is used:
203
187
  #
204
188
  # - ~/.choriarc
205
- # - APPData/ChoriaIO/choria/etc/client.conf on windows
206
- # - /etc/choria/client.conf then
207
- # - /usr/local/etc/choria/client.conf on unix
208
189
  # - ~/.mcollective
209
- # - APPData/PuppetLabs/mcollective/etc/client.cfg on windows
190
+ #
191
+ # On Unix:
192
+ #
193
+ # - /etc/choria/client.conf
194
+ # - /usr/local/etc/choria/client.conf
210
195
  # - /etc/puppetlabs/mcollective/client.cfg
211
196
  # - /etc/mcollective/client.cfg
212
197
  # - /usr/local/etc/mcollective/client.cfg
198
+ #
199
+ # On Windows:
200
+ #
201
+ # - APPData/ChoriaIO/choria/etc/client.conf on windows
202
+ # - APPData/PuppetLabs/mcollective/etc/client.cfg on windows
213
203
  def self.config_file_for_user
214
- config_paths = choria_config_paths_for_user + mcollective_config_paths_for_user
204
+ config_paths = config_paths_for_user
205
+
215
206
  found = config_paths.find_index { |file| File.readable?(file) } || 0
207
+
216
208
  config_paths[found]
217
209
  end
218
210
 
@@ -86,14 +86,6 @@ module MCollective
86
86
  end
87
87
  end
88
88
 
89
- # Which port to provide stats over HTTP on
90
- #
91
- # @return [Integer,nil]
92
- # @raise [StandardError] when not numeric
93
- def stats_port
94
- Integer(get_option("choria.stats_port", "")) if has_option?("choria.stats_port")
95
- end
96
-
97
89
  # Determines if there are any federations configured
98
90
  #
99
91
  # @return [Boolean]
@@ -888,15 +880,6 @@ module MCollective
888
880
  File.exist?(csr_path)
889
881
  end
890
882
 
891
- # The formatted string representation of the CSR fingerprint
892
- #
893
- # @return [String]
894
- def csr_fingerprint
895
- require "puppet"
896
- csr = OpenSSL::X509::Request.new(File.read(csr_path))
897
- Puppet::SSL::Digest.new(nil, csr.to_der)
898
- end
899
-
900
883
  # Searches the PATH for an executable command
901
884
  #
902
885
  # @param command [String] a command to search for
@@ -927,146 +910,6 @@ module MCollective
927
910
  which("facter")
928
911
  end
929
912
 
930
- # Creates any missing SSL directories
931
- #
932
- # This prepares a Puppet like SSL tree in case Puppet
933
- # has not been initialized yet
934
- #
935
- # @return [void]
936
- def make_ssl_dirs
937
- return if file_security?
938
-
939
- FileUtils.mkdir_p(ssl_dir, :mode => 0o0771)
940
-
941
- ["certificate_requests", "certs", "public_keys"].each do |dir|
942
- FileUtils.mkdir_p(File.join(ssl_dir, dir), :mode => 0o0755)
943
- end
944
-
945
- ["private_keys", "private"].each do |dir|
946
- FileUtils.mkdir_p(File.join(ssl_dir, dir), :mode => 0o0750)
947
- end
948
- end
949
-
950
- # Creates a RSA key of a certain strenth
951
- #
952
- # @return [OpenSSL::PKey::RSA]
953
- def create_rsa_key(bits)
954
- OpenSSL::PKey::RSA.new(bits)
955
- end
956
-
957
- # Writes a new 4096 bit key in the puppet default locatioj
958
- #
959
- # @return [OpenSSL::PKey::RSA]
960
- # @raise [StandardError] when the key already exist
961
- def write_key
962
- raise("Refusing to overwrite existing key in %s" % client_private_key) if has_client_private_key?
963
-
964
- key = create_rsa_key(4096)
965
- File.open(client_private_key, "w", 0o0640) {|f| f.write(key.to_pem)}
966
-
967
- key
968
- end
969
-
970
- # Creates a basic CSR
971
- #
972
- # @return [OpenSSL::X509::Request] signed CSR
973
- def create_csr(comonname, orgunit, key)
974
- csr = OpenSSL::X509::Request.new
975
- csr.version = 0
976
- csr.public_key = key.public_key
977
- csr.subject = OpenSSL::X509::Name.new(
978
- [
979
- ["CN", comonname, OpenSSL::ASN1::UTF8STRING],
980
- ["OU", orgunit, OpenSSL::ASN1::UTF8STRING]
981
- ]
982
- )
983
- csr.sign(key, OpenSSL::Digest.new("SHA1"))
984
-
985
- csr
986
- end
987
-
988
- # Creates a new CSR signed by the given key
989
- #
990
- # @param key [OpenSSL::PKey::RSA]
991
- # @return [String] PEM encoded CSR
992
- def write_csr(key)
993
- raise("Refusing to overwrite existing CSR in %s" % csr_path) if has_csr?
994
-
995
- csr = create_csr(certname, "mcollective", key)
996
-
997
- File.open(csr_path, "w", 0o0644) {|f| f.write(csr.to_pem)}
998
-
999
- csr.to_pem
1000
- end
1001
-
1002
- # Fetch and save the CA from Puppet
1003
- #
1004
- # @return [Boolean]
1005
- def fetch_ca
1006
- return true if has_ca?
1007
-
1008
- server = puppetca_server
1009
-
1010
- req = http_get("/puppet-ca/v1/certificate/ca?environment=production", "Accept" => "text/plain")
1011
- resp, _ = https(server).request(req)
1012
-
1013
- if resp.code == "200"
1014
- File.open(ca_path, "w", 0o0644) {|f| f.write(resp.body)}
1015
- else
1016
- raise(UserError, "Failed to fetch CA from %s:%s: %s: %s" % [server[:target], server[:port], resp.code, resp.message])
1017
- end
1018
-
1019
- has_ca?
1020
- end
1021
-
1022
- # Requests a certificate from the Puppet CA
1023
- #
1024
- # This will attempt to create a new key, write a CSR and
1025
- # then sends it to the CA for signing
1026
- #
1027
- # @return [Boolean]
1028
- # @raise [UserError] when requesting the cert fails
1029
- def request_cert
1030
- key = write_key
1031
- csr = write_csr(key)
1032
-
1033
- server = puppetca_server
1034
-
1035
- req = Net::HTTP::Put.new("/puppet-ca/v1/certificate_request/%s?environment=production" % certname, "Content-Type" => "text/plain")
1036
- req.body = csr
1037
- resp, _ = https(server).request(req)
1038
-
1039
- if resp.code == "200"
1040
- true
1041
- else
1042
- raise(UserError, "Failed to request certificate from %s:%s: %s: %s: %s" % [server[:target], server[:port], resp.code, resp.message, resp.body])
1043
- end
1044
- end
1045
-
1046
- # Attempts to fetch a cert from the CA
1047
- #
1048
- # @return [Boolean]
1049
- def attempt_fetch_cert
1050
- return true if has_client_public_cert?
1051
-
1052
- req = http_get("/puppet-ca/v1/certificate/%s?environment=production" % certname, "Accept" => "text/plain")
1053
- resp, _ = https(puppetca_server).request(req)
1054
-
1055
- if resp.code == "200"
1056
- File.open(client_public_cert, "w", 0o0644) {|f| f.write(resp.body)}
1057
- true
1058
- else
1059
- false
1060
- end
1061
- end
1062
-
1063
- # Determines if a CSR has been sent but not yet retrieved
1064
- #
1065
- # @return [Boolean]
1066
- def waiting_for_cert?
1067
- !has_client_public_cert? && has_client_private_key?
1068
- end
1069
-
1070
913
  # Gets a config option
1071
914
  #
1072
915
  # @param opt [String] config option to look up