chef_handler_foreman 0.0.1
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 +7 -0
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +1 -0
- data/chef_handler_foreman.gemspec +23 -0
- data/lib/chef_handler_foreman.rb +5 -0
- data/lib/chef_handler_foreman/foreman_facts.rb +75 -0
- data/lib/chef_handler_foreman/foreman_hooks.rb +45 -0
- data/lib/chef_handler_foreman/foreman_reporting.rb +90 -0
- data/lib/chef_handler_foreman/foreman_resource_reporter.rb +155 -0
- data/lib/chef_handler_foreman/foreman_uploader.rb +64 -0
- data/lib/chef_handler_foreman/version.rb +3 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5f732d147f13678919bd92180c402f03a1557cd3
|
4
|
+
data.tar.gz: 5fb453eeffa51588e2931ea9ebd9ee4d24075902
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 34dd72612b5e564bddd19caea1f5cacedc4ad98c111787185940737f665b0faa6a41684eb5e734eebbc0b1fb149581e6cffa694530ba5242383cda7b00ee2c08
|
7
|
+
data.tar.gz: a50c75a58979130d250e2ddaf97073458937649099e73ea6307695e4f58031f33ea3011e087b0d016a1a79e003d8bdbd0aa23fe0627d5d8776df7719065c1ac7
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Marek Hulan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
This gem adds Chef report and attributes handlers that send reports to TheForeman Project.
|
4
|
+
You need Foreman 1.3+ to use it.
|
5
|
+
See: http://www.theforeman.org
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
|
10
|
+
Since it's released as a gem you can simply run
|
11
|
+
```sh
|
12
|
+
# gem install chef_foreman_handler
|
13
|
+
```
|
14
|
+
## Usage:
|
15
|
+
|
16
|
+
In /etc/chef/config.rb:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# this adds new functions to chef configuration
|
20
|
+
require 'chef_handler_foreman'
|
21
|
+
# here you can specify your connection options
|
22
|
+
foreman_server_options :url => 'http://your.server/foreman'
|
23
|
+
# add following line if you want to upload node attributes (facts in Foreman language)
|
24
|
+
foreman_facts_upload true
|
25
|
+
# add following line if you want to upload reports
|
26
|
+
foreman_reports_upload true
|
27
|
+
```
|
28
|
+
|
29
|
+
You can also specify a second argument to foreman_reports_upload which is a number:
|
30
|
+
- 1 (default) for reporter based on more detailed ResourceReporter
|
31
|
+
- 2 not so verbose based just on run_status, actually just counts applied resources
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'chef_handler_foreman/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "chef_handler_foreman"
|
8
|
+
spec.version = ChefHandlerForeman::VERSION
|
9
|
+
spec.authors = ["Marek Hulan"]
|
10
|
+
spec.email = ["mhulan@redhat.com"]
|
11
|
+
spec.description = %q{Chef handlers to integrate with foreman}
|
12
|
+
spec.summary = %q{This gem adds chef handlers so your chef-client can upload attributes (facts) and reports to Foreman}
|
13
|
+
spec.homepage = "https://github.com/theforeman/chef-handler-foreman"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#This program is free software: you can redistribute it and/or modify
|
2
|
+
#it under the terms of the GNU General Public License as published by
|
3
|
+
#the Free Software Foundation, either version 3 of the License, or
|
4
|
+
#(at your option) any later version.
|
5
|
+
#
|
6
|
+
#This program is distributed in the hope that it will be useful,
|
7
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
8
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
9
|
+
#GNU General Public License for more details.
|
10
|
+
#
|
11
|
+
#You should have received a copy of the GNU General Public License
|
12
|
+
#along with this program. If not, see <http://www.gnu.org/licenses/>
|
13
|
+
|
14
|
+
require 'chef/handler'
|
15
|
+
|
16
|
+
module ChefHandlerForeman
|
17
|
+
class ForemanFacts < Chef::Handler
|
18
|
+
attr_accessor :uploader
|
19
|
+
|
20
|
+
def report
|
21
|
+
send_attributes(prepare_facts)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def prepare_facts
|
27
|
+
{ :name => node.name,
|
28
|
+
:facts => plain_attributes.merge({
|
29
|
+
:operatingsystem => node.lsb[:id],
|
30
|
+
:operatingsystemrelease => node.lsb.release,
|
31
|
+
:_timestamp => Time.now,
|
32
|
+
:_type => 'foreman_chef'
|
33
|
+
})
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def plain_attributes
|
38
|
+
plainify(node.attributes.to_hash).flatten.inject(&:merge)
|
39
|
+
end
|
40
|
+
|
41
|
+
def plainify(hash, prefix = nil)
|
42
|
+
result = []
|
43
|
+
hash.each_pair do |key, value|
|
44
|
+
if value.is_a?(Hash)
|
45
|
+
result.push plainify(value, get_key(key, prefix))
|
46
|
+
elsif value.is_a?(Array)
|
47
|
+
result.push plainify(array_to_hash(value), get_key(key, prefix))
|
48
|
+
else
|
49
|
+
new = {}
|
50
|
+
new[get_key(key, prefix)] = value
|
51
|
+
result.push new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
def array_to_hash(array)
|
58
|
+
new = {}
|
59
|
+
array.each_with_index { |v, index| new[index.to_s] = v }
|
60
|
+
new
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_key(key, prefix)
|
64
|
+
[prefix, key].compact.join('::')
|
65
|
+
end
|
66
|
+
|
67
|
+
def send_attributes(attributes)
|
68
|
+
if uploader
|
69
|
+
uploader.foreman_request('/api/hosts/facts', attributes, node.name)
|
70
|
+
else
|
71
|
+
Chef::Log.error "No uploader registered for foreman facts, skipping facts upload"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'chef_handler_foreman/foreman_facts'
|
2
|
+
require 'chef_handler_foreman/foreman_reporting'
|
3
|
+
require 'chef_handler_foreman/foreman_resource_reporter'
|
4
|
+
require 'chef_handler_foreman/foreman_uploader'
|
5
|
+
|
6
|
+
module ChefHandlerForeman
|
7
|
+
module ForemanHooks
|
8
|
+
# {:url => '', ...}
|
9
|
+
def foreman_server_options(options)
|
10
|
+
{ :client_key => client_key || '/etc/chef/client.pem' }.merge(options)
|
11
|
+
@foreman_uploader = ForemanUploader.new(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def foreman_facts_upload(upload)
|
15
|
+
if upload
|
16
|
+
foreman_facts_handler = ForemanFacts.new
|
17
|
+
foreman_facts_handler.uploader = @foreman_uploader
|
18
|
+
report_handlers << foreman_facts_handler
|
19
|
+
exception_handlers << foreman_facts_handler
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def foreman_reports_upload(upload, mode = 1)
|
24
|
+
if upload
|
25
|
+
case mode
|
26
|
+
when 1
|
27
|
+
foreman_reporter = ForemanResourceReporter.new(nil)
|
28
|
+
foreman_reporter.uploader = @foreman_uploader
|
29
|
+
if Chef::Config[:event_handlers].is_a?(Array)
|
30
|
+
Chef::Config[:event_handlers].push foreman_reporter
|
31
|
+
else
|
32
|
+
Chef::Config[:event_handlers] = [foreman_reporter]
|
33
|
+
end
|
34
|
+
when 2
|
35
|
+
foreman_handler = ForemanReporting.new
|
36
|
+
foreman_handler.uploader = uploader
|
37
|
+
report_handlers << foreman_handler
|
38
|
+
exception_handlers << foreman_handler
|
39
|
+
else
|
40
|
+
raise ArgumentError, 'unknown mode: ' + mode.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#This program is free software: you can redistribute it and/or modify
|
2
|
+
#it under the terms of the GNU General Public License as published by
|
3
|
+
#the Free Software Foundation, either version 3 of the License, or
|
4
|
+
#(at your option) any later version.
|
5
|
+
#
|
6
|
+
#This program is distributed in the hope that it will be useful,
|
7
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
8
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
9
|
+
#GNU General Public License for more details.
|
10
|
+
#
|
11
|
+
#You should have received a copy of the GNU General Public License
|
12
|
+
#along with this program. If not, see <http://www.gnu.org/licenses/>
|
13
|
+
|
14
|
+
require 'chef/handler'
|
15
|
+
|
16
|
+
module ChefHandlerForeman
|
17
|
+
class ForemanReporting < ::Chef::Handler
|
18
|
+
attr_accessor :uploader
|
19
|
+
|
20
|
+
def report
|
21
|
+
report = { 'host' => node.fqdn, 'reported_at' => Time.now.utc.to_s }
|
22
|
+
report_status = Hash.new(0)
|
23
|
+
|
24
|
+
|
25
|
+
report_status['failed'] = 1 if failed?
|
26
|
+
report_status['applied'] = run_status.updated_resources.count
|
27
|
+
report['status'] = report_status
|
28
|
+
|
29
|
+
# I can't compute much metrics for now
|
30
|
+
metrics = {}
|
31
|
+
metrics['resources'] = { 'total' => run_status.all_resources.count }
|
32
|
+
|
33
|
+
times = {}
|
34
|
+
run_status.all_resources.each do |resource|
|
35
|
+
resource_name = resource.resource_name
|
36
|
+
if times[resource_name].nil?
|
37
|
+
times[resource_name] = resource.elapsed_time
|
38
|
+
else
|
39
|
+
times[resource_name] += resource.elapsed_time
|
40
|
+
end
|
41
|
+
end
|
42
|
+
metrics['time'] = times.merge!({ 'total' => run_status.elapsed_time })
|
43
|
+
report['metrics'] = metrics
|
44
|
+
|
45
|
+
logs = []
|
46
|
+
run_status.updated_resources.each do |resource|
|
47
|
+
l = { 'log' => { 'sources' => {}, 'messages' => {}, 'level' => 'notice' } }
|
48
|
+
|
49
|
+
case resource.resource_name.to_s
|
50
|
+
when 'template', 'cookbook_file'
|
51
|
+
message = resource.diff
|
52
|
+
when 'package'
|
53
|
+
message = "Installed #{resource.package_name} package in #{resource.version}"
|
54
|
+
else
|
55
|
+
message = resource.action.to_s
|
56
|
+
end
|
57
|
+
l['log']['messages']['message'] = message
|
58
|
+
l['log']['sources']['source'] = [resource.resource_name.to_s, resource.name].join(' ')
|
59
|
+
#Chef::Log.info("Diff is #{l['log']['messages']['message']}")
|
60
|
+
logs << l
|
61
|
+
end
|
62
|
+
|
63
|
+
# I only set failed to 1 if chef run failed
|
64
|
+
if failed?
|
65
|
+
logs << {
|
66
|
+
'log' => {
|
67
|
+
'sources' => { 'source' => 'chef' },
|
68
|
+
'messages' => { 'message' => run_status.exception },
|
69
|
+
'level' => 'err' }
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
report['logs'] = logs
|
74
|
+
full_report = { 'report' => report }
|
75
|
+
|
76
|
+
send_report(full_report)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def send_report(report)
|
82
|
+
if uploader
|
83
|
+
uploader.foreman_request('/api/reports', report, node.name)
|
84
|
+
else
|
85
|
+
Chef::Log.error "No uploader registered for foreman reporting, skipping report upload"
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module ChefHandlerForeman
|
2
|
+
class ForemanResourceReporter < ::Chef::ResourceReporter
|
3
|
+
attr_accessor :uploader
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
@total_up_to_date = 0
|
7
|
+
@total_skipped = 0
|
8
|
+
@total_updated = 0
|
9
|
+
@total_failed = 0
|
10
|
+
@total_restarted = 0
|
11
|
+
@total_failed_restart = 0
|
12
|
+
@all_resources = []
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_started(run_status)
|
17
|
+
@run_status = run_status
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_completed(node)
|
21
|
+
@status = "success"
|
22
|
+
post_reporting_data
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_failed(exception)
|
26
|
+
@exception = exception
|
27
|
+
@status = "failure"
|
28
|
+
# If we failed before we received the run_started callback, there's not much we can do
|
29
|
+
# in terms of reporting
|
30
|
+
if @run_status
|
31
|
+
post_reporting_data
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource_current_state_loaded(new_resource, action, current_resource)
|
36
|
+
super
|
37
|
+
@all_resources.push @pending_update unless @pending_update.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def resource_up_to_date(new_resource, action)
|
42
|
+
@total_up_to_date += 1
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def resource_skipped(resource, action, conditional)
|
47
|
+
@total_skipped += 1
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def resource_updated(new_resource, action)
|
52
|
+
@total_updated += 1
|
53
|
+
@total_restarted += 1 if action.to_s == 'restart'
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
def resource_failed(new_resource, action, exception)
|
58
|
+
@total_failed += 1
|
59
|
+
@total_failed_restart += 1 if action.to_s == 'restart'
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
def resource_completed(new_resource)
|
64
|
+
if @pending_update && !nested_resource?(new_resource)
|
65
|
+
@pending_update.finish
|
66
|
+
@updated_resources << @pending_update
|
67
|
+
@pending_update = nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def post_reporting_data
|
72
|
+
if reporting_enabled?
|
73
|
+
run_data = prepare_run_data
|
74
|
+
Chef::Log.info("Sending resource update report to foreman (run-id: #{@run_id})")
|
75
|
+
Chef::Log.debug run_data.inspect
|
76
|
+
begin
|
77
|
+
Chef::Log.debug("Sending data...")
|
78
|
+
if uploader
|
79
|
+
uploader.foreman_request('/api/reports', { "report" => run_data }, node.name)
|
80
|
+
else
|
81
|
+
Chef::Log.error "No uploader registered for foreman reporting, skipping report upload"
|
82
|
+
end
|
83
|
+
rescue => e
|
84
|
+
Chef::Log.error "Sending failed with #{e.class} #{e.message}"
|
85
|
+
Chef::Log.error e.backtrace.join("\n")
|
86
|
+
end
|
87
|
+
else
|
88
|
+
Chef::Log.debug("Reporting disabled, skipping report upload")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def prepare_run_data
|
93
|
+
run_data = {}
|
94
|
+
run_data["host"] = node_name
|
95
|
+
run_data["reported_at"] = end_time.to_s
|
96
|
+
run_data["status"] = resources_per_status
|
97
|
+
|
98
|
+
run_data["metrics"] = {
|
99
|
+
"resources" => { "total" => @total_res_count },
|
100
|
+
"time" => resources_per_time
|
101
|
+
}
|
102
|
+
|
103
|
+
run_data["logs"] = resources_logs + [chef_log]
|
104
|
+
run_data
|
105
|
+
end
|
106
|
+
|
107
|
+
def resources_per_status
|
108
|
+
{ "applied" => @total_updated,
|
109
|
+
"restarted" => @total_restarted,
|
110
|
+
"failed" => @total_failed,
|
111
|
+
"failed_restarts" => @total_failed_restart,
|
112
|
+
"skipped" => @total_skipped,
|
113
|
+
"pending" => 0
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def resources_per_time
|
118
|
+
@run_status.all_resources.inject({}) do |memo, resource|
|
119
|
+
name, time = resource.resource_name.to_s, resource.elapsed_time || 0
|
120
|
+
memo[name] = memo[name] ? memo[name] + time : time
|
121
|
+
memo
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def resources_logs
|
126
|
+
@all_resources.map do |resource|
|
127
|
+
action = resource.new_resource.action
|
128
|
+
message = action.is_a?(Array) ? action.first.to_s : action.to_s
|
129
|
+
message += " (#{resource.exception.class} #{resource.exception.message})" unless resource.exception.nil?
|
130
|
+
{ "log" => {
|
131
|
+
"sources" => { "source" => resource.new_resource.to_s },
|
132
|
+
"messages" => { "message" => message },
|
133
|
+
"level" => resource.exception.nil? ? "notice" : 'err'
|
134
|
+
} }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def chef_log
|
139
|
+
message = 'run'
|
140
|
+
if @status == 'success' && exception.nil?
|
141
|
+
level = 'notice'
|
142
|
+
else
|
143
|
+
message += " (#{exception.class} #{exception.message})"
|
144
|
+
level = 'err'
|
145
|
+
end
|
146
|
+
|
147
|
+
{ "log" => {
|
148
|
+
"sources" => { "source" => 'Chef' },
|
149
|
+
"messages" => { "message" => message },
|
150
|
+
"level" => level
|
151
|
+
} }
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#This program is free software: you can redistribute it and/or modify
|
2
|
+
#it under the terms of the GNU General Public License as published by
|
3
|
+
#the Free Software Foundation, either version 3 of the License, or
|
4
|
+
#(at your option) any later version.
|
5
|
+
#
|
6
|
+
#This program is distributed in the hope that it will be useful,
|
7
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
8
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
9
|
+
#GNU General Public License for more details.
|
10
|
+
#
|
11
|
+
#You should have received a copy of the GNU General Public License
|
12
|
+
#along with this program. If not, see <http://www.gnu.org/licenses/>
|
13
|
+
|
14
|
+
require 'net/http'
|
15
|
+
require 'net/https'
|
16
|
+
require 'uri'
|
17
|
+
require 'openssl'
|
18
|
+
require 'digest/sha2'
|
19
|
+
require 'base64'
|
20
|
+
|
21
|
+
module ChefHandlerForeman
|
22
|
+
class ForemanUploader
|
23
|
+
attr_reader :options
|
24
|
+
|
25
|
+
def initialize(opts)
|
26
|
+
@options = opts
|
27
|
+
end
|
28
|
+
|
29
|
+
def foreman_request(path, body, client_name)
|
30
|
+
uri = URI.parse(options[:url])
|
31
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
32
|
+
http.use_ssl = uri.scheme == 'https'
|
33
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
34
|
+
|
35
|
+
if http.use_ssl?
|
36
|
+
if options[:foreman_ssl_ca] && !options[:foreman_ssl_ca].empty?
|
37
|
+
http.ca_file = options[:foreman_ssl_ca]
|
38
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
39
|
+
end
|
40
|
+
|
41
|
+
if options[:foreman_ssl_cert] && !options[:foreman_ssl_cert].empty? && options[:foreman_ssl_key] && !options[:foreman_ssl_key].empty?
|
42
|
+
http.cert = OpenSSL::X509::Certificate.new(File.read(options[:foreman_ssl_cert]))
|
43
|
+
http.key = OpenSSL::PKey::RSA.new(File.read(options[:foreman_ssl_key]), nil)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
req = Net::HTTP::Post.new("#{uri.path}/#{path}")
|
48
|
+
req.add_field('Accept', 'application/json,version=2')
|
49
|
+
req.content_type = 'application/json'
|
50
|
+
body_json = body.to_json
|
51
|
+
req.body = body_json
|
52
|
+
req.add_field('X-Foreman-Signature', sign_request(body_json, options[:client_key]))
|
53
|
+
req.add_field('X-Foreman-Client', client_name)
|
54
|
+
response = http.request(req)
|
55
|
+
end
|
56
|
+
|
57
|
+
def sign_request(body_json, key_path)
|
58
|
+
hash_body = Digest::SHA256.hexdigest(body_json)
|
59
|
+
key = OpenSSL::PKey::RSA.new(File.read(key_path))
|
60
|
+
# Base64.encode64 is adding \n in the string
|
61
|
+
signature = Base64.encode64(key.sign(OpenSSL::Digest::SHA256.new, hash_body)).gsub("\n",'')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef_handler_foreman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marek Hulan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Chef handlers to integrate with foreman
|
42
|
+
email:
|
43
|
+
- mhulan@redhat.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- chef_handler_foreman.gemspec
|
54
|
+
- lib/chef_handler_foreman.rb
|
55
|
+
- lib/chef_handler_foreman/foreman_facts.rb
|
56
|
+
- lib/chef_handler_foreman/foreman_hooks.rb
|
57
|
+
- lib/chef_handler_foreman/foreman_reporting.rb
|
58
|
+
- lib/chef_handler_foreman/foreman_resource_reporter.rb
|
59
|
+
- lib/chef_handler_foreman/foreman_uploader.rb
|
60
|
+
- lib/chef_handler_foreman/version.rb
|
61
|
+
homepage: https://github.com/theforeman/chef-handler-foreman
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.0.3
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: This gem adds chef handlers so your chef-client can upload attributes (facts)
|
85
|
+
and reports to Foreman
|
86
|
+
test_files: []
|
87
|
+
has_rdoc:
|