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 +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
|