loom-core 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fca395ca95a28376331f0163c1748fcd3eb083c2f6d677627edb04a795c5b858
4
- data.tar.gz: 29fc16366271bfe121eb57b7315daa87a6d8017210d41a061cdecc6665bb26bc
3
+ metadata.gz: ba730790e0a31bfadc0f837eb2574f9e21aed1833afd06881987cb76bc6bce2d
4
+ data.tar.gz: 6e3936463bef27cf155cdd9873f0268547495d1e0609dce16e5e7089699bd8f5
5
5
  SHA512:
6
- metadata.gz: 291da2a4d0b793019dd65c511dfc1caa113a3a12c3a7f2ab12e9b991a8e5ce09b4fba97fb150b15b01edd6c67f0ea0536f16fc00384bf80c6ec54f9b21c9c1c2
7
- data.tar.gz: 0b18248b8cf5583a48fb3844c39e15b0db216ad6c6ab62a160b5013d05e6f8931bbf165c35c7e107ce3de28a88e7227662480fd263f11031fb5356da2729c5a6
6
+ metadata.gz: bd86c4cafa91fcf0032f214999be470547f198f930cf1b4ff50e1aba0948aa6d78133205f05c91c81aedc2f4809266398365a5b57d878c6655ad92dc5f349100
7
+ data.tar.gz: a9338a3ff37ed372683af92825b196e5a6c0db4ba9fc14b75a345357dcc92474aeb3008058243e88f24d09e752dcde000551fc79f76bfe3a08c42facc0c426c5
data/.gitignore CHANGED
@@ -1,2 +1,2 @@
1
1
  pkg
2
- loom-core-0.0.1.gem
2
+ loom-core-*.gem
@@ -1,2 +1,3 @@
1
+ require_relative "provider"
1
2
  require_relative "fact_set"
2
3
  require_relative "fact_file_provider"
@@ -1,45 +1,9 @@
1
1
  module Loom::Facts
2
2
 
3
- class Provider
4
- attr_reader :fact_map
5
-
6
- class << self
7
- def disable_for_host(host_spec, klass)
8
- Loom.log.warn "disabling fact provider => #{klass} on #{host_spec.hostname}"
9
- @disabled_providers ||= {}
10
- @disabled_providers[host_spec.hostname] ||= []
11
- @disabled_providers[host_spec.hostname] << klass
12
- end
13
-
14
- def disabled_for_host?(host_spec, klass)
15
- @disabled_providers ||= {}
16
- @disabled_providers[host_spec.hostname] ||= []
17
- @disabled_providers[host_spec.hostname].include? klass
18
- end
19
-
20
- def register_factory(klass, &block)
21
- @provider_factories ||= []
22
- @provider_factories << block
23
- Loom.log.debug1(self) { "registered fact provider => #{klass}" }
24
- end
25
-
26
- def create_fact_providers(host_spec, shell, loom_config)
27
- @provider_factories.map do |block|
28
- block.call(host_spec, shell, loom_config)
29
- end.flatten
30
- end
31
- end
32
-
33
- def disable(host_spec)
34
- Provider.disable_for_host host_spec, self.class
35
- end
36
-
37
- # Should return a Hash
38
- def collect_facts
39
- raise 'not implemented'
40
- end
41
- end
42
-
3
+ ##
4
+ # A factset is created by running each registered Loom::Facts::Provider and
5
+ # calling Provider+collect_facts+. See ./fact_file_provider.rb and
6
+ # lib/loomext/facts/facter_provider.rb for examples of fact providers.
43
7
  class FactSet
44
8
 
45
9
  InvalidFactName = Class.new Loom::LoomError
@@ -53,19 +17,33 @@ module Loom::Facts
53
17
  fact_providers.each do |provider|
54
18
  next if Provider.disabled_for_host?(host_spec, provider.class)
55
19
 
56
- Loom.log.debug { "loading facts from provider => #{provider}" }
20
+ namespace = provider.namespace
21
+ Loom.log.debug { "loading facts from provider => #{provider}[#{namespace}]" }
57
22
 
23
+ provider_facts = {}
58
24
  begin
59
25
  provider.collect_facts.each do |k, v|
60
26
  k = k.to_sym
61
- if fact_map[k]
62
- Loom.log.warn "overriding fact => #{k}"
27
+ provider_facts[k] = v
28
+ end
29
+
30
+ if namespace
31
+ if fact_map[namespace]
32
+ Loom.log.warn "overriding fact[#{namespace}] with namespace"
33
+ end
34
+ fact_map[namespace] = provider_facts
35
+ else
36
+ provider_facts.each do |k, v|
37
+ if fact_map[k]
38
+ Loom.log.warn "overriding fact[#{k}]"
39
+ end
40
+ Loom.log.debug5(self) { "adding fact => #{k}=#{v.to_s}" }
41
+ fact_map[k] = v
63
42
  end
64
- Loom.log.debug5(self) { "adding fact => #{k}=#{v.to_s}" }
65
- fact_map[k] = v
66
43
  end
67
44
  rescue => e
68
45
  Loom.log.error "error executing fact provider #{provider.class} => #{e.message}"
46
+ Loom.log.debug(self) { e.backtrace.join("\n\t") }
69
47
  provider.disable(host_spec)
70
48
  end
71
49
  end
@@ -0,0 +1,43 @@
1
+ module Loom::Facts
2
+
3
+ class Provider
4
+ # TODO: add documentation re: use of namespace in fact_set.rb
5
+ attr_reader :fact_map, :namespace
6
+
7
+ class << self
8
+ def disable_for_host(host_spec, klass)
9
+ Loom.log.warn "disabling fact provider => #{klass} on #{host_spec.hostname}"
10
+ @disabled_providers ||= {}
11
+ @disabled_providers[host_spec.hostname] ||= []
12
+ @disabled_providers[host_spec.hostname] << klass
13
+ end
14
+
15
+ def disabled_for_host?(host_spec, klass)
16
+ @disabled_providers ||= {}
17
+ @disabled_providers[host_spec.hostname] ||= []
18
+ @disabled_providers[host_spec.hostname].include? klass
19
+ end
20
+
21
+ def register_factory(klass, &block)
22
+ @provider_factories ||= []
23
+ @provider_factories << block
24
+ Loom.log.debug1(self) { "registered fact provider => #{klass}" }
25
+ end
26
+
27
+ def create_fact_providers(host_spec, shell, loom_config)
28
+ @provider_factories.map do |block|
29
+ block.call(host_spec, shell, loom_config)
30
+ end.flatten
31
+ end
32
+ end
33
+
34
+ def disable(host_spec)
35
+ Provider.disable_for_host host_spec, self.class
36
+ end
37
+
38
+ # Should return a Hash of fact_name => fact_value entries
39
+ def collect_facts
40
+ raise 'not implemented'
41
+ end
42
+ end
43
+ end
@@ -30,7 +30,7 @@ module Loom::Mods
30
30
  raise ModDefinedError, name if instance_methods.include? name
31
31
 
32
32
  define_mod_factory name, klass
33
- Loom.log.debug1(self) { "registered mod => #{klass} as #{name}" }
33
+ Loom.log.debug(self) { "registered mod => #{klass} as #{name}" }
34
34
 
35
35
  opts.each do |k,v|
36
36
  case k
@@ -49,12 +49,19 @@ module Loom::Mods
49
49
 
50
50
  class << self
51
51
 
52
+ ##
53
+ # Registers a mod as a new namespace on the loom object.
54
+ # Mods add actions either via a `mod_block` or via registering
55
+ # actions. Only 1 mod_block may be registered per module (which should
56
+ # be fixed), otherwise actions are imported to add module behavior.
57
+ # See loom/lib/loomext/coremods.rb and files.rb for examples.
52
58
  def register_mod(name, **opts, &block)
53
59
  Loom.log.debug2(self) { "registered mod => #{name}" }
54
60
 
61
+ # TODO: allow multiple mod_blocks per mod. Should probably stop
62
+ # dynamically defining :mod_block to do so. Current behavior, is the
63
+ # last register_mod w/ a mod_block wins. This is obvsiously shitty.
55
64
  if block_given?
56
- # TODO: i forget what mod_blocks are. read through, remember, and
57
- # document them.
58
65
  Loom.log.debug2(self) { "acting as mod_block => #{name}:#{block}" }
59
66
  define_method :mod_block, &block
60
67
  end
data/lib/loom/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Loom
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -6,3 +6,4 @@ end
6
6
  require "loom"
7
7
 
8
8
  require_relative "facter_provider"
9
+ require_relative "system_info_provider"
@@ -9,6 +9,7 @@ module LoomExt::CoreFacts
9
9
  @has_facter = shell.test :which, "facter"
10
10
  disable(host_spec) unless @has_facter
11
11
  @shell = shell
12
+ @namespace = :facter
12
13
  end
13
14
 
14
15
  def collect_facts
@@ -0,0 +1,104 @@
1
+ module LoomExt::CoreFacts
2
+ class SystemInfoProvider < Loom::Facts::Provider
3
+
4
+ using Loom::CoreExt # using +underscore+ for key name creation
5
+
6
+ Loom::Facts::Provider.register_factory(self) do |host_spec, shell, loom_config|
7
+ SystemInfoProvider.new host_spec, shell
8
+ end
9
+
10
+ def initialize(host_spec, shell)
11
+ @shell = shell
12
+ @namespace = :system_info
13
+ end
14
+
15
+ def collect_facts
16
+ # see:
17
+ # https://linux.die.net/man/8/vmstat
18
+ # https://linux.die.net/man/5/proc
19
+ # https://linux.die.net/man/1/df
20
+ # https://www.cyberciti.biz/faq/linux-find-out-raspberry-pi-gpu-and-arm-cpu-temperature-command/
21
+ {
22
+ :vmstat => facts_from_vmstat,
23
+ :loadavg => facts_from_proc_loadavg,
24
+ :df => facts_from_df,
25
+ :os_release => facts_from_etc_os_release,
26
+ :cpu_temp => facts_from_sys_class_thermal_zones
27
+ }
28
+ end
29
+
30
+ private
31
+ def facts_from_vmstat
32
+ # NB: requires the host to support `vmstat -s` for table formatted output
33
+ vmstat_table = @shell.capture :vmstat, "-s"
34
+ vmstat_table.each_line.reduce({}) do |memo, line|
35
+ _, str_value, label = line.match(/\s*(\d+)\s(.*)/).to_a
36
+ int_value = str_value.to_i
37
+ value = int_value.to_s == str_value ? int_value : str_value
38
+ memo.merge label.strip.underscore.to_sym => value
39
+ end
40
+ end
41
+
42
+ def facts_from_proc_loadavg
43
+ loadavg = @shell.capture :cat, "/proc/loadavg"
44
+
45
+ one, five, fifteen, kernel_scheduling_entities, lastpid = loadavg.split
46
+ current_entities, total_entities = kernel_scheduling_entities.split("/")
47
+
48
+ {
49
+ :"1_min_avg" => one.to_f,
50
+ :"5_min_avg" => five.to_f,
51
+ :"15_min_avg" => fifteen.to_f,
52
+ :kernel_scheduling_entities => kernel_scheduling_entities,
53
+ :current_scheduling_entities => current_entities.to_i,
54
+ :total_scheduling_entities => total_entities.to_i,
55
+ :lastpid => lastpid
56
+ }
57
+ end
58
+
59
+ def facts_from_df
60
+ df = @shell.capture :df
61
+
62
+ headers = df.lines.first.split.map do |h|
63
+ h = "UsePercent" if h == "Use%"
64
+ h.strip.underscore.to_sym
65
+ end
66
+
67
+ info_lines = df.lines.drop(1).map { |l| l.strip }
68
+ info_lines.map do |info|
69
+ info_parts = info.split.map { |i| i.strip }
70
+ header_info_pairs = headers.zip(info_parts)
71
+ header_info_pairs.reduce({}) do |memo, pair|
72
+ str_value = pair[1]
73
+ int_value = str_value.to_i
74
+ value = int_value.to_s == str_value ? int_value : str_value
75
+ memo.merge pair[0] => value
76
+ end
77
+ end
78
+ end
79
+
80
+ def facts_from_etc_os_release
81
+ os_release = @shell.capture :cat, "/etc/os-release"
82
+
83
+ facts = {}
84
+ os_release.each_line do |l|
85
+ l = l.strip
86
+ key, value = l.split("=")
87
+ unquoted_value = value.gsub(/^"(.+)"$/) { |m| $1 }
88
+ facts[key.to_sym] = unquoted_value
89
+ end
90
+ facts
91
+ end
92
+
93
+ def facts_from_sys_class_thermal_zones
94
+ thermal_zones = @shell.capture :ls, "/sys/class/thermal"
95
+ thermal_zones
96
+ .split
97
+ .delete_if { |f| !f.strip.match(/^thermal_zone/) }
98
+ .map do |tz_dir|
99
+ temp = @shell.capture :cat, "/sys/class/thermal/#{tz_dir}/temp"
100
+ temp.strip.to_f / 1000
101
+ end
102
+ end
103
+ end
104
+ end
@@ -2,6 +2,7 @@ module LoomExt::CoreMods
2
2
  class Files < Loom::Mods::Module
3
3
 
4
4
  register_mod :files
5
+ required_commands :cat, :mv, :tee, :chown, :rm, :touch, :sudo, :mkdir, :echo
5
6
 
6
7
  # TODO: document loom file statements like:
7
8
  # `loom.files("some", "different/paths").cat`
@@ -88,6 +89,8 @@ module LoomExt::CoreMods
88
89
  each_path :action => :mkdir, :flags => flags
89
90
  end
90
91
 
92
+ # TODO this sudo line is just another instance of needing the harness to
93
+ # work properly (in this case to provides a hack for sudo_append)
91
94
  def ensure_line(line, sudo: false)
92
95
  if loom.is_sudo?
93
96
  Loom.log.warn "do not use files.ensure_line in sudo due to poor command escaping" +
@@ -97,17 +100,21 @@ module LoomExt::CoreMods
97
100
  each_path do |p|
98
101
  file = shell.capture :cat, p
99
102
 
100
- unless file.match(line)
103
+ matches = file.match(/^#{line}$/)
104
+ unless matches
101
105
  if sudo
102
106
  sudo_append(line)
103
107
  else
104
108
  append(line)
105
109
  end
110
+ else
111
+ Loom.log.debug(self) { "ensure_line match found: #{matches[0]}"}
106
112
  end
107
113
  end
108
114
  end
109
115
 
110
- # this is a hack to accomodate append being f'd inside sudo blocks
116
+ # TODO: Get the harness working, this is a hack to accomodate append being
117
+ # f'd inside sudo blocks
111
118
  def sudo_append(text="")
112
119
  if text.index "\n"
113
120
  Loom.log.warn "append lines individually until cmd escaping is fixed.... "
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loom-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erick Johnson
@@ -214,6 +214,7 @@ files:
214
214
  - lib/loom/facts/all.rb
215
215
  - lib/loom/facts/fact_file_provider.rb
216
216
  - lib/loom/facts/fact_set.rb
217
+ - lib/loom/facts/provider.rb
217
218
  - lib/loom/host_spec.rb
218
219
  - lib/loom/inventory.rb
219
220
  - lib/loom/logger.rb
@@ -249,6 +250,7 @@ files:
249
250
  - lib/loomext/corefacts.rb
250
251
  - lib/loomext/corefacts/all.rb
251
252
  - lib/loomext/corefacts/facter_provider.rb
253
+ - lib/loomext/corefacts/system_info_provider.rb
252
254
  - lib/loomext/coremods.rb
253
255
  - lib/loomext/coremods/all.rb
254
256
  - lib/loomext/coremods/exec.rb