loom-core 0.0.5 → 0.0.6
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/Gemfile.lock +1 -1
- data/bin/loom +5 -1
- data/lib/loom/config.rb +10 -3
- data/lib/loom/facts/fact_set.rb +7 -1
- data/lib/loom/mods/module.rb +3 -4
- data/lib/loom/pattern/definition_context.rb +1 -1
- data/lib/loom/pattern/dsl.rb +113 -32
- data/lib/loom/pattern/reference_set.rb +7 -7
- data/lib/loom/runner.rb +8 -0
- data/lib/loom/shell/api.rb +2 -0
- data/lib/loom/version.rb +1 -1
- data/lib/loomext/corefacts/system_info_provider.rb +2 -1
- data/lib/loomext/coremods/all.rb +2 -1
- data/lib/loomext/coremods/exec.rb +10 -0
- data/lib/loomext/coremods/git.rb +19 -0
- data/lib/loomext/coremods/package/adapter.rb +1 -1
- data/lib/loomext/coremods/systemd.rb +1 -0
- data/lib/loomext/coremods/systemd/all.rb +2 -0
- data/lib/loomext/coremods/{system.rb → systemd/systemd.rb} +19 -5
- data/lib/loomext/coremods/systemd/systemd_units.rb +69 -0
- data/scripts/harness.sh +1 -0
- data/spec/.loom/error_handling.loom +15 -0
- data/spec/.loom/fail.loom +20 -0
- data/spec/.loom/files.loom +39 -0
- data/spec/.loom/net.loom +21 -0
- data/spec/.loom/pattern_context.loom +78 -0
- data/spec/.loom/pkg.loom +33 -0
- data/spec/.loom/shell.loom +46 -0
- data/spec/.loom/test.loom +73 -0
- data/spec/.loom/user.loom +29 -0
- data/spec/.loom/vms.loom +22 -0
- data/spec/loom/facts/fact_set_spec.rb +57 -0
- data/spec/loom/pattern/dsl_spec.rb +58 -9
- data/spec/loom/shell/harness_blob_spec.rb +1 -1
- data/spec/loom/shell/harness_command_builder_spec.rb +1 -1
- data/spec/loomext/coremods/systemd_spec.rb +31 -0
- data/spec/runloom.sh +12 -19
- data/spec/scripts/harness_spec.rb +1 -1
- data/spec/shared/loom_internals_helper.rb +41 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/systemd.loom +22 -0
- data/spec/test_loom_spec.rb +95 -17
- data/test +2 -0
- metadata +26 -5
- data/spec/test.loom +0 -370
@@ -0,0 +1,19 @@
|
|
1
|
+
module LoomExt::CoreMods
|
2
|
+
class Git < Loom::Mods::Module
|
3
|
+
|
4
|
+
register_mod :git
|
5
|
+
required_commands :git
|
6
|
+
|
7
|
+
module Actions
|
8
|
+
def push
|
9
|
+
shell.execute :git, :push
|
10
|
+
end
|
11
|
+
|
12
|
+
def pull
|
13
|
+
shell.execute :git, :pull
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Git.import_actions Git::Actions
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "systemd/all"
|
@@ -1,13 +1,27 @@
|
|
1
1
|
module LoomExt::CoreMods
|
2
2
|
|
3
|
+
module SystemdCommon
|
4
|
+
def do_systemctl(action, unit=nil, *args, flags: [])
|
5
|
+
flags << "--no-pager"
|
6
|
+
flags << "--no-legend"
|
7
|
+
flags << "--no-ask-password"
|
8
|
+
|
9
|
+
exec_args = [
|
10
|
+
"systemctl",
|
11
|
+
flags,
|
12
|
+
action,
|
13
|
+
unit
|
14
|
+
].flatten.compact
|
15
|
+
args = exec_args.concat args
|
16
|
+
shell.execute(*args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
3
20
|
class Systemd < Loom::Mods::Module
|
21
|
+
include SystemdCommon
|
4
22
|
|
5
23
|
register_mod :systemd
|
6
24
|
|
7
|
-
def do_systemctl(action, *args)
|
8
|
-
shell.execute "systemctl", action, *args
|
9
|
-
end
|
10
|
-
|
11
25
|
module Actions
|
12
26
|
|
13
27
|
def is_loaded?(unit)
|
@@ -15,7 +29,7 @@ module LoomExt::CoreMods
|
|
15
29
|
end
|
16
30
|
|
17
31
|
def is_active?(unit)
|
18
|
-
|
32
|
+
do_systemctl "is-active", unit
|
19
33
|
end
|
20
34
|
|
21
35
|
def status(unit)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module LoomExt::CoreMods
|
2
|
+
|
3
|
+
module SystemdUnitsCommon
|
4
|
+
|
5
|
+
def init_action(*units, type: nil)
|
6
|
+
@units = units
|
7
|
+
@type = type
|
8
|
+
end
|
9
|
+
|
10
|
+
def do_systemctl_list(list_what, flags=common_list_flags)
|
11
|
+
do_systemctl("list-%s" % list_what, flags: flags)
|
12
|
+
end
|
13
|
+
|
14
|
+
def common_list_flags
|
15
|
+
["--plain", "--full", "--all"]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class SystemdUnits < Loom::Mods::Module
|
20
|
+
include SystemdCommon
|
21
|
+
include SystemdUnitsCommon
|
22
|
+
|
23
|
+
register_mod :systemd_units
|
24
|
+
|
25
|
+
module Actions
|
26
|
+
def list
|
27
|
+
do_systemctl_list :units
|
28
|
+
end
|
29
|
+
|
30
|
+
def status
|
31
|
+
@units.map do |unit|
|
32
|
+
do_systemctl "status", unit, flags: ["--output=short-unix"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
import_actions Actions
|
38
|
+
end
|
39
|
+
|
40
|
+
class SystemdSockets < SystemdUnits
|
41
|
+
include SystemdCommon
|
42
|
+
include SystemdUnitsCommon
|
43
|
+
|
44
|
+
register_mod :systemd_sockets
|
45
|
+
|
46
|
+
module Actions
|
47
|
+
def list
|
48
|
+
do_systemctl_list :sockets
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
import_actions Actions
|
53
|
+
end
|
54
|
+
|
55
|
+
class SystemdTimers < SystemdUnits
|
56
|
+
include SystemdCommon
|
57
|
+
include SystemdUnitsCommon
|
58
|
+
|
59
|
+
register_mod :systemd_timers
|
60
|
+
|
61
|
+
module Actions
|
62
|
+
def list
|
63
|
+
do_systemctl_list :timers
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
import_actions Actions
|
68
|
+
end
|
69
|
+
end
|
data/scripts/harness.sh
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
#
|
8
8
|
# 1. base64 encode an arbitrary shell script, this is the encoded
|
9
9
|
# script
|
10
|
+
# TODO[P0]: this should be a checksum for the original script!!! Check the code.
|
10
11
|
# 2. get a checksum for the encoded script
|
11
12
|
# 3. send the encoded script and checksum to a shell in another
|
12
13
|
# process (local or remote) to invoke the encoded script via this
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# !!! NOTE: This will reboot the host it runs on!!!
|
2
|
+
module ErrorHandling
|
3
|
+
include Loom::Pattern
|
4
|
+
|
5
|
+
namespace :err
|
6
|
+
|
7
|
+
desc "Handle SSH disconnection errors"
|
8
|
+
pattern :ssh_disconnect do |loom, facts|
|
9
|
+
if facts[:really_really_reboot]
|
10
|
+
loom.sudo cmd: :reboot
|
11
|
+
else
|
12
|
+
puts "to REALLY reboot set fact[:really_really_reboot] = true"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# All patterns are expected to fail
|
2
|
+
|
3
|
+
desc "Always fails due to return code."
|
4
|
+
pattern :fail_soft do |loom, facts|
|
5
|
+
unless loom << :false
|
6
|
+
loom.x :echo, "i am false"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Always fails due to a hard failure"
|
11
|
+
pattern :fail_hard do |loom, facts|
|
12
|
+
loom.fail "Fail big or not at all"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Expected to fail: Check timeout commands"
|
16
|
+
pattern :timeout_fail do |loom, facts|
|
17
|
+
loom.timeout(:timeout => 1) do
|
18
|
+
loom.x :sleep, 2
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Tests for LoomExt::CoreMods::Package
|
2
|
+
module Files
|
3
|
+
include Loom::Pattern
|
4
|
+
|
5
|
+
desc "Reads a file"
|
6
|
+
pattern :read do |loom, facts|
|
7
|
+
loom.files("/etc/hosts").cat
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Gsubs file text"
|
11
|
+
pattern :gsub do |loom, facts|
|
12
|
+
loom.files("/tmp/garbage").write <<EOS
|
13
|
+
This is a bunch of junk
|
14
|
+
192.123.456.0\t\thostname.xyz
|
15
|
+
EOS
|
16
|
+
|
17
|
+
loom.files("/tmp/garbage")
|
18
|
+
.cat
|
19
|
+
.gsub(pattern: /[\d]{3}/, replace: "xxx")
|
20
|
+
.append("this is something new")
|
21
|
+
.cat
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Chowns a file"
|
25
|
+
pattern :chown do |loom, facts|
|
26
|
+
loom.files("/tmp/chown.me")
|
27
|
+
.touch
|
28
|
+
.append("this file will be owned by root")
|
29
|
+
|
30
|
+
loom.sudo do
|
31
|
+
loom.files("/tmp/chown.me").chown user: :root
|
32
|
+
loom.x :ls, "-lZ", "/tmp/chown.me"
|
33
|
+
|
34
|
+
loom.files("/tmp/chown.me").chown user: :root, group: :root
|
35
|
+
end
|
36
|
+
|
37
|
+
loom.sudo { loom.exec :rm, "/tmp/chown.me" }
|
38
|
+
end
|
39
|
+
end
|
data/spec/.loom/net.loom
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Net
|
2
|
+
include Loom::Pattern
|
3
|
+
|
4
|
+
desc "tests the net package, with_net check"
|
5
|
+
pattern :check_net do |loom, facts|
|
6
|
+
unless loom.net(check_host: '127.0.0.1').has_net?
|
7
|
+
loom.fail 'can not ping localhost'
|
8
|
+
end
|
9
|
+
|
10
|
+
has_local_net = false
|
11
|
+
loom.net(check_host: '127.0.0.1').with_net do
|
12
|
+
has_local_net = true
|
13
|
+
end
|
14
|
+
loom.fail "should have local net" unless has_local_net
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "expected check_net failures"
|
18
|
+
pattern :check_net_fail do |loom, facts|
|
19
|
+
loom.net(timeout: 2, check_host: '1.1.1.1').check_net
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Tests patterns nested at deeper module levels with contextual let, before, and
|
2
|
+
# after hooks. Verifies hook order and contexts are set correctly.
|
3
|
+
module PatternContext
|
4
|
+
module Parent
|
5
|
+
include Loom::Pattern
|
6
|
+
|
7
|
+
with_facts :outer_fact => :outer, :replaced => :original
|
8
|
+
|
9
|
+
before do
|
10
|
+
puts "Test::Parent => before"
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
puts "Test::Parent => after"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Checks facts on a parent pattern"
|
18
|
+
pattern :check_facts do |loom, facts|
|
19
|
+
unless facts[:outer_fact] == :outer
|
20
|
+
raise "expected outer fact => #{facts[:outer_fact]}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:a_let_key) { "the value" }
|
25
|
+
let(:a_fact_based_let) { |facts| facts[:outer_fact].to_s + "/let" }
|
26
|
+
let(:a_referencing_let) { a_let_key + " referenced" }
|
27
|
+
|
28
|
+
desc "Checks let defines"
|
29
|
+
pattern :check_lets do |loom, facts|
|
30
|
+
raise "bad let :a_let_key" unless a_let_key == "the value"
|
31
|
+
raise "bad let :a_fact_based_let" unless a_fact_based_let == "outer/let"
|
32
|
+
|
33
|
+
unless a_referencing_let == "the value referenced"
|
34
|
+
raise "bad let :a_referencing_let => #{a_referencing_let}"
|
35
|
+
end
|
36
|
+
|
37
|
+
puts "a_let_key: %s" % a_let_key
|
38
|
+
puts "a_fact_based_let: %s" % a_fact_based_let
|
39
|
+
end
|
40
|
+
|
41
|
+
module Child
|
42
|
+
include Loom::Pattern
|
43
|
+
|
44
|
+
with_facts :inner_fact => :inner, :replaced => :override
|
45
|
+
let(:a_let_key) { |facts| facts[:inner_fact].to_s + " overrides parent" }
|
46
|
+
|
47
|
+
before do
|
48
|
+
puts "Test::Parent::Child => before"
|
49
|
+
end
|
50
|
+
|
51
|
+
after do
|
52
|
+
puts "Test::Parent::Child => after"
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Check let overrides"
|
56
|
+
pattern :check_let_overrides do |loom, facts|
|
57
|
+
raise "bad let :a_let_key" unless a_let_key == "inner overrides parent"
|
58
|
+
raise "bad let :a_fact_based_let" unless a_fact_based_let == "outer/let"
|
59
|
+
|
60
|
+
puts "child a_let_key: %s" % a_let_key
|
61
|
+
puts "child a_fact_based_let: %s" % a_fact_based_let
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "Checks inherited facts on a cihld pattern"
|
65
|
+
pattern :check_facts do |loom, facts|
|
66
|
+
unless facts[:inner_fact] == :inner
|
67
|
+
raise "expected inner fact => #{facts[:inner_fact]}"
|
68
|
+
end
|
69
|
+
unless facts[:outer_fact] == :outer
|
70
|
+
raise "expected outer fact => #{facts[:outer_fact]}"
|
71
|
+
end
|
72
|
+
unless facts[:replaced] == :override
|
73
|
+
raise "expected replaced fact => #{facts[:replaced_fact]}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end # Child
|
77
|
+
end # Parent
|
78
|
+
end #PatternContext
|
data/spec/.loom/pkg.loom
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Tests for LoomExt::CoreMods::Package
|
2
|
+
module Package
|
3
|
+
include Loom::Pattern
|
4
|
+
|
5
|
+
namespace :pkg
|
6
|
+
|
7
|
+
before do |loom, facts|
|
8
|
+
puts "#{self} in before"
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
puts "#{self} in after"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Updates the default package manager cache"
|
16
|
+
pattern :update_cache do |loom, facts|
|
17
|
+
loom.sudo { loom.pkg.update_cache }
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Installs Apache HTTP server"
|
21
|
+
pattern :install_httpd do |loom, facts|
|
22
|
+
loom.sudo do
|
23
|
+
loom.pkg.install 'apache2' unless loom.pkg.installed? 'apache2'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Installs Facter GEM"
|
28
|
+
pattern :install_facter do |loom, facts|
|
29
|
+
loom.sudo do
|
30
|
+
loom.pkg[:gem].ensure_installed :facter
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Shell
|
2
|
+
include Loom::Pattern
|
3
|
+
|
4
|
+
desc "Executes some commands in a subshell"
|
5
|
+
pattern :subshell do |loom, facts|
|
6
|
+
loom << :"(echo $$; echo $BASHPID; whoami)"
|
7
|
+
loom << :"(sudo -i -u root whoami)"
|
8
|
+
|
9
|
+
loom.local << :"(echo $$; echo $BASHPID; whoami)"
|
10
|
+
# loom.local << "(sudo -i -u root whoami)"
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Tests nested sudo scenarios"
|
14
|
+
pattern :sudo do |loom, facts|
|
15
|
+
loom.sudo user: "root" do
|
16
|
+
loom << :pwd
|
17
|
+
loom << :whoami
|
18
|
+
loom.exec :touch, "loom.file"
|
19
|
+
|
20
|
+
loom.sudo do
|
21
|
+
loom << :whoami
|
22
|
+
loom << :pwd
|
23
|
+
loom.x :touch, "root.file"
|
24
|
+
|
25
|
+
loom.user.add_system_user :postgres, uid: 999
|
26
|
+
loom.sudo user: :postgres do
|
27
|
+
loom << :whoami
|
28
|
+
loom.cd "/tmp" do
|
29
|
+
loom << :pwd
|
30
|
+
loom.x :touch, "postgres.file"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
loom.user.remove :postgres
|
34
|
+
|
35
|
+
loom.x :touch, "root.file2"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
loom.cd "/tmp" do
|
40
|
+
loom << :pwd
|
41
|
+
loom.sudo user: :root, cmd: :pwd do loom << :pwd end
|
42
|
+
loom << :pwd
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# TODO: add in test verifications that these tests are actually doing what
|
2
|
+
# they're supposed to do.
|
3
|
+
|
4
|
+
module Smoke
|
5
|
+
include Loom::Pattern
|
6
|
+
|
7
|
+
desc "Prints some known facts"
|
8
|
+
report :three_facts do |loom, facts|
|
9
|
+
facts
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Reports `uptime` status"
|
13
|
+
pattern :uptime do |loom, facts|
|
14
|
+
loom << :uptime
|
15
|
+
loom << :hostname
|
16
|
+
loom.local << :hostname
|
17
|
+
end
|
18
|
+
#produces { pkg.installed? :httpd }
|
19
|
+
|
20
|
+
desc "cd's to the /etc directory and runs `pwd`"
|
21
|
+
pattern :cd do |loom, facts|
|
22
|
+
loom.cd "/etc" do
|
23
|
+
loom << :pwd
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "tests return codes from wrapped commands"
|
28
|
+
pattern :wrap_returns do |loom, facts|
|
29
|
+
# using loom.time as a proxy for Shell::Core#wrap here
|
30
|
+
loom.time do
|
31
|
+
raise "wrapped true is not true" unless loom.test :true
|
32
|
+
raise "wrapped false is not false" if loom.test :false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Tests a condition."
|
37
|
+
pattern :test do |loom, facts|
|
38
|
+
unless loom.test :false
|
39
|
+
loom.x :echo, "i tested false"
|
40
|
+
end
|
41
|
+
|
42
|
+
if loom.test :true
|
43
|
+
loom.x :echo, "i tested true"
|
44
|
+
end
|
45
|
+
|
46
|
+
if loom.test :which, "bash"
|
47
|
+
loom.x :echo, "has bash"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Tests a grep condition."
|
52
|
+
pattern :match do |loom, facts|
|
53
|
+
if loom.files("/etc/hosts").match? :pattern => "aldsfja;ldjf"
|
54
|
+
loom.fail "should not match garbage"
|
55
|
+
else
|
56
|
+
loom.x :echo, "I didnt match garbage"
|
57
|
+
end
|
58
|
+
|
59
|
+
unless loom.files("/etc/hosts").match? :pattern => "localhost"
|
60
|
+
loom.fail "should match localhost"
|
61
|
+
else
|
62
|
+
loom.x :echo, "I did match my target"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "Wrapped time commands"
|
68
|
+
pattern :time do |loom, facts|
|
69
|
+
loom.time do
|
70
|
+
loom.x :echo, :hi
|
71
|
+
loom.x :sleep, 2
|
72
|
+
end
|
73
|
+
end
|