foreman_ansible 0.1.1 → 0.2.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.

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: 3cae18690ddfd00ff1050acdefd09a621457177a
4
- data.tar.gz: bba73f69e7a760c310c712f69027cc0312b23a1a
3
+ metadata.gz: 5d9930905b911888013c949cc42e140daed748c4
4
+ data.tar.gz: 62f9e18006e75d4be30d9bf263cdb81edbbf4b05
5
5
  SHA512:
6
- metadata.gz: 2f58daf8630756494fa0f39ecf99df13cbf38694005fcf73bad1f2ec4a1e026c89ab3cde7703ca051041b41ec80469934aeb2d75d8f43360d63c6bdec6126a46
7
- data.tar.gz: 46a793766a4fd1cfd2c75e67ecacc68225410efea24d430115f452fe5f4ff9964acac8b0ef3468eab895f4fc6b5153ca1e333675cdf1070089abf11867a469be
6
+ metadata.gz: 468ae9f121f50e441d2d1317bd87a79f0b547aa4f7fba0c4c6ce18a63e7538813ac02301530757fedaeef7c8c7f95bb54007ad25b5c75771dfc91bd6f8ff4fd5
7
+ data.tar.gz: 676edd7606ac3c52c5d195ff2550ac0a610ad7e22b3987fdec4093a79a7bc538b71e9a7f66ef616e53a5d9e0215ced797b0ff94b2f569c16cdb221660eb42cb1
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Foreman](http://theforeman.org) integration with Ansible. For now, it's just importing facts and not meant for general use.
4
4
 
5
- ** Warning - this project hasn't been released yet, and might change significantly. Please don't use in production. **
5
+ **Warning - this project hasn't been released yet, and might change significantly. Please don't use in production**
6
6
 
7
7
  ## Basic usage
8
8
 
@@ -17,15 +17,17 @@ bin_ansible_callbacks = True
17
17
 
18
18
  And copy `extras/foreman_callback.py` from this repo to `~/.ansible/plugins/callback_plugins/`. That's it!
19
19
 
20
- Now, every time you run `ansible -m setup $HOSTNAME`, Ansible will automatically submit facts for $HOSTNAME to Foreman.
20
+ 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.
21
21
 
22
- In Foreman, you should add whatever Ansible hosts you want to submit facts from to the Setting (Administer > Settings, Puppet tab - I know..)) 'trusted_puppetmaster_hosts'.
22
+ ##### Registering a new host in Foreman
23
+ ![sign up gif](http://i.imgur.com/mlnVFJj.gif)
23
24
 
24
- #### Demo
25
+ ##### Host with failed and successful reports
26
+ ![reports](http://i.imgur.com/1ySO4sh.png)
25
27
 
26
- ![demo gif](http://i.imgur.com/mlnVFJj.gif)
28
+ ### Extra information
27
29
 
28
- ### Extra
30
+ In Foreman, you should add whatever Ansible hosts you want to submit facts from to the setting `trusted_puppetmaster_hosts`. Change it at Administer > Settings, Puppet tab.
29
31
 
30
32
  If the Foreman setting 'create_new_host_when_facts_are_uploaded' is true, and $HOSTNAME doesn't exist in Foreman, it will autocreate that host in Foreman. If it already exists, it will update the facts.
31
33
 
@@ -33,9 +35,9 @@ Similarly, the Foreman setting 'ignore_puppet_facts_for_provisioning' is set to
33
35
 
34
36
  ### Devs
35
37
 
36
- Send a POST request to /api/v2/hosts/facts with the format you can see [in the API docs](http://theforeman.org/api/1.9/apidoc/v2/hosts/facts.html).
38
+ The callback sends a POST request to /api/v2/hosts/facts with the format you can see [in the API docs](http://theforeman.org/api/1.9/apidoc/v2/hosts/facts.html).
37
39
 
38
- Facts must contain the output of `ansible -m setup $HOSTNAME`, plus a '_type' and '_timestamp' top level keys. You can see an example on test/fixtures/sample_facts.json in this repository.
40
+ Facts must contain the output of `ansible -m setup $HOSTNAME`, plus a '_type' and '_timestamp' keys. You can see an example on test/fixtures/sample_facts.json in this repository.
39
41
 
40
42
  After that request, you should have a host registered in Foreman with the Ansible facts. It takes into account some facter and ohai facts if these are available on the system as well.
41
43
 
@@ -7,7 +7,69 @@ module ForemanAnsible
7
7
  def initialize(host, facts = {})
8
8
  @host = host
9
9
  @facts = normalize(facts[:ansible_facts])
10
+ @original_facts = FactSparser.unsparse(facts[:ansible_facts])
10
11
  @counters = {}
11
12
  end
13
+
14
+ private
15
+
16
+ def add_new_facts
17
+ @counters[:added] = 0
18
+ add_missing_facts(FactSparser.unsparse(@original_facts))
19
+ logger.debug("Merging facts for '#{host}': added #{@counters[:added]} facts")
20
+ end
21
+
22
+ def add_missing_facts(imported_facts, parent = nil, prefix = '')
23
+ imported_facts.select! { |fact_name, fact_value| !fact_value.nil? }
24
+
25
+ imported_facts.each do |imported_name, imported_value|
26
+ fact_fqn = fact_fqn(imported_name, prefix)
27
+ next unless missing_facts.include?(fact_fqn)
28
+ fact_name = find_fact_name(fact_fqn, parent)
29
+
30
+ add_fact_value(imported_value, fact_name)
31
+ add_compose_fact(imported_value, fact_name, fact_fqn)
32
+ end
33
+ end
34
+
35
+ def add_compose_fact(imported_values, fact_name, fact_fqn)
36
+ if imported_values.is_a?(Hash)
37
+ add_missing_facts(imported_values, fact_name, fact_fqn)
38
+ elsif imported_values.is_a?(Array)
39
+ imported_values.each do |imported_value|
40
+ next unless imported_value.is_a?(Hash)
41
+ add_missing_facts(imported_value, fact_name, fact_fqn)
42
+ end
43
+ end
44
+ end
45
+
46
+ def missing_facts
47
+ @missing_facts ||= (facts.keys + FactSparser.sparse(@original_facts).keys) - db_facts.keys
48
+ end
49
+
50
+ # Returns pairs [id, fact_name]
51
+ def fact_names
52
+ @fact_names ||= fact_name_class.maximum(:id, :group => 'name')
53
+ end
54
+
55
+ # Fact fully qualified name contains an unambiguous name for a fact
56
+ # e.g: ansible_lo::ipv6, ansible_virbr0::active
57
+ def fact_fqn(name, prefix)
58
+ prefix.empty? ? name : prefix + FactName::SEPARATOR + name
59
+ end
60
+
61
+ def find_fact_name(name, parent)
62
+ return FactName.find(fact_names[name]) if fact_names[name].present?
63
+ fact_name_class.create!(:name => name,
64
+ :parent => parent,
65
+ :compose => compose)
66
+ end
67
+
68
+ def add_fact_value(value, fact_name)
69
+ method = host.new_record? ? :build : :create!
70
+ host.fact_values.send(method, :value => value, :fact_name => fact_name)
71
+ @counters[:added] += 1
72
+ end
73
+
12
74
  end
13
75
  end
@@ -12,9 +12,7 @@ module ForemanAnsible
12
12
  Operatingsystem.create!(args.merge(:description => os_description))
13
13
  end
14
14
 
15
- def environment
16
- # Don't do anything
17
- end
15
+ def environment; end # Don't do anything as there's no env in Ansible
18
16
 
19
17
  def architecture
20
18
  name = facts[:ansible_architecture] || facts[:facter_architecture]
@@ -41,7 +39,13 @@ module ForemanAnsible
41
39
  end
42
40
 
43
41
  def get_interfaces
44
- facts[:ansible_interfaces]
42
+ # Move ansibles default interface first in the list of interfaces since
43
+ # Foreman picks the first one that is usable. If ansible has no
44
+ # preference otherwise at least sort the list.
45
+ pref = facts[:ansible_default_ipv4] &&
46
+ facts[:ansible_default_ipv4]['interface']
47
+ pref ? (facts[:ansible_interfaces] - [pref]).unshift(pref) :
48
+ facts[:ansible_interfaces].sort
45
49
  end
46
50
 
47
51
  def get_facts_for_interface(interface)
@@ -51,9 +55,7 @@ module ForemanAnsible
51
55
  HashWithIndifferentAccess[interface_facts.merge(:ipaddress => ipaddress)]
52
56
  end
53
57
 
54
- def ipmi_interface
55
- # ?
56
- end
58
+ def ipmi_interface; end
57
59
 
58
60
  private
59
61
 
@@ -64,17 +66,17 @@ module ForemanAnsible
64
66
 
65
67
  def os_name
66
68
  facts[:ansible_distribution] ||
67
- facts[:ansible_lsb]['id']
69
+ facts[:ansible_lsb] && facts[:ansible_lsb]['id']
68
70
  end
69
71
 
70
72
  def os_major
71
73
  facts[:ansible_distribution_major_version] ||
72
- facts[:ansible_lsb]['major_release']
74
+ facts[:ansible_lsb] && facts[:ansible_lsb]['major_release']
73
75
  end
74
76
 
75
77
  def os_release
76
78
  facts[:ansible_distribution_version] ||
77
- facts[:ansible_lsb]['release']
79
+ facts[:ansible_lsb] && facts[:ansible_lsb]['release']
78
80
  end
79
81
 
80
82
  def os_minor
@@ -83,7 +85,7 @@ module ForemanAnsible
83
85
  end
84
86
 
85
87
  def os_description
86
- facts[:ansible_lsb]['description']
88
+ facts[:ansible_lsb] && facts[:ansible_lsb]['description']
87
89
  end
88
90
  end
89
91
  end
@@ -0,0 +1,24 @@
1
+ module ForemanAnsible
2
+ class FactSparser
3
+ class << self
4
+ def sparse(hash, options = {} )
5
+ hash.map do |k, v|
6
+ prefix = options.fetch(:prefix, []) + [k]
7
+ next sparse(v, options.merge(:prefix => prefix)) if v.is_a? Hash
8
+ { prefix.join(options.fetch(:separator, FactName::SEPARATOR)) => v }
9
+ end.reduce(:merge) || Hash.new
10
+ end
11
+
12
+ def unsparse(hash, options={})
13
+ ret = Hash.new
14
+ sparse(hash).each do |k, v|
15
+ current = ret
16
+ key = k.to_s.split(options.fetch(:separator, FactName::SEPARATOR))
17
+ current = (current[key.shift] ||= Hash.new) until key.size <= 1
18
+ current[key.first] = v
19
+ end
20
+ ret
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module ForemanAnsible
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.1'
3
3
  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.1.1
4
+ version: 0.2.1
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: 2015-11-02 00:00:00.000000000 Z
11
+ date: 2015-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -37,6 +37,7 @@ files:
37
37
  - app/models/foreman_ansible/fact_name.rb
38
38
  - app/services/foreman_ansible/fact_importer.rb
39
39
  - app/services/foreman_ansible/fact_parser.rb
40
+ - app/services/foreman_ansible/fact_sparser.rb
40
41
  - lib/foreman_ansible.rb
41
42
  - lib/foreman_ansible/engine.rb
42
43
  - lib/foreman_ansible/version.rb