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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 651683d29fb40dbd94af8c41c17aac05d338da63
4
- data.tar.gz: 08b2873008325af3d6108f2cebe5cfef7e3a3198
3
+ metadata.gz: f98cfedfee37e7a9829abe818b80cfc7d553b001
4
+ data.tar.gz: 008f22e68ec44bf9aa46e75d9006608df8c2821a
5
5
  SHA512:
6
- metadata.gz: 1e2d6381c31429e26137a351e8125f7475a9328f3fa58f46b5b59d60f0590f7ff4f85be8d72b11bc822c4db3711e77497c49b30c1395745374787a73a0808a78
7
- data.tar.gz: 8e6cdf7a6c43694f79a1587fd10cc30b4d74543ea329dff02628d2c03e0aa7a9b9272abf1c353e1c52b4a7eef1a5c769d6509d5f7eb0ed379677d487dd6d8f93
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
- And copy `extras/foreman_callback.py` from this repo to `~/.ansible/plugins/callback_plugins/`. That's it!
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
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ :virtual_path => 'config_reports/_output',
3
+ :name => 'report_output',
4
+ :surround => '#report_log',
5
+ :partial => 'foreman_ansible/config_reports/output'
6
+ )
@@ -53,7 +53,7 @@ module ForemanAnsible
53
53
 
54
54
  # Returns pairs [id, fact_name]
55
55
  def fact_names
56
- @fact_names ||= fact_name_class.group('name').maximum(:id)
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
- #value = nil if compose?(value)
76
- host.fact_values.send(method, :value => value.to_s, :fact_name => fact_name)
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', :after => :finisher_hook do
12
+ initializer 'foreman_ansible.register_plugin', :before => :finisher_hook do
10
13
  Foreman::Plugin.register :foreman_ansible do
11
- requires_foreman '>= 1.6'
14
+ requires_foreman '>= 1.9'
12
15
  end
13
16
  end
14
17
 
@@ -2,5 +2,5 @@
2
2
  # This way other parts of Foreman can just call ForemanAnsible::VERSION
3
3
  # and detect what version the plugin is running.
4
4
  module ForemanAnsible
5
- VERSION = '0.2.2'
5
+ VERSION = '0.3'
6
6
  end
@@ -1,13 +1,3 @@
1
- # Tasks
2
- namespace :foreman_ansible do
3
- namespace :example do
4
- desc 'Example Task'
5
- task :task => :environment do
6
- # Task goes here
7
- end
8
- end
9
- end
10
-
11
1
  # Tests
12
2
  namespace :test do
13
3
  desc 'Test ForemanAnsible'
@@ -1 +1,10 @@
1
1
  require 'test_helper'
2
+
3
+ def sample_facts_file
4
+ File.read(File.join(
5
+ ForemanAnsible::Engine.root, 'test', 'fixtures', 'sample_facts.json'))
6
+ end
7
+
8
+ def facts_json
9
+ HashWithIndifferentAccess.new(JSON.parse(sample_facts_file))
10
+ end
@@ -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
- facts_json = HashWithIndifferentAccess.new(JSON.parse(sample_facts_file))
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, @facts_importer.facts[:facter_domain])
12
- @facts_importer.domain
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, @facts_importer.facts[:ansible_product_name])
17
- @facts_importer.model
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, @facts_importer.facts[:ansible_architecture])
22
- @facts_importer.architecture
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 @facts_importer.environment
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 = @facts_importer.facts['ansible_distribution_major_version']
32
- _, minor_fact = @facts_importer.
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 => @facts_importer.facts['ansible_distribution'],
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
- @facts_importer.operatingsystem
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
- ForemanAnsible::FactSparser.sparse(@original_os_facts)
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
- ForemanAnsible::FactSparser.unsparse(@sparsed_os_facts)
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.2.2
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-05 00:00:00.000000000 Z
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