loom-core 0.0.2 → 0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/lib/loom/facts/all.rb +1 -0
- data/lib/loom/facts/fact_set.rb +23 -45
- data/lib/loom/facts/provider.rb +43 -0
- data/lib/loom/mods/mod_loader.rb +1 -1
- data/lib/loom/mods/module.rb +9 -2
- data/lib/loom/version.rb +1 -1
- data/lib/loomext/corefacts/all.rb +1 -0
- data/lib/loomext/corefacts/facter_provider.rb +1 -0
- data/lib/loomext/corefacts/system_info_provider.rb +104 -0
- data/lib/loomext/coremods/files.rb +9 -2
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba730790e0a31bfadc0f837eb2574f9e21aed1833afd06881987cb76bc6bce2d
|
4
|
+
data.tar.gz: 6e3936463bef27cf155cdd9873f0268547495d1e0609dce16e5e7089699bd8f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd86c4cafa91fcf0032f214999be470547f198f930cf1b4ff50e1aba0948aa6d78133205f05c91c81aedc2f4809266398365a5b57d878c6655ad92dc5f349100
|
7
|
+
data.tar.gz: a9338a3ff37ed372683af92825b196e5a6c0db4ba9fc14b75a345357dcc92474aeb3008058243e88f24d09e752dcde000551fc79f76bfe3a08c42facc0c426c5
|
data/.gitignore
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
pkg
|
2
|
-
loom-core
|
2
|
+
loom-core-*.gem
|
data/lib/loom/facts/all.rb
CHANGED
data/lib/loom/facts/fact_set.rb
CHANGED
@@ -1,45 +1,9 @@
|
|
1
1
|
module Loom::Facts
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
62
|
-
|
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
|
data/lib/loom/mods/mod_loader.rb
CHANGED
@@ -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.
|
33
|
+
Loom.log.debug(self) { "registered mod => #{klass} as #{name}" }
|
34
34
|
|
35
35
|
opts.each do |k,v|
|
36
36
|
case k
|
data/lib/loom/mods/module.rb
CHANGED
@@ -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
@@ -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
|
-
|
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
|
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.
|
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
|