loom-core 0.0.1
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 +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +99 -0
- data/Guardfile +54 -0
- data/Rakefile +6 -0
- data/bin/loom +185 -0
- data/lib/env/development.rb +1 -0
- data/lib/loom.rb +44 -0
- data/lib/loom/all.rb +20 -0
- data/lib/loom/config.rb +106 -0
- data/lib/loom/core_ext.rb +37 -0
- data/lib/loom/dsl.rb +60 -0
- data/lib/loom/facts.rb +13 -0
- data/lib/loom/facts/all.rb +2 -0
- data/lib/loom/facts/fact_file_provider.rb +86 -0
- data/lib/loom/facts/fact_set.rb +138 -0
- data/lib/loom/host_spec.rb +32 -0
- data/lib/loom/inventory.rb +124 -0
- data/lib/loom/logger.rb +141 -0
- data/lib/loom/method_signature.rb +174 -0
- data/lib/loom/mods.rb +4 -0
- data/lib/loom/mods/action_proxy.rb +105 -0
- data/lib/loom/mods/all.rb +3 -0
- data/lib/loom/mods/mod_loader.rb +80 -0
- data/lib/loom/mods/module.rb +113 -0
- data/lib/loom/pattern.rb +15 -0
- data/lib/loom/pattern/all.rb +7 -0
- data/lib/loom/pattern/definition_context.rb +74 -0
- data/lib/loom/pattern/dsl.rb +176 -0
- data/lib/loom/pattern/hook.rb +28 -0
- data/lib/loom/pattern/loader.rb +48 -0
- data/lib/loom/pattern/reference.rb +71 -0
- data/lib/loom/pattern/reference_set.rb +169 -0
- data/lib/loom/pattern/result_reporter.rb +77 -0
- data/lib/loom/runner.rb +209 -0
- data/lib/loom/shell.rb +12 -0
- data/lib/loom/shell/all.rb +10 -0
- data/lib/loom/shell/api.rb +48 -0
- data/lib/loom/shell/cmd_result.rb +33 -0
- data/lib/loom/shell/cmd_wrapper.rb +164 -0
- data/lib/loom/shell/core.rb +226 -0
- data/lib/loom/shell/harness_blob.rb +26 -0
- data/lib/loom/shell/harness_command_builder.rb +50 -0
- data/lib/loom/shell/session.rb +25 -0
- data/lib/loom/trap.rb +44 -0
- data/lib/loom/version.rb +3 -0
- data/lib/loomext/all.rb +4 -0
- data/lib/loomext/corefacts.rb +6 -0
- data/lib/loomext/corefacts/all.rb +8 -0
- data/lib/loomext/corefacts/facter_provider.rb +24 -0
- data/lib/loomext/coremods.rb +5 -0
- data/lib/loomext/coremods/all.rb +13 -0
- data/lib/loomext/coremods/exec.rb +50 -0
- data/lib/loomext/coremods/files.rb +104 -0
- data/lib/loomext/coremods/net.rb +33 -0
- data/lib/loomext/coremods/package/adapter.rb +100 -0
- data/lib/loomext/coremods/package/package.rb +62 -0
- data/lib/loomext/coremods/user.rb +82 -0
- data/lib/loomext/coremods/vm.rb +0 -0
- data/lib/loomext/coremods/vm/all.rb +6 -0
- data/lib/loomext/coremods/vm/vbox.rb +84 -0
- data/loom.gemspec +39 -0
- data/loom/inventory.yml +13 -0
- data/scripts/harness.sh +242 -0
- data/spec/loom/host_spec_spec.rb +101 -0
- data/spec/loom/inventory_spec.rb +154 -0
- data/spec/loom/method_signature_spec.rb +275 -0
- data/spec/loom/pattern/dsl_spec.rb +207 -0
- data/spec/loom/shell/cmd_wrapper_spec.rb +239 -0
- data/spec/loom/shell/harness_blob_spec.rb +42 -0
- data/spec/loom/shell/harness_command_builder_spec.rb +36 -0
- data/spec/runloom.sh +35 -0
- data/spec/scripts/harness_spec.rb +385 -0
- data/spec/spec_helper.rb +94 -0
- data/spec/test.loom +370 -0
- data/spec/test_loom_spec.rb +57 -0
- metadata +287 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require_relative "adapter"
|
3
|
+
|
4
|
+
module LoomExt::CoreMods
|
5
|
+
class Package < Loom::Mods::Module
|
6
|
+
|
7
|
+
UnsupportedPackageManager = Class.new Loom::Mods::ModActionError
|
8
|
+
|
9
|
+
attr_reader :pkg_adapter
|
10
|
+
|
11
|
+
register_mod :pkg
|
12
|
+
|
13
|
+
def init_action
|
14
|
+
@pkg_adapter = default_adapter
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(adapter)
|
18
|
+
case adapter.to_sym
|
19
|
+
when :dnf
|
20
|
+
DnfAdapter.new loom
|
21
|
+
when :rpm
|
22
|
+
RpmAdapter.new loom
|
23
|
+
when :apt
|
24
|
+
AptAdapter.new loom
|
25
|
+
when :dpkg
|
26
|
+
DpkgAdapter.new loom
|
27
|
+
when :gem
|
28
|
+
GemAdapter.new loom
|
29
|
+
else
|
30
|
+
raise UnsupportedPackageManager, adapter
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method :[], :get
|
34
|
+
|
35
|
+
def default_adapter
|
36
|
+
if loom.test :which, "dnf"
|
37
|
+
DnfAdapter.new loom
|
38
|
+
elsif loom.test :which, "rpm"
|
39
|
+
RpmAdapter.new loom
|
40
|
+
elsif loom.test :which, "apt"
|
41
|
+
AptAdapter.new loom
|
42
|
+
elsif loom.test :which, "dpkg"
|
43
|
+
DpkgAdapter.new loom
|
44
|
+
else
|
45
|
+
raise UnsupportedPackageManager
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Actions
|
50
|
+
extend Forwardable
|
51
|
+
def_delegators :@pkg_adapter, :installed?, :install, :uninstall,
|
52
|
+
:update_cache, :upgrade, :ensure_installed
|
53
|
+
|
54
|
+
def [](*args)
|
55
|
+
get(*args)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
import_actions Package::Actions
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module LoomExt::CoreMods
|
2
|
+
class User < Loom::Mods::Module
|
3
|
+
|
4
|
+
SudoersDNoExistError = Class.new Loom::Mods::ModActionError
|
5
|
+
SudoersDNotIncluded = Class.new Loom::Mods::ModActionError
|
6
|
+
|
7
|
+
register_mod :user
|
8
|
+
required_commands :useradd, :userdel, :getent
|
9
|
+
|
10
|
+
SUDOERS_FILE = "/etc/sudoers"
|
11
|
+
SUDOERS_DIR = "/etc/sudoers.d"
|
12
|
+
LOOM_SUDOERS_FILE = SUDOERS_DIR + "/90-loom-sudoers"
|
13
|
+
|
14
|
+
def user_exists?(user)
|
15
|
+
shell.test :getent, :passwd, user
|
16
|
+
end
|
17
|
+
|
18
|
+
def includes_sudoers?
|
19
|
+
shell.test :grep, :"-e", :"'^#includedir #{SUDOERS_DIR}$'", SUDOERS_FILE
|
20
|
+
end
|
21
|
+
|
22
|
+
def sudoersd_exists?
|
23
|
+
shell.test :test, %Q[-d #{SUDOERS_DIR}]
|
24
|
+
end
|
25
|
+
|
26
|
+
module Actions
|
27
|
+
def add(user,
|
28
|
+
home_dir: nil,
|
29
|
+
login_shell: "/bin/bash",
|
30
|
+
uid: nil,
|
31
|
+
gid: nil,
|
32
|
+
groups: [],
|
33
|
+
is_system_user: nil)
|
34
|
+
if user_exists? user
|
35
|
+
Loom.log.warn "add_user skipping existing user => #{user}"
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
flags = []
|
40
|
+
flags << ["--home-dir", home_dir] if home_dir
|
41
|
+
flags << ["--create-home"] if home_dir
|
42
|
+
flags << ["--shell", login_shell] if login_shell
|
43
|
+
flags << ["--uid", uid] if uid
|
44
|
+
flags << ["--gid", gid] if gid
|
45
|
+
flags << ["--groups", groups] unless groups.empty?
|
46
|
+
flags << "--system" if is_system_user
|
47
|
+
|
48
|
+
loom.exec :useradd, flags, user
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_system_user(user, **user_fields)
|
52
|
+
if user_exists? user
|
53
|
+
Loom.log.warn "add_system_user skipping existing user => #{user}"
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
add user, is_system_user: true, login_shell: "/bin/false", **user_fields
|
58
|
+
end
|
59
|
+
|
60
|
+
def remove(user)
|
61
|
+
unless user_exists? user
|
62
|
+
Loom.log.warn "remove_user skipping non-existant user => #{user}"
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
loom.exec :userdel, "-r", user
|
67
|
+
end
|
68
|
+
|
69
|
+
def make_sudoer(user)
|
70
|
+
raise SudoersDNotIncluded unless includes_sudoers?
|
71
|
+
raise SudoersDNoExistError unless sudoersd_exists?
|
72
|
+
|
73
|
+
sudoer_conf = :"#{user} ALL=(ALL) NOPASSWD:ALL"
|
74
|
+
|
75
|
+
loom.files(LOOM_SUDOERS_FILE).append sudoer_conf
|
76
|
+
loom.exec :chmod, "0440", LOOM_SUDOERS_FILE
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
User.import_actions User::Actions
|
82
|
+
end
|
File without changes
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module LoomExt::CoreMods::VM
|
2
|
+
class Virtualbox < Loom::Mods::Module
|
3
|
+
|
4
|
+
DuplicateVMImport = Class.new Loom::ExecutionError
|
5
|
+
UnknownVM = Class.new Loom::ExecutionError
|
6
|
+
|
7
|
+
register_mod :vbox
|
8
|
+
required_commands :vboxmanage
|
9
|
+
|
10
|
+
module Actions
|
11
|
+
def check_exists(vm)
|
12
|
+
loom.test "vboxmanage showvminfo #{vm}".split
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_running(vm)
|
16
|
+
loom.test "vboxmanage list runningvms".split, :piped_cmds => [
|
17
|
+
"grep \"#{vm}\"".split
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
def list
|
22
|
+
loom << "vboxmanage list vms".split
|
23
|
+
end
|
24
|
+
|
25
|
+
def snapshot(vm, action: :take, snapshot_name: nil)
|
26
|
+
raise UnknownVM, vm unless check_exists(vm)
|
27
|
+
|
28
|
+
cmd = ["vboxmanage snapshot #{vm} #{action}"]
|
29
|
+
cmd << snapshot_name if snapshot_name
|
30
|
+
cmd = cmd.join " "
|
31
|
+
|
32
|
+
loom << cmd.split
|
33
|
+
end
|
34
|
+
|
35
|
+
def import(ova_file, vm, disk, take_snapshot: true)
|
36
|
+
raise DuplicateVMImport, vm if check_exists(vm)
|
37
|
+
|
38
|
+
loom << "vboxmanage import #{ova_file} \
|
39
|
+
--vsys 0 --vmname #{vm} \
|
40
|
+
--vsys 0 --unit 12 --disk '#{disk}'".split
|
41
|
+
|
42
|
+
if take_snapshot
|
43
|
+
snapshot vm, action: :take, snapshot_name: "#{vm}:import"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def clone(src_vm, dst_vm, options: :link, snapshot: nil, take_snapshot: true)
|
48
|
+
raise DuplicateVMImport, "VM already exists => #{dst_vm}" if check_exists(dst_vm)
|
49
|
+
raise UnknownVM, src_vm unless check_exists(src_vm)
|
50
|
+
|
51
|
+
cmd = ["vboxmanage clonevm #{src_vm}"]
|
52
|
+
cmd << "--snapshot #{snapshot}" if snapshot
|
53
|
+
cmd << "--options #{options}" if options
|
54
|
+
cmd << "--name #{dst_vm}"
|
55
|
+
cmd << "--register"
|
56
|
+
cmd = cmd.join " "
|
57
|
+
|
58
|
+
loom << cmd.split
|
59
|
+
|
60
|
+
if take_snapshot
|
61
|
+
snapshot dst_vm, action: :take, snapshot_name: "#{dst_vm}:clone"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def up(vm)
|
66
|
+
unless check_running(vm)
|
67
|
+
loom << "vboxmanage startvm #{vm} --type headless".split
|
68
|
+
else
|
69
|
+
Loom.log.warn "VM #{vm} already running, nothing to do"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def down(vm)
|
74
|
+
if check_running(vm)
|
75
|
+
loom << "vboxmanage controlvm #{vm} acpipowerbutton".split
|
76
|
+
else
|
77
|
+
Loom.log.warn "VM #{vm} not running, nothing to do"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
import_actions Actions
|
83
|
+
end
|
84
|
+
end
|
data/loom.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path '../lib/', __FILE__
|
2
|
+
require 'loom/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'loom-core'
|
6
|
+
s.description = 'Repeatable management of remote hosts over SSH'
|
7
|
+
s.summary = s.description
|
8
|
+
s.version = Loom::VERSION
|
9
|
+
s.license = 'MIT'
|
10
|
+
s.authors = ['Erick Johnson']
|
11
|
+
s.email = 'ejohnson82@gmail.com'
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
16
|
+
s.require_paths = %w[lib]
|
17
|
+
|
18
|
+
s.add_dependency 'sshkit', '~> 1.11'
|
19
|
+
s.add_dependency 'commander', '~> 4.4'
|
20
|
+
|
21
|
+
# Need net-ssh beta and its explicit requirements until for ed25519
|
22
|
+
# elliptic curve key support
|
23
|
+
# https://github.com/net-ssh/net-ssh/issues/214
|
24
|
+
|
25
|
+
# grrr.. 4.x.beta won't work in `gem install` until the official
|
26
|
+
# release due to net-scp gem dependencies.
|
27
|
+
# I can manually `gem install net-ssh --version 4.0.0.beta3` for now.
|
28
|
+
# s.add_dependency 'net-ssh', '>= 4.0.0.beta3'
|
29
|
+
s.add_dependency 'net-ssh', '>= 3'
|
30
|
+
s.add_dependency 'rbnacl-libsodium', '1.0.10'
|
31
|
+
s.add_dependency 'bcrypt_pbkdf', '1.0.0.alpha1'
|
32
|
+
|
33
|
+
s.add_development_dependency 'bundler', '~> 1.13'
|
34
|
+
s.add_development_dependency 'rake', '~> 11.3'
|
35
|
+
s.add_development_dependency 'rspec', '~> 3.5'
|
36
|
+
s.add_development_dependency 'guard-rspec', '~> 4.7'
|
37
|
+
s.add_development_dependency 'pry', '~> 0.10'
|
38
|
+
s.add_development_dependency 'pry-byebug'
|
39
|
+
end
|
data/loom/inventory.yml
ADDED
data/scripts/harness.sh
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
# The Harness script for encoding, checksum'ing and running loom
|
2
|
+
# patterns.
|
3
|
+
#
|
4
|
+
# The point of the harness is to safely encode arbitrary commands as
|
5
|
+
# base64 strings and execute them in another shell, usually on a
|
6
|
+
# remote machine over SSH. The flow for running the harness is:
|
7
|
+
#
|
8
|
+
# 1. base64 encode an arbitrary shell script, this is the encoded
|
9
|
+
# script
|
10
|
+
# 2. get a checksum for the encoded script
|
11
|
+
# 3. send the encoded script and checksum to a shell in another
|
12
|
+
# process (local or remote) to invoke the encoded script via this
|
13
|
+
# harness script
|
14
|
+
#
|
15
|
+
# Given 2 hosts, [local] and [remote] the process looks like this:
|
16
|
+
#
|
17
|
+
# [local]$ encoded=$(./scripts/harness.sh --print_base64 - <<'EOS'
|
18
|
+
# echo my sweet script
|
19
|
+
# EOS
|
20
|
+
# )
|
21
|
+
# [local]$ checksum=$(./scripts/harness --print_checksum $encoded)
|
22
|
+
#
|
23
|
+
# ... SCP harness.sh to some/path on remote ...
|
24
|
+
#
|
25
|
+
# [local]$ ssh user@remote \
|
26
|
+
# some/path/harness.sh --run - $checksum <<EOS
|
27
|
+
# $encoded
|
28
|
+
# EOS
|
29
|
+
#
|
30
|
+
# There are 2 different shells that the harness deals with. The
|
31
|
+
# harness shell, and the command shell.
|
32
|
+
#
|
33
|
+
# The harness shell is the shell used to run the harness script (this
|
34
|
+
# file). Only POSIX features are supported in the harness
|
35
|
+
# script. Officially, `bash`, `bash --posix`, and `dash` are suported
|
36
|
+
# via the specs, (see spec/scripts/harness_spec.rb). Unofficially, any
|
37
|
+
# POSIX compliant shell should work.
|
38
|
+
#
|
39
|
+
# The command shell is the shell used by the harness to execute the
|
40
|
+
# encoded script. By default the command shell is `/bin/sh`. The
|
41
|
+
# command shell can be whatever you choose by passing an additonal
|
42
|
+
# parameter to `harness.sh --run`. For example, to run the encoded
|
43
|
+
# script in dash:
|
44
|
+
#
|
45
|
+
# [local]$ harness.sh --run - $checksum --cmd_shell /bin/dash <<EOS
|
46
|
+
# $encoded
|
47
|
+
# EOS
|
48
|
+
#
|
49
|
+
# To run the harness script in bash POSIX mode and the command script
|
50
|
+
# in plain old bash, the following will work:
|
51
|
+
#
|
52
|
+
# [local]$ (bash --posix -) <<HARNESS_EOS
|
53
|
+
# harness.sh --run - $checksum --cmd_shell /bin/bash <<COMMAND_EOS
|
54
|
+
# $encoded
|
55
|
+
# COMMAND_EOS
|
56
|
+
# HARNESS_EOS
|
57
|
+
#
|
58
|
+
# Commands will be recored as they are executed in the record file. By
|
59
|
+
# default the record file is /dev/null. To use a record file pass the
|
60
|
+
# record_file argument to --run, e.g.:
|
61
|
+
#
|
62
|
+
# harness.sh --run - $checksum --record_file /opt/loom/cmds <<CMDS...
|
63
|
+
#
|
64
|
+
|
65
|
+
declare -r DEFAULT_COMMAND_SHELL="/bin/sh"
|
66
|
+
declare -r DEFAULT_RECORD_FILE="/dev/null"
|
67
|
+
|
68
|
+
declare -r TRUE=0
|
69
|
+
declare -r FALSE=1
|
70
|
+
|
71
|
+
declare -r SUCCESS=0
|
72
|
+
|
73
|
+
declare -r EXIT_INVALID_BASE64=9
|
74
|
+
declare -r EXIT_BAD_CHECKSUM=8
|
75
|
+
declare -r EXIT_MISSING_ARG=2
|
76
|
+
declare -r EXIT_GENERIC=1
|
77
|
+
|
78
|
+
exit_with_usage() {
|
79
|
+
script=$(basename "$0")
|
80
|
+
echo "Usages:"
|
81
|
+
echo " ${script} --check <base64_blob|-> <golden_checksum>"
|
82
|
+
echo " ${script} --run <base64_blob|-> <golden_checksum> \\"
|
83
|
+
echo " [--cmd_shell shell] \\"
|
84
|
+
echo " [--record_file record_file]"
|
85
|
+
echo " ${script} --print_checksum <base64_blob|->"
|
86
|
+
echo " ${script} --print_base64 <raw_cmds|->"
|
87
|
+
exit $EXIT_GENERIC
|
88
|
+
}
|
89
|
+
|
90
|
+
##
|
91
|
+
# If $0 equals "-", then consume and return STDIN, otherwise return
|
92
|
+
# the value.
|
93
|
+
value_or_stdin() {
|
94
|
+
local value="${1}"
|
95
|
+
|
96
|
+
if [ "${value}" = "-" ]; then
|
97
|
+
echo "read stdin" 1>&2
|
98
|
+
(cat)<&0
|
99
|
+
else
|
100
|
+
echo "read value arg" 1>&2
|
101
|
+
echo -n $value
|
102
|
+
fi
|
103
|
+
}
|
104
|
+
|
105
|
+
base64_encode_cmds() {
|
106
|
+
local raw_cmds="$1"
|
107
|
+
echo $(base64 -w0 <<BASE64_EOF
|
108
|
+
${raw_cmds}
|
109
|
+
BASE64_EOF
|
110
|
+
)
|
111
|
+
}
|
112
|
+
|
113
|
+
validate_base64_blob() {
|
114
|
+
local unknown_blob="$1"
|
115
|
+
(base64 -d <<BASE64_EOF
|
116
|
+
${unknown_blob}
|
117
|
+
BASE64_EOF
|
118
|
+
) > /dev/null
|
119
|
+
if [ ! "$?" -eq 0 ]; then
|
120
|
+
exit $EXIT_INVALID_BASE64
|
121
|
+
fi
|
122
|
+
}
|
123
|
+
|
124
|
+
validate_arg_is_present() {
|
125
|
+
arg="$1"
|
126
|
+
msg="$2"
|
127
|
+
if [ -z "${arg}" ]; then
|
128
|
+
echo "${msg}" 1>&2
|
129
|
+
exit $EXIT_MISSING_ARG
|
130
|
+
fi
|
131
|
+
}
|
132
|
+
|
133
|
+
print_checksum() {
|
134
|
+
local chksum_blob="$1"
|
135
|
+
|
136
|
+
echo "checksum'ing base64 blob: +${chksum_blob}+" 1>&2
|
137
|
+
echo $(sha1sum - <<CHECKSUM_EOF | cut -d' ' -f1
|
138
|
+
${chksum_blob}
|
139
|
+
CHECKSUM_EOF
|
140
|
+
)
|
141
|
+
}
|
142
|
+
|
143
|
+
check_cmds() {
|
144
|
+
local base64_blob="$1"
|
145
|
+
local golden_sha1="$2"
|
146
|
+
local actual_sha1=$(print_checksum "${base64_blob}")
|
147
|
+
|
148
|
+
test "${golden_sha1}" = "${actual_sha1}"
|
149
|
+
}
|
150
|
+
|
151
|
+
run_cmds() {
|
152
|
+
local base64_blob="$1"
|
153
|
+
local cmd_shell="${2:-$DEFAULT_COMMAND_SHELL}"
|
154
|
+
local record_file="${3:-$DEFAULT_RECORD_FILE}"
|
155
|
+
(
|
156
|
+
base64 -d | tee -a ${record_file} | ${cmd_shell} -
|
157
|
+
) <<RUN_EOS
|
158
|
+
${base64_blob}
|
159
|
+
RUN_EOS
|
160
|
+
}
|
161
|
+
|
162
|
+
main() {
|
163
|
+
set -xv
|
164
|
+
local flag="$1"
|
165
|
+
local should_run=$FALSE
|
166
|
+
shift
|
167
|
+
|
168
|
+
if [ -z "${flag}" ]; then
|
169
|
+
exit_with_usage
|
170
|
+
fi
|
171
|
+
|
172
|
+
case $flag in
|
173
|
+
--print_base64)
|
174
|
+
declare -r raw_cmds=$(value_or_stdin "$1")
|
175
|
+
declare -r base64_blob=$(base64_encode_cmds "${raw_cmds}")
|
176
|
+
validate_base64_blob "${base64_blob}"
|
177
|
+
|
178
|
+
printf $base64_blob
|
179
|
+
exit $SUCCESS
|
180
|
+
;;
|
181
|
+
--print_checksum)
|
182
|
+
declare -r base64_blob=$(value_or_stdin "$1")
|
183
|
+
validate_base64_blob "${base64_blob}"
|
184
|
+
|
185
|
+
printf $(print_checksum "${base64_blob}")
|
186
|
+
exit $SUCCESS
|
187
|
+
;;
|
188
|
+
--check)
|
189
|
+
declare -r base64_blob=$(value_or_stdin "$1")
|
190
|
+
declare -r golden_sha1="$2"
|
191
|
+
shift
|
192
|
+
shift
|
193
|
+
;;
|
194
|
+
--run)
|
195
|
+
should_run=$TRUE
|
196
|
+
declare -r base64_blob=$(value_or_stdin "$1")
|
197
|
+
declare -r golden_sha1="$2"
|
198
|
+
shift
|
199
|
+
shift
|
200
|
+
|
201
|
+
while (( "$#" >= 2 )); do
|
202
|
+
case "$1" in
|
203
|
+
--cmd_shell)
|
204
|
+
declare -r cmd_shell="$2"
|
205
|
+
shift
|
206
|
+
shift
|
207
|
+
;;
|
208
|
+
--record_file)
|
209
|
+
declare -r record_file="$2"
|
210
|
+
shift
|
211
|
+
shift
|
212
|
+
;;
|
213
|
+
*)
|
214
|
+
echo "unknown arg for --run: ${1}" 1>&2
|
215
|
+
exit_with_usage
|
216
|
+
shift
|
217
|
+
;;
|
218
|
+
esac
|
219
|
+
shift
|
220
|
+
done
|
221
|
+
;;
|
222
|
+
*)
|
223
|
+
exit_with_usage
|
224
|
+
;;
|
225
|
+
esac
|
226
|
+
|
227
|
+
validate_arg_is_present "${base64_blob}" "missing base64_blob"
|
228
|
+
validate_arg_is_present "${golden_sha1}" "missing golden_sha1"
|
229
|
+
validate_base64_blob "${base64_blob}"
|
230
|
+
|
231
|
+
if ! (check_cmds "${base64_blob}" "${golden_sha1}"); then
|
232
|
+
echo "checksum failed, expected ${golden_sha1}" 1>&2
|
233
|
+
exit $EXIT_BAD_CHECKSUM
|
234
|
+
fi
|
235
|
+
|
236
|
+
if [ "${should_run}" -eq $TRUE ]; then
|
237
|
+
echo "running commands" 1>&2
|
238
|
+
run_cmds "${base64_blob}" "${cmd_shell}" "${record_file}"
|
239
|
+
fi
|
240
|
+
}
|
241
|
+
|
242
|
+
main "$@"
|