foreman_ansible 0.2.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of foreman_ansible might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +15 -1
- data/app/helpers/foreman_ansible/ansible_reports_helper.rb +27 -0
- data/app/overrides/report_output.rb +6 -0
- data/app/services/foreman_ansible/fact_importer.rb +4 -3
- data/app/views/foreman_ansible/config_reports/_ansible.html.erb +23 -0
- data/app/views/foreman_ansible/config_reports/_output.html.erb +15 -0
- data/lib/foreman_ansible/engine.rb +5 -2
- data/lib/foreman_ansible/version.rb +1 -1
- data/lib/tasks/foreman_ansible_tasks.rake +0 -10
- data/test/test_plugin_helper.rb +9 -0
- data/test/unit/fact_importer_test.rb +47 -0
- data/test/unit/fact_parser_test.rb +12 -17
- data/test/unit/fact_sparser_test.rb +3 -3
- data/test/unit/helpers/foreman_ansible/ansible_reports_helper_test.rb +23 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f98cfedfee37e7a9829abe818b80cfc7d553b001
|
4
|
+
data.tar.gz: 008f22e68ec44bf9aa46e75d9006608df8c2821a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b1a8c519e2f29aaf1cfdb5b8c604e06db5d8dcbf3a7646a25b1e9a2a935e9dab4b0977ae21d56e4623fd022fd6b68db4358efddcb9f1a32ab83755f4b2921cf
|
7
|
+
data.tar.gz: 54eace7707e28bcb0870cb8e24a270fb473c208c4845bb85c3fbdcf925a1690f0c31577072a5a076502564dde7a1b4ec9c2202336c21bf4b4bc4ea828ffbd2fb
|
data/README.md
CHANGED
@@ -15,8 +15,19 @@ Deploy `extras/foreman_callback.py` as a callback on your Ansible installation.
|
|
15
15
|
callback_plugins = ~/.ansible/plugins/callback_plugins/
|
16
16
|
bin_ansible_callbacks = True
|
17
17
|
```
|
18
|
+
And copy `extras/foreman_callback.py` from this repo to `~/.ansible/plugins/callback_plugins/`.
|
18
19
|
|
19
|
-
|
20
|
+
You can configure it via the following environment variables:
|
21
|
+
|
22
|
+
* FOREMAN_URL: the URL of your Foreman installation (default "http://localhost:3000")
|
23
|
+
* FOREMAN_SSL_CERT: The public key when using SSL client certificates (default "/etc/foreman/client_cert.pem")
|
24
|
+
* FOREMAN_SSL_KEY: The private key when using SSL client certificates (default "/etc/foreman/client_key.pem")
|
25
|
+
* FOREMAN_SSL_VERIFY: wether to verify SSL certificates. Use *False*
|
26
|
+
to disable certificate checks. You can also set it to CA bundle (default is "True").
|
27
|
+
|
28
|
+
See the [python-requests documentation](http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification) on the details of certificate setup.
|
29
|
+
|
30
|
+
That's it!
|
20
31
|
|
21
32
|
Now, every time you run a playbook or `ansible -m setup $HOSTNAME`, Ansible will automatically submit facts and a small report for $HOSTNAME to Foreman. See 'Extra information' below if you find any error.
|
22
33
|
|
@@ -62,3 +73,6 @@ GNU General Public License for more details.
|
|
62
73
|
|
63
74
|
You should have received a copy of the GNU General Public License
|
64
75
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
76
|
+
|
77
|
+
|
78
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ForemanAnsible
|
2
|
+
# This module takes the config reports stored in Foreman for Ansible and
|
3
|
+
# modifies them to be properly presented in views
|
4
|
+
module AnsibleReportsHelper
|
5
|
+
def module_name(log)
|
6
|
+
JSON.parse(log.source.value)['module_name']
|
7
|
+
end
|
8
|
+
|
9
|
+
def module_args(log)
|
10
|
+
JSON.parse(log.source.value)['module_args']
|
11
|
+
end
|
12
|
+
|
13
|
+
def ansible_module_message(log)
|
14
|
+
paragraph_style = 'margin:0px;font-family:Menlo,Monaco,Consolas,monospace'
|
15
|
+
JSON.parse(log.message.value).except('invocation').map do |name, value|
|
16
|
+
next if value.blank?
|
17
|
+
"<p style=#{paragraph_style}>#{name}: #{value}</p>"
|
18
|
+
end.join.html_safe
|
19
|
+
end
|
20
|
+
|
21
|
+
def ansible_report?(log)
|
22
|
+
module_name(log).present?
|
23
|
+
rescue # Failures when parsing the log indicates it's not an Ansible report
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -53,7 +53,7 @@ module ForemanAnsible
|
|
53
53
|
|
54
54
|
# Returns pairs [id, fact_name]
|
55
55
|
def fact_names
|
56
|
-
|
56
|
+
fact_name_class.group('name').maximum(:id)
|
57
57
|
end
|
58
58
|
|
59
59
|
# Fact fully qualified name contains an unambiguous name for a fact
|
@@ -72,8 +72,9 @@ module ForemanAnsible
|
|
72
72
|
def add_fact_value(value, fact_name)
|
73
73
|
return unless missing_facts.include?(fact_name.name)
|
74
74
|
method = host.new_record? ? :build : :create!
|
75
|
-
|
76
|
-
|
75
|
+
host.fact_values.send(method,
|
76
|
+
:value => value.to_s,
|
77
|
+
:fact_name => fact_name)
|
77
78
|
@counters[:added] += 1
|
78
79
|
end
|
79
80
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<table id='report_log' class="table table-bordered table-striped">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th><%= _("Level") %></th>
|
5
|
+
<th><%= _("Module") %></th>
|
6
|
+
<th><%= _("Arguments") %></th>
|
7
|
+
<th><%= _("Message") %></th>
|
8
|
+
</tr>
|
9
|
+
</thead>
|
10
|
+
<tbody>
|
11
|
+
<% logs.each do |log| %>
|
12
|
+
<tr>
|
13
|
+
<td><span <%= report_tag log.level %>><%= h log.level %></span></td>
|
14
|
+
<td><%= h module_name(log) %></td>
|
15
|
+
<td><%= h module_args(log) %></td>
|
16
|
+
<td><%= ansible_module_message(log) %></td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
<tr id='ntsh' <%= "style='display: none;'".html_safe if logs.size > 0%>><td colspan="3">
|
20
|
+
<%= _("Nothing to show") %>
|
21
|
+
</td></tr>
|
22
|
+
</tbody>
|
23
|
+
</table>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!--
|
2
|
+
We parse a few parts of the report log, to check if it's an Ansible report
|
3
|
+
An alternative to this would be to subclass Ansible < ConfigReport and change
|
4
|
+
the API endpoint at api/v2/config_reports to accept a :type argument with the
|
5
|
+
config management system type.
|
6
|
+
|
7
|
+
However, that solution breaks compatibility of this plugin with older versions
|
8
|
+
of Foreman that do not have that endpoint.
|
9
|
+
-->
|
10
|
+
<% if ansible_report?(logs.first) %>
|
11
|
+
<%= render :partial => 'foreman_ansible/config_reports/ansible',
|
12
|
+
:locals => { :logs => logs } %>
|
13
|
+
<% else %>
|
14
|
+
<%= render_original, :locals => { :logs => logs } %>
|
15
|
+
<% end %>
|
@@ -1,14 +1,17 @@
|
|
1
|
+
require 'deface'
|
1
2
|
module ForemanAnsible
|
2
3
|
# This engine connects ForemanAnsible with Foreman core
|
3
4
|
class Engine < ::Rails::Engine
|
4
5
|
engine_name 'foreman_ansible'
|
5
6
|
|
7
|
+
config.autoload_paths += Dir["#{config.root}/app/helpers"]
|
6
8
|
config.autoload_paths += Dir["#{config.root}/app/overrides"]
|
7
9
|
config.autoload_paths += Dir["#{config.root}/app/services"]
|
10
|
+
config.autoload_paths += Dir["#{config.root}/app/views"]
|
8
11
|
|
9
|
-
initializer 'foreman_ansible.register_plugin', :
|
12
|
+
initializer 'foreman_ansible.register_plugin', :before => :finisher_hook do
|
10
13
|
Foreman::Plugin.register :foreman_ansible do
|
11
|
-
requires_foreman '>= 1.
|
14
|
+
requires_foreman '>= 1.9'
|
12
15
|
end
|
13
16
|
end
|
14
17
|
|
data/test/test_plugin_helper.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module ForemanAnsible
|
4
|
+
class FactImporterTest < ActiveSupport::TestCase
|
5
|
+
setup do
|
6
|
+
@host = FactoryGirl.build_stubbed(:host)
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'add new facts adds all fact names in the fixture' do
|
10
|
+
@fact_importer = FactImporter.new(@host, facts_json)
|
11
|
+
facts_to_be_added = FactSparser.sparse(facts_json[:ansible_facts]).keys +
|
12
|
+
FactSparser.unsparse(facts_json[:ansible_facts]).keys
|
13
|
+
@fact_importer.send(:add_new_facts)
|
14
|
+
assert (facts_to_be_added - FactName.all.map(&:name)).empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'missing_facts returns facts we do not have in the database' do
|
18
|
+
@fact_importer = FactImporter.new(@host, facts_json)
|
19
|
+
@fact_importer.expects(:db_facts).returns('ansible_cmdline' => 'fakevalue')
|
20
|
+
refute @fact_importer.send(:missing_facts).include?('ansible_cmdline')
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#add_fact_value' do
|
24
|
+
setup do
|
25
|
+
@fact_importer = FactImporter.new(@host, :ansible_facts => {})
|
26
|
+
end
|
27
|
+
test 'does not add existing facts' do
|
28
|
+
existing_fact = FactoryGirl.build(:fact_name)
|
29
|
+
@fact_importer.expects(:missing_facts).returns([])
|
30
|
+
assert_nil @fact_importer.send(:add_fact_value, nil, existing_fact)
|
31
|
+
end
|
32
|
+
|
33
|
+
test 'adds missing facts' do
|
34
|
+
missing_fact = FactoryGirl.build(:fact_name)
|
35
|
+
@fact_importer.expects(:missing_facts).returns([missing_fact.name])
|
36
|
+
@fact_importer.counters[:added] = 0
|
37
|
+
assert_difference('@host.fact_values.count', 1) do
|
38
|
+
@fact_importer.send(:add_fact_value, 'missing_value', missing_fact)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'add_fact_value works for hosts that have not been created yet' do
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -3,40 +3,39 @@ require 'test_plugin_helper'
|
|
3
3
|
module ForemanAnsible
|
4
4
|
class FactParserTest < ActiveSupport::TestCase
|
5
5
|
setup do
|
6
|
-
|
7
|
-
@facts_importer = ForemanAnsible::FactParser.new(facts_json)
|
6
|
+
@facts_parser = ForemanAnsible::FactParser.new(facts_json)
|
8
7
|
end
|
9
8
|
|
10
9
|
test 'finds facter domain even if ansible_domain is empty' do
|
11
|
-
expect_where(Domain, @
|
12
|
-
@
|
10
|
+
expect_where(Domain, @facts_parser.facts[:facter_domain])
|
11
|
+
@facts_parser.domain
|
13
12
|
end
|
14
13
|
|
15
14
|
test 'finds model' do
|
16
|
-
expect_where(Model, @
|
17
|
-
@
|
15
|
+
expect_where(Model, @facts_parser.facts[:ansible_product_name])
|
16
|
+
@facts_parser.model
|
18
17
|
end
|
19
18
|
|
20
19
|
test 'finds architecture' do
|
21
|
-
expect_where(Architecture, @
|
22
|
-
@
|
20
|
+
expect_where(Architecture, @facts_parser.facts[:ansible_architecture])
|
21
|
+
@facts_parser.architecture
|
23
22
|
end
|
24
23
|
|
25
24
|
test 'does not set environment' do
|
26
|
-
refute @
|
25
|
+
refute @facts_parser.environment
|
27
26
|
end
|
28
27
|
|
29
28
|
test 'creates operatingsystem from operating system options' do
|
30
29
|
sample_mock = mock
|
31
|
-
major_fact = @
|
32
|
-
_, minor_fact = @
|
30
|
+
major_fact = @facts_parser.facts['ansible_distribution_major_version']
|
31
|
+
_, minor_fact = @facts_parser.
|
33
32
|
facts['ansible_distribution_version'].split('.')
|
34
33
|
Operatingsystem.expects(:where).
|
35
|
-
with(:name => @
|
34
|
+
with(:name => @facts_parser.facts['ansible_distribution'],
|
36
35
|
:major => major_fact, :minor => minor_fact || '').
|
37
36
|
returns(sample_mock)
|
38
37
|
sample_mock.expects(:first)
|
39
|
-
@
|
38
|
+
@facts_parser.operatingsystem
|
40
39
|
end
|
41
40
|
|
42
41
|
private
|
@@ -48,9 +47,5 @@ module ForemanAnsible
|
|
48
47
|
returns(sample_mock)
|
49
48
|
sample_mock.expects(:first_or_create)
|
50
49
|
end
|
51
|
-
|
52
|
-
def sample_facts_file
|
53
|
-
File.read(File.join(Engine.root, 'test', 'fixtures', 'sample_facts.json'))
|
54
|
-
end
|
55
50
|
end
|
56
51
|
end
|
@@ -7,17 +7,17 @@ module ForemanAnsible
|
|
7
7
|
'name' => 'Fedora' } }
|
8
8
|
@sparsed_os_facts = { 'operatingsystem::major' => 20,
|
9
9
|
'operatingsystem::minor' => 1,
|
10
|
-
'operatingsystem::name' => 'Fedora'}
|
10
|
+
'operatingsystem::name' => 'Fedora' }
|
11
11
|
end
|
12
12
|
|
13
13
|
test 'sparses simple hash' do
|
14
14
|
assert_equal @sparsed_os_facts,
|
15
|
-
|
15
|
+
ForemanAnsible::FactSparser.sparse(@original_os_facts)
|
16
16
|
end
|
17
17
|
|
18
18
|
test 'unsparse simple hash' do
|
19
19
|
assert_equal @original_os_facts,
|
20
|
-
|
20
|
+
ForemanAnsible::FactSparser.unsparse(@sparsed_os_facts)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module ForemanAnsible
|
4
|
+
module Helpers
|
5
|
+
class AnsibleReportsHelperTest < ActiveSupport::TestCase
|
6
|
+
include ForemanAnsible::AnsibleReportsHelper
|
7
|
+
|
8
|
+
test 'ansible_report? returns false when log is not parseable' do
|
9
|
+
refute ansible_report?('')
|
10
|
+
end
|
11
|
+
|
12
|
+
test 'ansible_report? returns false when log is from Puppet' do
|
13
|
+
refute ansible_report?(FactoryGirl.build(:log))
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'ansible_report? returns true when log contains module_name' do
|
17
|
+
log = FactoryGirl.build(:log)
|
18
|
+
log.source.value = '{ "module_name" : "foo" }'
|
19
|
+
assert ansible_report?(log)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_ansible
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Lobato Garcia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: deface
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "<"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
27
41
|
description: Ansible integration with Foreman
|
28
42
|
email:
|
29
43
|
- elobatocs@gmail.com
|
@@ -34,10 +48,14 @@ files:
|
|
34
48
|
- LICENSE
|
35
49
|
- README.md
|
36
50
|
- Rakefile
|
51
|
+
- app/helpers/foreman_ansible/ansible_reports_helper.rb
|
37
52
|
- app/models/foreman_ansible/fact_name.rb
|
53
|
+
- app/overrides/report_output.rb
|
38
54
|
- app/services/foreman_ansible/fact_importer.rb
|
39
55
|
- app/services/foreman_ansible/fact_parser.rb
|
40
56
|
- app/services/foreman_ansible/fact_sparser.rb
|
57
|
+
- app/views/foreman_ansible/config_reports/_ansible.html.erb
|
58
|
+
- app/views/foreman_ansible/config_reports/_output.html.erb
|
41
59
|
- lib/foreman_ansible.rb
|
42
60
|
- lib/foreman_ansible/engine.rb
|
43
61
|
- lib/foreman_ansible/version.rb
|
@@ -48,8 +66,10 @@ files:
|
|
48
66
|
- locale/gemspec.rb
|
49
67
|
- test/fixtures/sample_facts.json
|
50
68
|
- test/test_plugin_helper.rb
|
69
|
+
- test/unit/fact_importer_test.rb
|
51
70
|
- test/unit/fact_parser_test.rb
|
52
71
|
- test/unit/fact_sparser_test.rb
|
72
|
+
- test/unit/helpers/foreman_ansible/ansible_reports_helper_test.rb
|
53
73
|
homepage: https://github.com/theforeman/foreman_ansible
|
54
74
|
licenses:
|
55
75
|
- GPL-3
|
@@ -78,4 +98,6 @@ test_files:
|
|
78
98
|
- test/fixtures/sample_facts.json
|
79
99
|
- test/test_plugin_helper.rb
|
80
100
|
- test/unit/fact_parser_test.rb
|
101
|
+
- test/unit/fact_importer_test.rb
|
81
102
|
- test/unit/fact_sparser_test.rb
|
103
|
+
- test/unit/helpers/foreman_ansible/ansible_reports_helper_test.rb
|