loom-core 0.0.1 → 0.0.2

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: '00595d8a3c27f3c3a2567849e6d188c68a3c5914646238f0009767bff5769687'
4
- data.tar.gz: 1988e1d88027c87309183db5355a2167f46ef2c48efcde7d5d143daf04011ea3
3
+ metadata.gz: fca395ca95a28376331f0163c1748fcd3eb083c2f6d677627edb04a795c5b858
4
+ data.tar.gz: 29fc16366271bfe121eb57b7315daa87a6d8017210d41a061cdecc6665bb26bc
5
5
  SHA512:
6
- metadata.gz: a48f5d6d82ec87da2c8e0dca0107602a434f8e4d8f42e1eb5d4d5638106aea1733836745d91db52f497b0eb4d2b9812909a42e9aef10a6408a26b23cb227758c
7
- data.tar.gz: dc23a63efd9405c7834911e66a709f944793e8b9bca62858e0a86864f999d0d8e942a21f9bda9893bd2672291806205d0b7e752cb9dbe70e0b2854630434bb97
6
+ metadata.gz: 291da2a4d0b793019dd65c511dfc1caa113a3a12c3a7f2ab12e9b991a8e5ce09b4fba97fb150b15b01edd6c67f0ea0536f16fc00384bf80c6ec54f9b21c9c1c2
7
+ data.tar.gz: 0b18248b8cf5583a48fb3844c39e15b0db216ad6c6ab62a160b5013d05e6f8931bbf165c35c7e107ce3de28a88e7227662480fd263f11031fb5356da2729c5a6
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  pkg
2
+ loom-core-0.0.1.gem
data/lib/loom/dsl.rb CHANGED
@@ -31,6 +31,7 @@ module Loom
31
31
  sshkit_backend = self
32
32
 
33
33
  begin
34
+ # TODO: document the reciever of this yield
34
35
  yield sshkit_backend, host_spec
35
36
  rescue SocketError => e
36
37
  Loom.log.error "error connecting to host => #{host_spec.hostname}"
@@ -53,6 +54,7 @@ module Loom
53
54
  end
54
55
  end
55
56
 
57
+ # TODO: Why did I make this "shadow" class?
56
58
  class SSHKitDSLShadow
57
59
  extend SSHKit::DSL
58
60
  end
@@ -11,6 +11,8 @@ module Loom
11
11
  attr_accessor :disabled
12
12
  attr_reader :sshkit_host
13
13
 
14
+ # TODO: change this to take an sshkit_host and make parse public. Stop calling parse from the
15
+ # ctor.
14
16
  def initialize(host_string)
15
17
  @sshkit_host = parse host_string
16
18
  end
@@ -26,7 +28,15 @@ module Loom
26
28
 
27
29
  private
28
30
  def parse(host_string)
29
- SSHKit::Host.new host_string
31
+ host = SSHKit::Host.new host_string
32
+ host.ssh_options = {
33
+ :auth_methods => ['publickey'],
34
+ :keys => ["~/.ssh/id_esd25519_2"],
35
+ # :verbose => :debug,
36
+ }
37
+ Loom.log.debug1(self) { "parsing hoststring[#{host_string}] => #{host}" }
38
+ Loom.log.debug1(self) { "netssh options for host[#{host}] => #{host.netssh_options}" }
39
+ host
30
40
  end
31
41
  end
32
42
  end
@@ -41,11 +41,11 @@ module Loom::Mods
41
41
  bound_action_name = tuple[1]
42
42
 
43
43
  define_method public_action_name do |*args, &block|
44
- # TODO: Effectively this is the API for all mods, but it's burried
45
- # here in the middle of nowhere. Add documentation - or make it
46
- # easier to read.
47
- Loom.log.debug2(self) do
48
- "proxy to mod #{@mod} => #{public_action_name}: #{args} #{block}"
44
+ # TODO[P0]: Effectively this is the API for all mods, but it's
45
+ # burried here in the middle of nowhere. Add documentation - or make
46
+ # it easier to read.
47
+ Loom.log.debug(self) do
48
+ "proxy to mod action: #{public_action_name} => #{bound_action_name}, #{@mod}"
49
49
  end
50
50
 
51
51
  @mod.send bound_action_name, *args, &block
@@ -89,7 +89,7 @@ module Loom::Mods
89
89
  def add_action(action_name, bound_method_name, namespace=nil)
90
90
  if namespace.nil?
91
91
  tuple = [action_name, bound_method_name]
92
- @action_tuples << tuple unless namespace
92
+ @action_tuples << tuple unless namespace
93
93
  else
94
94
  # Adds an action name to a nested ActionMap
95
95
  add_namespace(namespace).add_action action_name, bound_method_name
@@ -40,6 +40,9 @@ module Loom::Mods
40
40
  else
41
41
  Loom.log.debug3(self) { "initing action => #{args}" }
42
42
  init_action *args, &pattern_block
43
+
44
+ # TODO: ooohhh... the action_proxy code path is fucking
45
+ # crazy. ActionProxy needs some documentation.
43
46
  action_proxy
44
47
  end
45
48
  end
@@ -50,6 +53,8 @@ module Loom::Mods
50
53
  Loom.log.debug2(self) { "registered mod => #{name}" }
51
54
 
52
55
  if block_given?
56
+ # TODO: i forget what mod_blocks are. read through, remember, and
57
+ # document them.
53
58
  Loom.log.debug2(self) { "acting as mod_block => #{name}:#{block}" }
54
59
  define_method :mod_block, &block
55
60
  end
@@ -83,6 +88,11 @@ module Loom::Mods
83
88
  def bind_action(action_name, unbound_method, namespace=nil)
84
89
  bound_method_name = [namespace, action_name].compact.join '_'
85
90
 
91
+ # TODO: document why the `define_method` calls in class only operate on
92
+ # the single mod instance, rather than adding each "bound_method_name"
93
+ # (e.g.) to each instance of Module. (actually I think it's because this
94
+ # is executing from the subclass (via import_actions), so it's only that
95
+ # class). in any case, add more docs and code pointers.
86
96
  define_method bound_method_name do |*args, &block|
87
97
  Loom.log.debug1(self) { "exec mod action #{self.class}##{bound_method_name}" }
88
98
 
@@ -44,6 +44,14 @@ module Loom::Pattern
44
44
  report << "Completed in: %01.3fs" % @delta_t
45
45
 
46
46
  cmds.find_all { |cmd| !cmd.is_test }.each do |cmd|
47
+ # TODO: this is a bit confusing for the user... when you cat a file from
48
+ # a loom pattern, the output of a command isn't visible unless -V is
49
+ # specified... not sure what to do here. I don't want to see the output
50
+ # of every command, and I don't really want to pipe more info through
51
+ # the `@shell_session.command_results` (e.g. should_report_result:)?
52
+ #
53
+ # Although.. maybe that's the better API? then the logic here can be
54
+ # moved and strategized per command/result/shell.
47
55
  if !cmd.success? || @loom_config.run_verbose
48
56
  report.concat generate_cmd_report(cmd)
49
57
  end
data/lib/loom/runner.rb CHANGED
@@ -165,8 +165,8 @@ module Loom
165
165
  result_reporter = Loom::Pattern::ResultReporter.new(
166
166
  @loom_config, pattern_ref.slug, hostname, shell_session)
167
167
 
168
- # TODO: This is a crappy mechanism for tracking errors, there should be an
169
- # exception thrown inside of Shell when a command fails and pattern
168
+ # TODO: This is a crappy mechanism for tracking errors (hency my crappy error reporting :( ),
169
+ # there should be an exception thrown inside of Shell when a command fails and pattern
170
170
  # execution should stop. All errors should come from exceptions.
171
171
  run_failure = []
172
172
  begin
@@ -175,7 +175,8 @@ module Loom
175
175
  Loom.log.debug e.backtrace.join "\n\t"
176
176
  run_failure << e
177
177
  ensure
178
- # TODO: this prints out [Result: OK] even if an exception is raised
178
+ # TODO[P0]: this prints out [Result: OK] even if an exception is raised... this is really
179
+ # annoying.
179
180
  result_reporter.write_report
180
181
 
181
182
  # TODO: this is not the correct error condition.
@@ -24,6 +24,10 @@ module Loom::Shell
24
24
 
25
25
  attr_reader :session, :shell_api, :mod_loader, :dry_run
26
26
 
27
+ def is_sudo?
28
+ !@sudo_users.empty?
29
+ end
30
+
27
31
  def local
28
32
  @local ||= LocalShell.new @mod_loader, @session, @dry_run
29
33
  end
@@ -96,6 +100,35 @@ module Loom::Shell
96
100
  end
97
101
  end
98
102
 
103
+ # def sudo(user=nil, *sudo_cmd, &block)
104
+ # # I'm trying to work around crappy double escaping issues caused by
105
+ # # sudo_legacy... but I'm failing
106
+ # if block_given?
107
+ # # TODO: this shit is broken with these errors:
108
+ # # $ ... 'You cannot switch to user '' using sudo, please check the sudoers file'
109
+ # #
110
+ # # Loom.log.debug3(self) { "sudo with SSHKit::Backend+as+" }
111
+ # # @sshkit_backend.as user, &block
112
+
113
+ # # Aside from probably being unsafe... this implementation leads to a
114
+ # # hung terminal after switching to root.... sigh....
115
+ # #
116
+ # # Loom.log.warn(self) { "fix sudo... this doesn't seem safe" }
117
+ # # execute "sudo", "su", user
118
+ # # begin
119
+ # # yield
120
+ # # ensure
121
+ # # execute "exit"
122
+ # # end
123
+
124
+ # Loom.log.debug3(self) { "sudo legacy... the other way" }
125
+ # sudo_stack_and_wrap(user, *sudo_cmd, &block)
126
+ # else
127
+ # Loom.log.debug3(self) { "sudo legacy" }
128
+ # sudo_stack_and_wrap(user, *sudo_cmd)
129
+ # end
130
+ # end
131
+
99
132
  def cd(path, &block)
100
133
  Loom.log.debug1(self) { "cd => #{path} #{block}" }
101
134
 
@@ -124,6 +157,10 @@ module Loom::Shell
124
157
  execute cmd
125
158
  end
126
159
 
160
+ def upload(local_path, remote_path)
161
+ @sshkit_backend.upload! local_path, remote_path
162
+ end
163
+
127
164
  def execute(*cmd_parts, is_test: false, **cmd_opts)
128
165
  cmd_parts.compact!
129
166
  raise "empty command passed to execute" if cmd_parts.empty?
@@ -159,9 +196,10 @@ module Loom::Shell
159
196
  "[%s]:$ %s" % [prompt_label, output]
160
197
  end
161
198
 
162
- def execute_internal(*cmd_parts, piped_cmds: [])
199
+ def execute_internal(*cmd_parts, pipe_to: [])
163
200
  primary_cmd = create_command *cmd_parts
164
- piped_cmds = piped_cmds.map { |cmd_parts| CmdWrapper.new *cmd_parts }
201
+ # TODO: where is piped_cmds used?
202
+ piped_cmds = pipe_to.map { |cmd_parts| CmdWrapper.new *cmd_parts }
165
203
 
166
204
  cmd = CmdPipeline.new([primary_cmd].concat(piped_cmds)).to_s
167
205
  # Tests if the command looks like "echo\ hi", the trailing slash after
@@ -187,9 +225,13 @@ module Loom::Shell
187
225
  # @return [String|Loom::Shell::CmdWrapper]
188
226
  def create_command(*cmd_parts)
189
227
  cmd_wrapper = if cmd_parts.is_a? CmdWrapper
228
+ Loom.log.debug3(self) { "existing cmd from args => #{cmd_parts}" }
190
229
  cmd_parts
230
+ elsif cmd_parts[0].is_a? CmdWrapper
231
+ Loom.log.debug3(self) { "existing cmd from args[0] => #{cmd_parts[0]}" }
232
+ cmd_parts[0]
191
233
  else
192
- Loom.log.debug3(self) { "new cmd from parts => #{cmd_parts}" }
234
+ Loom.log.debug3(self) { "new cmd from args => #{cmd_parts}" }
193
235
  CmdWrapper.new *cmd_parts
194
236
  end
195
237
 
@@ -0,0 +1,168 @@
1
+ # 10/21/2018: I resurrected this from an auto save file from a LOONNGGGG time
2
+ # ago., not really sure exactly what the original purpose is, but it has the
3
+ # code for uploading the harness script. I believe this was working at one
4
+ # point, but that was long ago
5
+
6
+ module Loom
7
+
8
+ # Ensures loom is setup to run on the remote.
9
+ # - creates the boostrap loom directory
10
+ # - uploads the harness
11
+ # - creates a directoy for loom execution logging
12
+ class HostSession
13
+
14
+ HISTORY_FILE = "command.log"
15
+
16
+ # @param [Loom::HostSpec] host_spec
17
+ # @param [Loom::Config] loom_config
18
+ # @param [SSHKit::Backend::Abstract] sshkit_backend
19
+ def initialize(host_spec, loom_config, sshkit_backend)
20
+ @host_spec = host_spec
21
+ @sshkit_backend = sshkit_backend
22
+ @loom_config = loom_config
23
+
24
+ @remote_loom_root = loom_config.bootstrap_loom_root
25
+ @loom_user = loom_config.loom_user
26
+
27
+ @session_name = "session.%d" % Time.now.to_i
28
+ @disabled = false
29
+ end
30
+
31
+ attr_reader :session_name
32
+
33
+ def bootstrap
34
+ ensure_loom_remote_dirs
35
+ ensure_harness_uploaded
36
+ log_to_command_history "begin loom execution"
37
+ log_to_command_history "start: " + Time.now.to_i.to_s
38
+ end
39
+
40
+ def disabled?
41
+ @disabled
42
+ end
43
+
44
+ # @param [Loom::Pattern::Reference] pattern_ref
45
+ # @return [Loom::Pattern::ExecResult]
46
+ def execute_pattern(pattern_ref)
47
+ shell = create_shell
48
+
49
+ shell_session = shell.session
50
+ result_reporter = Loom::Pattern::ResultReporter.new(
51
+ @loom_config, pattern_ref.slug, hostname, shell_session)
52
+
53
+ # TODO: This is a crappy mechanism for tracking errors, there should be an
54
+ # exception thrown inside of Shell when a command fails and pattern
55
+ # execution should stop. All errors should come from exceptions.
56
+ run_failure = []
57
+ begin
58
+ fact_set = collect_facts_for_host
59
+ pattern_ref.call(shell.shell_api, fact_set)
60
+ rescue => e
61
+ handle_host_failure e
62
+ ensure
63
+ # TODO: this prints out [Result: OK] even if an exception is raised
64
+ result_reporter.write_report
65
+
66
+ # TODO: this is not the correct error condition.
67
+ unless shell_session.success?
68
+ run_failure << result_reporter.failure_summary
69
+ handle_host_failure result_reporter.failure_summary
70
+ end
71
+ @result_reports << result_reporter
72
+ @run_failures << run_failure unless run_failure.empty?
73
+ end
74
+ end
75
+
76
+ def handle_host_failure(error_or_message=nil)
77
+ Loom.log.debug { "handling host failure => #{hostname}" }
78
+ if error_or_message.respond_to? :backtrace
79
+ Loom.log.debug { e.backtrace.join "\n\t" }
80
+ end
81
+
82
+ message = if error_or_message.respond_to? :message
83
+ error_or_message.message
84
+ else
85
+ error_or_message
86
+ end
87
+
88
+ failure_strategy = @loom_config.run_failure_strategy.to_sym
89
+ case failure_strategy
90
+ when :exclude_host
91
+ Loom.log.warn "disabling host due to failure => #{message}"
92
+ @disabled = true
93
+ when :fail_fast
94
+ Loom.log.error "fail fast host failure => #{message}"
95
+ raise FailFastExecutionError, message
96
+ when :cowboy
97
+ # This is mostly for testing, don't use in prod.
98
+ Loom.log.warn "cowboy failure, wooohooo => #{message}"
99
+ else
100
+ raise ConfigError, "unknown failure_strategy: #{failure_stratgy}"
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ # @return [String]
107
+ def script_path
108
+ File.join @remote_loom_root, "scripts"
109
+ end
110
+
111
+ # @return [String]
112
+ def session_path
113
+ File.join @remote_loom_root, "run", @session_name
114
+ end
115
+
116
+ # @return [String]
117
+ def history_file
118
+ File.join session_name, HISTORY_FILE
119
+ end
120
+
121
+ def ensure_loom_remote_dirs
122
+ @sshkit_backend.as user: :root do
123
+ @sshkit_backend.execute :mkdir, '-p', @remote_loom_root
124
+ @sshkit_backend.execute :mkdir, '-p', script_path
125
+ @sshkit_backend.execute :mkdir, '-p', session_path
126
+
127
+ chown_opts = "-R %s:%s %s" % [@loom_user, @loom_user, @remote_loom_root]
128
+ @sshkit_backend.execute :chown, chown_opts
129
+ end
130
+ end
131
+
132
+ def ensure_harness_uploaded
133
+ @sshkit_backend.upload! Loom::Resource::HARNESS, script_path
134
+ end
135
+
136
+ def create_command_history
137
+ @sshkit_backend :touch, history_file
138
+ end
139
+
140
+ def write_to_command_history(text)
141
+ @sshkit_backend :cat, "<<EOS\n#{text}\nEOS", ">>", history_file
142
+ end
143
+
144
+ def log_to_command_history(text)
145
+ write_to_command_history(
146
+ "[%s] %s: #{text}" % [Time.now.utc.to_s, hostname])
147
+ end
148
+
149
+ # The naming inconsistency w/ the missing underscore in hostname (vs
150
+ # host_spec, host_session, etc...) is confusing, but that's *nix's fault.
151
+ def hostname
152
+ @host_spec.hostname
153
+ end
154
+
155
+ def collect_facts_for_host
156
+ Loom.log.info "collecting facts for host => #{hostname}"
157
+ Loom::Facts.fact_set(@host_spec, create_shell, @loom_config)
158
+ end
159
+
160
+ def create_shell
161
+ Loom::Shell.create create_mod_loader, @sshkit_backend
162
+ end
163
+
164
+ def create_mod_loader
165
+ Loom::Mods::ModLoader.new loom_config
166
+ end
167
+ end
168
+ end
data/lib/loom/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Loom
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -10,4 +10,5 @@ require_relative "files"
10
10
  require_relative "net"
11
11
  require_relative "user"
12
12
  require_relative "package/package"
13
+ require_relative "system"
13
14
  require_relative "vm/all"
@@ -31,11 +31,17 @@ module LoomExt::CoreMods
31
31
  end
32
32
 
33
33
  class Sudo < Loom::Mods::Module
34
- register_mod :sudo do |user: nil, cmd: nil, &block|
34
+ register_mod :sudo do |user: :root, cmd: nil, &block|
35
35
  shell.sudo user, cmd, &block
36
36
  end
37
37
  end
38
38
 
39
+ class SudoCheck < Loom::Mods::Module
40
+ register_mod :is_sudo? do
41
+ shell.is_sudo?
42
+ end
43
+ end
44
+
39
45
  class Test < Loom::Mods::Module
40
46
  register_mod :test do |*cmd|
41
47
  shell.test *cmd
@@ -47,4 +53,10 @@ module LoomExt::CoreMods
47
53
  raise FailError, message
48
54
  end
49
55
  end
56
+
57
+ class Upload < Loom::Mods::Module
58
+ register_mod :upload do |local_path, remote_path|
59
+ shell.upload local_path, remote_path
60
+ end
61
+ end
50
62
  end
@@ -3,6 +3,8 @@ module LoomExt::CoreMods
3
3
 
4
4
  register_mod :files
5
5
 
6
+ # TODO: document loom file statements like:
7
+ # `loom.files("some", "different/paths").cat`
6
8
  def init_action(paths)
7
9
  @paths = [paths].flatten.compact
8
10
  end
@@ -45,6 +47,12 @@ module LoomExt::CoreMods
45
47
  end
46
48
  end
47
49
 
50
+ def mv(new_path)
51
+ each_path do |p|
52
+ shell.capture :mv, p, new_path
53
+ end
54
+ end
55
+
48
56
  def match?(pattern: /./)
49
57
  all = true
50
58
  each_path do |p|
@@ -80,20 +88,70 @@ module LoomExt::CoreMods
80
88
  each_path :action => :mkdir, :flags => flags
81
89
  end
82
90
 
91
+ def ensure_line(line, sudo: false)
92
+ if loom.is_sudo?
93
+ Loom.log.warn "do not use files.ensure_line in sudo due to poor command escaping" +
94
+ ": use files.ensure_line and pass sudo: true"
95
+ end
96
+
97
+ each_path do |p|
98
+ file = shell.capture :cat, p
99
+
100
+ unless file.match(line)
101
+ if sudo
102
+ sudo_append(line)
103
+ else
104
+ append(line)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ # this is a hack to accomodate append being f'd inside sudo blocks
111
+ def sudo_append(text="")
112
+ if text.index "\n"
113
+ Loom.log.warn "append lines individually until cmd escaping is fixed.... "
114
+ end
115
+
116
+ each_path do |p|
117
+ text.each_line do |line|
118
+ loom.x "/bin/echo", "-e", line, :pipe_to => [[:sudo, :tee, "-a", p]]
119
+ end
120
+ end
121
+ end
122
+
83
123
  def append(text="")
124
+ if text.index "\n"
125
+ Loom.log.warn "append lines individually until cmd escaping is fixed.... "
126
+ end
127
+
128
+ if loom.is_sudo?
129
+ Loom.log.warn "do not use files.append in sudo" +
130
+ ": use files.sudo_append due to poor command escaping"
131
+ end
132
+
84
133
  each_path do |p|
85
- loom.test "[ -f #{p} ]"
134
+ # TODO: this shit is broken when escaped in a sudo command. This is
135
+ # why I began work on the harness.
136
+ # $ cd /home/pi; sudo -u root -- /bin/sh -c "/bin/echo -e 192.168.1.190 rp0\''; '\'" | tee -a /etc/hosts
137
+ #
138
+ text.each_line do |line|
139
+ loom.x :"/bin/echo", "-e", line, :pipe_to => [[:tee, "-a", p]]
140
+ end
86
141
 
87
- redirect = Loom::Shell::CmdRedirect.append_stdout p
88
- cmd = Loom::Shell::CmdWrapper.new(
89
- :"/bin/echo", "-e", text, redirect: redirect)
90
- shell.execute cmd
142
+ # TODO: fix this broken shit w/ the harness, CmdRedirect and
143
+ # CmdWrapper are dogshit. This was an escaping attempt before harness
144
+ # script.
145
+ #
146
+ # redirect = Loom::Shell::CmdRedirect.append_stdout p
147
+ # cmd = Loom::Shell::CmdWrapper.new(
148
+ # :"/bin/echo", "-e", text, redirect: redirect)
91
149
  end
92
150
  end
93
151
 
94
152
  def write(text="")
95
153
  each_path do |p|
96
- loom.x :"/bin/echo", "-e", text, :piped_cmds => [[:tee, p]]
154
+ loom.x :"/bin/echo", "-e", text, :pipe_to => [[:tee, p]]
97
155
  end
98
156
  end
99
157
 
@@ -54,7 +54,8 @@ module LoomExt::CoreMods
54
54
  class AptAdapter < DpkgAdapter
55
55
 
56
56
  def install(pkg_name)
57
- loom.net.with_net { loom << "echo apt-get install #{pkg_name}" }
57
+ loom.x "apt-get", "-y", "install", pkg_name
58
+ # loom.net.with_net { loom << "echo apt-get install #{pkg_name}" }
58
59
  end
59
60
 
60
61
  def uninstall(pkg_name)
@@ -62,11 +63,14 @@ module LoomExt::CoreMods
62
63
  end
63
64
 
64
65
  def update_cache
65
- loom.net.with_net { loom << "apt update" }
66
+ # loom.net.with_net { loom << "apt update" }
67
+ loom.x "apt", "-y", "update"
66
68
  end
67
69
 
68
- def upgrade(pkg_name)
69
- loom.net.with_net { loom << "apt upgrade" }
70
+ def upgrade(pkg_name = nil)
71
+ # loom.net.with_net { loom << "apt upgrade" }
72
+ args = ["apt-get", "-y", "upgrade", pkg_name].compact
73
+ loom.x(*args)
70
74
  end
71
75
  end
72
76
 
@@ -0,0 +1,52 @@
1
+ module LoomExt::CoreMods
2
+
3
+ class Systemd < Loom::Mods::Module
4
+
5
+ register_mod :systemd
6
+
7
+ def do_systemctl(action, *args)
8
+ shell.execute "systemctl", action, *args
9
+ end
10
+
11
+ module Actions
12
+
13
+ def is_loaded?(unit)
14
+ status(unit).match? /^\s+Loaded:\sloaded\s/
15
+ end
16
+
17
+ def is_active?(unit)
18
+ status(unit).match? /^\s+Active:\sactive\s/
19
+ end
20
+
21
+ def status(unit)
22
+ do_systemctl "status", unit
23
+ end
24
+
25
+ def enable(unit)
26
+ do_systemctl "enable", unit
27
+ end
28
+
29
+ def start(unit)
30
+ do_systemctl "start", unit
31
+ end
32
+
33
+ def disable(unit)
34
+ do_systemctl "disable", unit
35
+ end
36
+
37
+ def restart(unit)
38
+ do_systemctl "restart", unit
39
+ end
40
+
41
+ def stop(unit)
42
+ do_systemctl "stop", unit
43
+ end
44
+
45
+ def link(path)
46
+ do_systemctl "link", path
47
+ end
48
+ end
49
+ end
50
+
51
+ Systemd.import_actions Systemd::Actions
52
+ end
@@ -13,7 +13,7 @@ module LoomExt::CoreMods::VM
13
13
  end
14
14
 
15
15
  def check_running(vm)
16
- loom.test "vboxmanage list runningvms".split, :piped_cmds => [
16
+ loom.test "vboxmanage list runningvms".split, :pipe_to => [
17
17
  "grep \"#{vm}\"".split
18
18
  ]
19
19
  end
data/loom.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.add_dependency 'sshkit', '~> 1.11'
19
19
  s.add_dependency 'commander', '~> 4.4'
20
20
 
21
+ # *** Obsolete, see new issue below ***
21
22
  # Need net-ssh beta and its explicit requirements until for ed25519
22
23
  # elliptic curve key support
23
24
  # https://github.com/net-ssh/net-ssh/issues/214
@@ -26,9 +27,13 @@ Gem::Specification.new do |s|
26
27
  # release due to net-scp gem dependencies.
27
28
  # I can manually `gem install net-ssh --version 4.0.0.beta3` for now.
28
29
  # s.add_dependency 'net-ssh', '>= 4.0.0.beta3'
29
- s.add_dependency 'net-ssh', '>= 3'
30
+ s.add_dependency 'net-ssh', '>= 5'
30
31
  s.add_dependency 'rbnacl-libsodium', '1.0.10'
31
- s.add_dependency 'bcrypt_pbkdf', '1.0.0.alpha1'
32
+ s.add_dependency 'bcrypt_pbkdf', ">= 1.0", "< 2.0"
33
+
34
+ # New net-ssh requiremetns for ed25519
35
+ # https://github.com/net-ssh/net-ssh/issues/565
36
+ s.add_dependency 'ed25519', '>=1.0', '<2.0'
32
37
 
33
38
  s.add_development_dependency 'bundler', '~> 1.13'
34
39
  s.add_development_dependency 'rake', '~> 11.3'
data/scripts/harness.sh CHANGED
@@ -28,7 +28,8 @@
28
28
  # EOS
29
29
  #
30
30
  # There are 2 different shells that the harness deals with. The
31
- # harness shell, and the command shell.
31
+ # harness shell, and the command shell. The point being, to isolate
32
+ # each environment and be independent of the other.
32
33
  #
33
34
  # The harness shell is the shell used to run the harness script (this
34
35
  # file). Only POSIX features are supported in the harness
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loom-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erick Johnson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-27 00:00:00.000000000 Z
11
+ date: 2018-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sshkit
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '3'
47
+ version: '5'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3'
54
+ version: '5'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rbnacl-libsodium
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +70,42 @@ dependencies:
70
70
  name: bcrypt_pbkdf
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '='
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ - - "<"
74
77
  - !ruby/object:Gem::Version
75
- version: 1.0.0.alpha1
78
+ version: '2.0'
76
79
  type: :runtime
77
80
  prerelease: false
78
81
  version_requirements: !ruby/object:Gem::Requirement
79
82
  requirements:
80
- - - '='
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '1.0'
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: '2.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: ed25519
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '1.0'
96
+ - - "<"
97
+ - !ruby/object:Gem::Version
98
+ version: '2.0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '1.0'
106
+ - - "<"
81
107
  - !ruby/object:Gem::Version
82
- version: 1.0.0.alpha1
108
+ version: '2.0'
83
109
  - !ruby/object:Gem::Dependency
84
110
  name: bundler
85
111
  requirement: !ruby/object:Gem::Requirement
@@ -213,6 +239,7 @@ files:
213
239
  - lib/loom/shell/cmd_result.rb
214
240
  - lib/loom/shell/cmd_wrapper.rb
215
241
  - lib/loom/shell/core.rb
242
+ - lib/loom/shell/harness/session.rb
216
243
  - lib/loom/shell/harness_blob.rb
217
244
  - lib/loom/shell/harness_command_builder.rb
218
245
  - lib/loom/shell/session.rb
@@ -229,6 +256,7 @@ files:
229
256
  - lib/loomext/coremods/net.rb
230
257
  - lib/loomext/coremods/package/adapter.rb
231
258
  - lib/loomext/coremods/package/package.rb
259
+ - lib/loomext/coremods/system.rb
232
260
  - lib/loomext/coremods/user.rb
233
261
  - lib/loomext/coremods/vm.rb
234
262
  - lib/loomext/coremods/vm/all.rb
@@ -268,7 +296,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
268
296
  version: '0'
269
297
  requirements: []
270
298
  rubyforge_project:
271
- rubygems_version: 2.7.6
299
+ rubygems_version: 2.7.7
272
300
  signing_key:
273
301
  specification_version: 4
274
302
  summary: Repeatable management of remote hosts over SSH