foreman_ansible 0.2.2 → 0.3
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.
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
|