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.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11bd9487c4e4752e294000493fe1fe04537f97bfcea9385b1cf16e90c2c79a71
|
4
|
+
data.tar.gz: 926227cb27d65b64103dd0f541acb1f523afdfac2df832180450f1aaaff4397f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 687255010d7a4c709cb95b2022151a95175ae88decb368cfac503dd3bfdb24c677abdbd2ef055f16a80a783bad2d24762ab856bf20c085ec08d1f51734c78c01
|
7
|
+
data.tar.gz: b789683f5aefd5a1997536e3f930f143bb7c12fc24be4e40d10fb0147e0c997c5af84798fad9e2da79d3cdbb7f5fe4a854d3f981f6deabe43ff08ab0092e3c68
|
data/Gemfile.lock
CHANGED
data/bin/loom
CHANGED
@@ -65,9 +65,13 @@ EOS
|
|
65
65
|
Loom.configure { |c| c.inventory_all_hosts = flag }
|
66
66
|
end
|
67
67
|
|
68
|
+
global_option "-L", "Adds localhost to the active inventory" do |flag|
|
69
|
+
Loom.configure { |c| c.inventory_hosts << "localhost" }
|
70
|
+
end
|
71
|
+
|
68
72
|
global_option "-H", "--hosts host1,h2,h3", Array,
|
69
73
|
"Adds HOSTS to the active inventory" do |hosts|
|
70
|
-
Loom.configure { |c| c.inventory_hosts
|
74
|
+
Loom.configure { |c| c.inventory_hosts.concat hosts }
|
71
75
|
end
|
72
76
|
|
73
77
|
global_option "-G", "--groups group1,g2,g3", Array,
|
data/lib/loom/config.rb
CHANGED
@@ -12,6 +12,12 @@ module Loom
|
|
12
12
|
CONFIG_VARS = {
|
13
13
|
:loom_search_paths => ['/etc/loom', File.join(ENV['HOME'], '.loom'), './.loom'],
|
14
14
|
:loom_files => ['site.loom'],
|
15
|
+
:loom_file_patterns => ['*.loom'],
|
16
|
+
|
17
|
+
:loomfile_autoloads => [
|
18
|
+
'loomext/corefacts',
|
19
|
+
'loomext/coremods',
|
20
|
+
],
|
15
21
|
|
16
22
|
:inventory_all_hosts => false,
|
17
23
|
:inventory_hosts => [],
|
@@ -49,6 +55,8 @@ module Loom
|
|
49
55
|
end
|
50
56
|
alias_method :dump, :to_yaml # aliased to dump for debugging purposes
|
51
57
|
|
58
|
+
# TODO: disallow CONFIG_VAR properties named after Config methods.... like
|
59
|
+
# files. this is shitty, but I don't want to do a larger change.
|
52
60
|
def files
|
53
61
|
@file_manager
|
54
62
|
end
|
@@ -68,11 +76,10 @@ module Loom
|
|
68
76
|
private
|
69
77
|
class FileManager
|
70
78
|
|
71
|
-
LOOM_FILE_PATTERNS = ["*.loom"]
|
72
|
-
|
73
79
|
def initialize(config)
|
74
80
|
@loom_search_paths = config.loom_search_paths
|
75
81
|
@loom_files = config.loom_files
|
82
|
+
@loom_file_patterns = config.loom_file_patterns
|
76
83
|
end
|
77
84
|
|
78
85
|
def find(glob_patterns)
|
@@ -80,7 +87,7 @@ module Loom
|
|
80
87
|
end
|
81
88
|
|
82
89
|
def loom_files
|
83
|
-
[@loom_files + search_loom_paths(
|
90
|
+
[@loom_files + search_loom_paths(@loom_file_patterns)].flatten.uniq
|
84
91
|
end
|
85
92
|
|
86
93
|
private
|
data/lib/loom/facts/fact_set.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module Loom::Facts
|
2
2
|
|
3
|
+
class << self
|
4
|
+
def is_empty?(fact_set)
|
5
|
+
EMPTY.equal? fact_set
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
3
9
|
EMPTY = {}
|
4
10
|
class << EMPTY
|
5
11
|
def [](*args)
|
@@ -104,7 +110,7 @@ NB
|
|
104
110
|
v = @fact_map[fact_name.to_sym]
|
105
111
|
dup = v.dup rescue v
|
106
112
|
if dup.nil?
|
107
|
-
EMPTY
|
113
|
+
Loom::Facts::EMPTY
|
108
114
|
else
|
109
115
|
dup
|
110
116
|
end
|
data/lib/loom/mods/module.rb
CHANGED
@@ -19,10 +19,9 @@ module Loom::Mods
|
|
19
19
|
@mods = shell.mod_loader
|
20
20
|
@loom_config = loom_config
|
21
21
|
|
22
|
-
# The action proxy is a facade for the mod provided to
|
23
|
-
# ShellApi (the 'loom' object). The ShellApi calls back to the mod_loader
|
24
|
-
#
|
25
|
-
# action_proxy.
|
22
|
+
# The action proxy is a facade (or is it a proxy? i don't know) for the mod provided to
|
23
|
+
# patterns by the ShellApi (the 'loom' object). The ShellApi calls back to the mod_loader on
|
24
|
+
# method missing which instantiates a new Module object and returns the action_proxy.
|
26
25
|
@action_proxy = self.class.action_proxy self, shell.shell_api
|
27
26
|
@action_args = nil
|
28
27
|
@action_block = nil
|
@@ -45,7 +45,7 @@ module Loom::Pattern
|
|
45
45
|
Loom.log.debug1(self) { "let[:#{let_key}] => #{value}" }
|
46
46
|
|
47
47
|
if value.nil? || value.equal?(Loom::Facts::EMPTY)
|
48
|
-
Loom.log.
|
48
|
+
Loom.log.error "value of let expression[:#{let_key}] is nil"
|
49
49
|
raise NilLetValueError, let_key
|
50
50
|
end
|
51
51
|
scope_object.define_singleton_method(let_key) { value }
|
data/lib/loom/pattern/dsl.rb
CHANGED
@@ -1,36 +1,63 @@
|
|
1
|
-
=begin
|
2
|
-
|
3
1
|
# TODO: DSL extensions:
|
4
|
-
-
|
5
|
-
|
6
|
-
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
2
|
+
# - a way to test and verify pattern execution.... I still don't trust this
|
3
|
+
# enough. this starts with fixing error reporting.
|
4
|
+
# - Pattern+non_idempotent+ marks a pattern as explicitly not idempotent, this
|
5
|
+
# let's additional warnings and checks to be added
|
6
|
+
# - A history module, store a log of each executed command, a hash of the .loom
|
7
|
+
# file, and the requisite facts (the let declarations) for each executed pattern
|
8
|
+
# on the host it executes. /var/log/loom/history? Create this log on startup.
|
9
|
+
# -- add a new set of history commands through the CLI and a history
|
10
|
+
# FactProvider exposing host/loom/pattern_slug execution stats.
|
11
|
+
# - Provide automatic command reversion support with a =Module= DSL that ties in
|
12
|
+
# with local revision history.
|
13
|
+
# -- allow Module actions/mods to define an "undo" command of itself given the
|
14
|
+
# original inputs to the action
|
15
|
+
# -- using the history to pull previous params (let defns) into a revert command.
|
16
|
+
# -- usages of the raw shell, such as `loom.x` and `loom.capture` would be
|
17
|
+
# unsupported. so would accesses to the fact_set in any before/after/pattern
|
18
|
+
# blocks.
|
19
|
+
# -- however patterns that only used let blocks, and used all "revertable"
|
20
|
+
# module methods, could have automatic state reversion and integrity checking
|
21
|
+
# managed.
|
22
|
+
# -- best practices (encouraged through warnings) to be to heavily discourage
|
23
|
+
# uses of loom.execute and loom.capture in .loom files and encourage all
|
24
|
+
# accesses to fact_set be done in let expressions (enforce this maybe?)
|
25
|
+
# -- Later... before/after hooks can ensure the entire loom execution sequence
|
26
|
+
# was "revertable"
|
27
|
+
# - A mechanism to allow mods to register CLI flags and actions. Using an action predicate
|
28
|
+
# mechanisms can add flags at the global or action levels. All CLI flags set config values.
|
29
|
+
# -- Mods can also register for action namespaces similar to git. This is consistent with mod
|
30
|
+
# namespaces on the loom object.
|
31
|
+
# -- Best way is to migrate loom/mods/module and loom/mods/action_proxy into base classes of
|
32
|
+
# themselves. The isolate the shell specific behavior into a subclass of each to preserve the
|
33
|
+
# current behavior. A new "cli" module and "cli" action proxy would enable the implementation.
|
34
|
+
# - Add a phase to the pattern execution sequence to collect calls to factset and loom
|
35
|
+
# objects. Results collected from this ""pre-execute"" can be analyzed for errors, optimization,
|
36
|
+
# success assertions, verification, etc. The loom file then executes in 2 passes, analyze &
|
37
|
+
# execute.
|
38
|
+
# -- pre-fact collection - inject the facts (or loom) object as a recorder (like a mock in record mode)
|
39
|
+
# instead of the factual fact set. no need to change any loom files.
|
40
|
+
# -- only run fact providers which are accessed in the pattern set
|
41
|
+
# -- only load modules accessed in the pattern set
|
42
|
+
# - Replace Pattern "mods" and "mod specs" in Loom::Pattern::ReferenceSet with usages of a builder
|
43
|
+
# instead. Currently the internal data model in ReferenceSet is confusing, but luckily it's the
|
44
|
+
# only client of pattern modules, that have used Loom::Pattern::DSL. Change calls to
|
45
|
+
# DSL#pattern/report/weave (anythin else that creates a pattern) to add a new PatternBuilder to
|
46
|
+
# the module. Use the builder to implement the TODO above ("Add a phase..."). Implement analysis
|
47
|
+
# on the builder.
|
48
|
+
|
49
|
+
=begin
|
27
50
|
|
28
51
|
## .loom File DSL
|
29
52
|
|
30
|
-
See
|
53
|
+
See:
|
54
|
+
* spec/test.loom for a valid .loom file.
|
55
|
+
* spec/loom/pattern/dsl_spec.rb for other examples
|
31
56
|
|
32
|
-
|
33
|
-
|
57
|
+
|
58
|
+
I've tried to take inspriation from several ruby DSLs, including (but not
|
59
|
+
limited to) RSpec, Thor, Commander, Sinatra... so hopefully it feels
|
60
|
+
comfortable.
|
34
61
|
|
35
62
|
Loom::Pattern::DSL is the mixin that defines the declarative API for all .loom
|
36
63
|
file defined modules. It is included into Loom::Pattern by default. The outer
|
@@ -40,7 +67,7 @@ default. Submodules must explicitly include Loom::Pattern, and will receive DSL.
|
|
40
67
|
For example, given the following .loom file:
|
41
68
|
|
42
69
|
``` ~ruby
|
43
|
-
|
70
|
+
pattern :cmd do |loom, facts| puts loom.xe :uptime end
|
44
71
|
|
45
72
|
module Outer
|
46
73
|
|
@@ -76,6 +103,11 @@ file. A ReferenseSet being a collection of references with uniquely named
|
|
76
103
|
slugs. The slug of a reference is computed from the module namespace and
|
77
104
|
instance method name.
|
78
105
|
|
106
|
+
### `report`
|
107
|
+
|
108
|
+
Use `report` to create a pattern that outputs a fact, other value, or result of
|
109
|
+
a block to yaml, json, or any other format.
|
110
|
+
|
79
111
|
### `let`, `before`, and `after`
|
80
112
|
|
81
113
|
Module::Inner, from above, inherits all +let+ declarations from its outer
|
@@ -172,7 +204,7 @@ invoked via Loom::Runner+load+. Expansion happens on read via
|
|
172
204
|
Loom::Pattern::Loader+patterns+, thus the list of patterns is constant
|
173
205
|
throughout all phases of pattern execution.
|
174
206
|
|
175
|
-
#### Pattern Execution
|
207
|
+
#### Pattern Execution Sequence
|
176
208
|
|
177
209
|
Once hosts and patterns are identified in earlier Loom::Runner phases,
|
178
210
|
Loom::Runner+run_internal+, per host, initiates an SSH session and command
|
@@ -210,8 +242,14 @@ TODO
|
|
210
242
|
##
|
211
243
|
|
212
244
|
=end
|
245
|
+
|
246
|
+
require "yaml"
|
247
|
+
require "json"
|
248
|
+
|
213
249
|
module Loom::Pattern
|
214
250
|
|
251
|
+
PatternDefinitionError = Class.new Loom::LoomError
|
252
|
+
|
215
253
|
# TODO: clarify this DSL to only export:
|
216
254
|
# - description
|
217
255
|
# - pattern
|
@@ -246,6 +284,39 @@ module Loom::Pattern
|
|
246
284
|
define_pattern_internal(name, &block)
|
247
285
|
end
|
248
286
|
|
287
|
+
##
|
288
|
+
# @param format[:yaml|:json|:raw] default is :yaml
|
289
|
+
def report(name, format: :yaml, &block)
|
290
|
+
Loom.log.debug1(self) { "defining reporting pattern => #{name}" }
|
291
|
+
define_pattern_internal(name) do |loom, facts|
|
292
|
+
# TODO: I don't like all of this logic in the dsl.
|
293
|
+
result = if block_given?
|
294
|
+
Loom.log.debug(self) { "report[#{name}] from block" }
|
295
|
+
self.instance_exec(loom, facts, &block)
|
296
|
+
elsif !Loom::Facts.is_empty?(facts[name])
|
297
|
+
Loom.log.debug(self) { "report[#{name}] from facts[#{name}]" }
|
298
|
+
facts[name]
|
299
|
+
elsif self.respond_to?(name) && !self.send(name).nil?
|
300
|
+
Loom.log.debug(self) { "report[#{name}] from let{#{name}}" }
|
301
|
+
self.send name
|
302
|
+
else
|
303
|
+
err_msg = "no facts to report for fact[#{name}:#{name.class}]"
|
304
|
+
raise PatternDefinitionError, err_msg
|
305
|
+
end
|
306
|
+
result = result.stdout if result.is_a? Loom::Shell::CmdResult
|
307
|
+
|
308
|
+
puts case format
|
309
|
+
when :yaml then result.to_yaml
|
310
|
+
when :json then result.to_json
|
311
|
+
when :raw then result
|
312
|
+
else
|
313
|
+
err_msg = "invalid report format: #{format.inspect}"
|
314
|
+
err_msg << "valid options: yaml,json,raw"
|
315
|
+
raise PatternDefinitionError, err_msg
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
249
320
|
def weave(name, pattern_slugs)
|
250
321
|
Loom.log.debug1(self) { "defining weave => #{name}" }
|
251
322
|
@weave_slugs ||= {}
|
@@ -300,7 +371,7 @@ module Loom::Pattern
|
|
300
371
|
end
|
301
372
|
|
302
373
|
private
|
303
|
-
def define_pattern_internal(name, &
|
374
|
+
def define_pattern_internal(name, &loom_file_block)
|
304
375
|
@pattern_methods ||= []
|
305
376
|
@pattern_method_map ||= {}
|
306
377
|
@pattern_descriptions ||= {}
|
@@ -312,7 +383,17 @@ module Loom::Pattern
|
|
312
383
|
@pattern_descriptions[method_name] = @next_description
|
313
384
|
@next_description = nil
|
314
385
|
|
315
|
-
|
386
|
+
##
|
387
|
+
# ```ruby
|
388
|
+
# pattern :xyz do |loom, facts|
|
389
|
+
# loom.x :dostuff
|
390
|
+
# end
|
391
|
+
# ```
|
392
|
+
# Patterns declared in the .loom file are defined here:
|
393
|
+
define_method method_name do |loom, facts|
|
394
|
+
Loom.log.debug2(self) { "calling .loom file pattern: #{name}" }
|
395
|
+
self.instance_exec(loom, facts, &loom_file_block)
|
396
|
+
end
|
316
397
|
end
|
317
398
|
|
318
399
|
def hook(scope, &block)
|
@@ -56,22 +56,22 @@ module Loom::Pattern
|
|
56
56
|
using Loom::CoreExt # using demodulize for namespace creation
|
57
57
|
|
58
58
|
class << self
|
59
|
-
def create(ruby_code,
|
59
|
+
def create(ruby_code, source_file)
|
60
60
|
shell_module = Module.new
|
61
61
|
shell_module.include Loom::Pattern
|
62
62
|
# TODO: I think this is my black magic for capturing stacktrace
|
63
63
|
# info... I forget the details. Add documentation.
|
64
|
-
shell_module.module_eval ruby_code,
|
64
|
+
shell_module.module_eval ruby_code, source_file, 1
|
65
65
|
shell_module.namespace ""
|
66
66
|
|
67
|
-
self.new(shell_module,
|
67
|
+
self.new(shell_module, source_file).build
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
def initialize(shell_module,
|
71
|
+
def initialize(shell_module, source_file)
|
72
72
|
@shell_module = shell_module
|
73
73
|
@pattern_mod_specs = pattern_mod_specs
|
74
|
-
@
|
74
|
+
@source_file = source_file
|
75
75
|
end
|
76
76
|
|
77
77
|
def build
|
@@ -106,7 +106,7 @@ module Loom::Pattern
|
|
106
106
|
desc = mod.pattern_description weave_name
|
107
107
|
Loom.log.warn "no descripiton for weave => #{slug}" unless desc
|
108
108
|
|
109
|
-
ExpandingReference.new slug, mod.weave_slugs[weave_name], @
|
109
|
+
ExpandingReference.new slug, mod.weave_slugs[weave_name], @source_file, desc
|
110
110
|
end
|
111
111
|
|
112
112
|
def build_pattern_reference(pattern_name, slug, context, mod)
|
@@ -114,7 +114,7 @@ module Loom::Pattern
|
|
114
114
|
desc = mod.pattern_description pattern_name
|
115
115
|
Loom.log.warn "no descripiton for pattern => #{slug}" unless desc
|
116
116
|
|
117
|
-
Reference.new slug, method, @
|
117
|
+
Reference.new slug, method, @source_file, context, desc
|
118
118
|
end
|
119
119
|
|
120
120
|
def context_for_mod_spec(mod_spec)
|
data/lib/loom/runner.rb
CHANGED
@@ -78,6 +78,10 @@ module Loom
|
|
78
78
|
rescue => e
|
79
79
|
Loom.log.fatal "fatal error => #{e.inspect}"
|
80
80
|
Loom.log.fatal e.backtrace.join "\n\t"
|
81
|
+
|
82
|
+
loom_files = @loom_config.files.loom_files
|
83
|
+
loom_errors = e.backtrace.select { |line| line =~ /(#{loom_files.join("|")})/ }
|
84
|
+
Loom.log.error "Loom file errors: \n\t" + loom_errors.join("\n\t")
|
81
85
|
exit 99
|
82
86
|
end
|
83
87
|
end
|
@@ -114,6 +118,10 @@ module Loom
|
|
114
118
|
pattern_loader = Loom::Pattern::Loader.load @loom_config
|
115
119
|
@pattern_refs = pattern_loader.patterns @pattern_slugs
|
116
120
|
|
121
|
+
@loom_config[:loomfile_autoloads].each do |path|
|
122
|
+
Loom.log.debug { "autoloading: #{path}" }
|
123
|
+
require path
|
124
|
+
end
|
117
125
|
@mod_loader = Loom::Mods::ModLoader.new @loom_config
|
118
126
|
end
|
119
127
|
|
data/lib/loom/shell/api.rb
CHANGED
@@ -19,6 +19,7 @@ module Loom::Shell
|
|
19
19
|
@shell.local.shell_api
|
20
20
|
end
|
21
21
|
|
22
|
+
# This is the entry point for `loom.foo` calls from .loom files.
|
22
23
|
def method_missing(name, *args, &block)
|
23
24
|
Loom.log.debug3(self) { "shell api => #{name} #{args} #{block}" }
|
24
25
|
# TODO: The relationship between shell and mod_loader seems leaky here, a
|
@@ -42,6 +43,7 @@ module Loom::Shell
|
|
42
43
|
def method_missing(name, *args, &block)
|
43
44
|
@cmd_executions.push name
|
44
45
|
@cmd_execution_args.push args
|
46
|
+
self
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
data/lib/loom/version.rb
CHANGED
@@ -83,8 +83,9 @@ module LoomExt::CoreFacts
|
|
83
83
|
facts = {}
|
84
84
|
os_release.each_line do |l|
|
85
85
|
l = l.strip
|
86
|
+
next if l.empty?
|
86
87
|
key, value = l.split("=")
|
87
|
-
unquoted_value = value.gsub(/^"(.+)"$/) { |m| $1 }
|
88
|
+
unquoted_value = value.gsub(/^"(.+)"$/) { |m| $1 } rescue ""
|
88
89
|
facts[key.to_sym] = unquoted_value
|
89
90
|
end
|
90
91
|
facts
|
data/lib/loomext/coremods/all.rb
CHANGED
@@ -7,8 +7,9 @@ require "loom"
|
|
7
7
|
|
8
8
|
require_relative "exec"
|
9
9
|
require_relative "files"
|
10
|
+
require_relative "git"
|
10
11
|
require_relative "net"
|
11
12
|
require_relative "user"
|
12
13
|
require_relative "package/package"
|
13
|
-
require_relative "
|
14
|
+
require_relative "systemd"
|
14
15
|
require_relative "vm/all"
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# TODO: rename this file -> oneliners.rb
|
1
2
|
module LoomExt::CoreMods
|
2
3
|
|
3
4
|
FailError = Class.new Loom::ExecutionError
|
@@ -14,8 +15,16 @@ module LoomExt::CoreMods
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
18
|
+
class ExecEcho < Loom::Mods::Module
|
19
|
+
register_mod :exec_echo, :alias => [:xe, :"<<e"] do |*cmd, **opts|
|
20
|
+
shell.capture *cmd, **opts
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
17
24
|
class ChangeDirectory < Loom::Mods::Module
|
18
25
|
register_mod :change_directory, :alias => :cd do |path, &block|
|
26
|
+
# TODO: I think this block binding is to the Module instead of the RunContext. Find out and
|
27
|
+
# fix it.
|
19
28
|
shell.cd path, &block
|
20
29
|
end
|
21
30
|
end
|
@@ -34,6 +43,7 @@ module LoomExt::CoreMods
|
|
34
43
|
|
35
44
|
class Sudo < Loom::Mods::Module
|
36
45
|
register_mod :sudo do |user: :root, cmd: nil, &block|
|
46
|
+
# TODO: ditto re: binding to Module instead of RunContext.
|
37
47
|
shell.sudo user, cmd, &block
|
38
48
|
end
|
39
49
|
end
|