loom-core 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/bin/loom +5 -1
  4. data/lib/loom/config.rb +10 -3
  5. data/lib/loom/facts/fact_set.rb +7 -1
  6. data/lib/loom/mods/module.rb +3 -4
  7. data/lib/loom/pattern/definition_context.rb +1 -1
  8. data/lib/loom/pattern/dsl.rb +113 -32
  9. data/lib/loom/pattern/reference_set.rb +7 -7
  10. data/lib/loom/runner.rb +8 -0
  11. data/lib/loom/shell/api.rb +2 -0
  12. data/lib/loom/version.rb +1 -1
  13. data/lib/loomext/corefacts/system_info_provider.rb +2 -1
  14. data/lib/loomext/coremods/all.rb +2 -1
  15. data/lib/loomext/coremods/exec.rb +10 -0
  16. data/lib/loomext/coremods/git.rb +19 -0
  17. data/lib/loomext/coremods/package/adapter.rb +1 -1
  18. data/lib/loomext/coremods/systemd.rb +1 -0
  19. data/lib/loomext/coremods/systemd/all.rb +2 -0
  20. data/lib/loomext/coremods/{system.rb → systemd/systemd.rb} +19 -5
  21. data/lib/loomext/coremods/systemd/systemd_units.rb +69 -0
  22. data/scripts/harness.sh +1 -0
  23. data/spec/.loom/error_handling.loom +15 -0
  24. data/spec/.loom/fail.loom +20 -0
  25. data/spec/.loom/files.loom +39 -0
  26. data/spec/.loom/net.loom +21 -0
  27. data/spec/.loom/pattern_context.loom +78 -0
  28. data/spec/.loom/pkg.loom +33 -0
  29. data/spec/.loom/shell.loom +46 -0
  30. data/spec/.loom/test.loom +73 -0
  31. data/spec/.loom/user.loom +29 -0
  32. data/spec/.loom/vms.loom +22 -0
  33. data/spec/loom/facts/fact_set_spec.rb +57 -0
  34. data/spec/loom/pattern/dsl_spec.rb +58 -9
  35. data/spec/loom/shell/harness_blob_spec.rb +1 -1
  36. data/spec/loom/shell/harness_command_builder_spec.rb +1 -1
  37. data/spec/loomext/coremods/systemd_spec.rb +31 -0
  38. data/spec/runloom.sh +12 -19
  39. data/spec/scripts/harness_spec.rb +1 -1
  40. data/spec/shared/loom_internals_helper.rb +41 -0
  41. data/spec/spec_helper.rb +5 -1
  42. data/spec/systemd.loom +22 -0
  43. data/spec/test_loom_spec.rb +95 -17
  44. data/test +2 -0
  45. metadata +26 -5
  46. 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
@@ -40,7 +40,7 @@ module LoomExt::CoreMods
40
40
  end
41
41
 
42
42
  def install(pkg_name)
43
- loom << "gem install #{pkg_name}"
43
+ loom.x :gem, :install, pkg_name
44
44
  end
45
45
  end
46
46
 
@@ -0,0 +1 @@
1
+ require_relative "systemd/all"
@@ -0,0 +1,2 @@
1
+ require_relative "systemd"
2
+ require_relative "systemd_units"
@@ -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
- status(unit).match? /^\s+Active:\sactive\s/
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
@@ -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
@@ -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
@@ -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