balmora 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/bin/balmora +6 -0
- data/lib/balmora.rb +77 -0
- data/lib/balmora/arguments.rb +175 -0
- data/lib/balmora/cli.rb +150 -0
- data/lib/balmora/command.rb +106 -0
- data/lib/balmora/command/commands.rb +21 -0
- data/lib/balmora/command/exec.rb +24 -0
- data/lib/balmora/command/file.rb +168 -0
- data/lib/balmora/command/files.rb +122 -0
- data/lib/balmora/command/pacman.rb +71 -0
- data/lib/balmora/command/reload_config.rb +13 -0
- data/lib/balmora/command/restart.rb +13 -0
- data/lib/balmora/command/set_variable.rb +41 -0
- data/lib/balmora/command/stop.rb +17 -0
- data/lib/balmora/command/yaourt.rb +8 -0
- data/lib/balmora/config.rb +190 -0
- data/lib/balmora/context.rb +98 -0
- data/lib/balmora/context/config_changed.rb +11 -0
- data/lib/balmora/context/exec.rb +26 -0
- data/lib/balmora/context/exec_result.rb +7 -0
- data/lib/balmora/contexts.rb +76 -0
- data/lib/balmora/extension.rb +58 -0
- data/lib/balmora/extension/file_secret.rb +45 -0
- data/lib/balmora/logger.rb +25 -0
- data/lib/balmora/require.rb +25 -0
- data/lib/balmora/shell.rb +118 -0
- data/lib/balmora/state.rb +82 -0
- data/lib/balmora/variables.rb +110 -0
- data/lib/balmora/variables/config.rb +7 -0
- data/lib/balmora/variables/variables.rb +7 -0
- metadata +74 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
class Balmora::Command::Commands < Balmora::Command
|
2
|
+
|
3
|
+
def options()
|
4
|
+
return super().concat([:commands])
|
5
|
+
end
|
6
|
+
|
7
|
+
def verify()
|
8
|
+
if @commands.nil?()
|
9
|
+
raise Error.new('"commands" should be set')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def run()
|
14
|
+
@balmora.run_commands(@state, @commands)
|
15
|
+
end
|
16
|
+
|
17
|
+
def _installed()
|
18
|
+
return @shell.run!(['pacman', '-Q'], verbose: false).split("\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Balmora::Command::Exec < Balmora::Command
|
2
|
+
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
def options()
|
6
|
+
return super().concat([:exec])
|
7
|
+
end
|
8
|
+
|
9
|
+
def verify()
|
10
|
+
if @exec.nil?()
|
11
|
+
raise Error.new('"exec" should be defined')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def run()
|
16
|
+
exec = option(:exec)
|
17
|
+
if !exec.instance_of?(::Array)
|
18
|
+
exec = [@shell.expression(exec)]
|
19
|
+
end
|
20
|
+
|
21
|
+
@shell.system(exec)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
class Balmora::Command::File < Balmora::Command
|
2
|
+
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
OPTIONS = '-T'
|
6
|
+
|
7
|
+
def init()
|
8
|
+
super()
|
9
|
+
|
10
|
+
@action = @variables.inject(@action)
|
11
|
+
@file = @variables.inject(@file)
|
12
|
+
@source = @variables.inject(@source)
|
13
|
+
@storage = @variables.inject(@storage)
|
14
|
+
end
|
15
|
+
|
16
|
+
def options()
|
17
|
+
return super().concat([:file, :source, :storage, :action, :check_equal,
|
18
|
+
:options])
|
19
|
+
end
|
20
|
+
|
21
|
+
def run()
|
22
|
+
if !_run_required?()
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
|
26
|
+
_create_target_path()
|
27
|
+
_copy_file()
|
28
|
+
# _change_file_owner()
|
29
|
+
end
|
30
|
+
|
31
|
+
def verify()
|
32
|
+
if @file.nil?()
|
33
|
+
raise Error.new('"file" should be defined')
|
34
|
+
end
|
35
|
+
|
36
|
+
if !@storage.nil?() && !@source.nil?()
|
37
|
+
raise Error.new('"storage" and "source" could not be defined together')
|
38
|
+
end
|
39
|
+
|
40
|
+
if @storage.nil?() && @source.nil?()
|
41
|
+
raise Error.new('"storage" or "source" should be defined')
|
42
|
+
end
|
43
|
+
|
44
|
+
if @action.nil?()
|
45
|
+
raise Error.new('"action" should be set')
|
46
|
+
end
|
47
|
+
|
48
|
+
if !['pull', 'push'].include?(@action)
|
49
|
+
Error.new("Unknown action #{@action.inspect()}")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def _create_target_path()
|
56
|
+
@shell.run!(['mkdir', '-p', ::File.dirname(_target_path())], verbose: false)
|
57
|
+
end
|
58
|
+
|
59
|
+
def _copy_file()
|
60
|
+
@shell.run!(['cp', option(:options) || OPTIONS, _source_path(),
|
61
|
+
_target_path()])
|
62
|
+
end
|
63
|
+
|
64
|
+
# def _change_file_owner()
|
65
|
+
# new_owner = _get_target_required_owner()
|
66
|
+
# if _get_target_actual_owner() == new_owner
|
67
|
+
# return
|
68
|
+
# end
|
69
|
+
|
70
|
+
# @shell.run!(['chown', new_owner, '-R', _target_path()])
|
71
|
+
# end
|
72
|
+
|
73
|
+
# def _get_target_actual_owner()
|
74
|
+
# owner =
|
75
|
+
# @shell.run!(['stat', '-c', '%U:%G', _target_path()], verbose: false).
|
76
|
+
# strip()
|
77
|
+
|
78
|
+
# return owner
|
79
|
+
# end
|
80
|
+
|
81
|
+
# def _get_target_required_owner()
|
82
|
+
# owner =
|
83
|
+
# if @action == 'pull'
|
84
|
+
# @owner
|
85
|
+
# elsif @action == 'push'
|
86
|
+
# @storage_owner
|
87
|
+
# else
|
88
|
+
# raise Error.new("Can not get owner for action #{@action}")
|
89
|
+
# end
|
90
|
+
|
91
|
+
# owner = owner || @shell.user_id()
|
92
|
+
|
93
|
+
# return owner
|
94
|
+
# end
|
95
|
+
|
96
|
+
def _run_required?()
|
97
|
+
# if @check_equal == false
|
98
|
+
# return true
|
99
|
+
# end
|
100
|
+
|
101
|
+
command = [
|
102
|
+
'test', '-e', _source_path(), _expr('&&'),
|
103
|
+
*@shell.sudo(), 'test', '-e', _target_path(), _expr('&&'),
|
104
|
+
_expr('[ "$('), *@shell.sudo(), *_source_contents(), _expr('| md5sum'),
|
105
|
+
_expr(')" = '),
|
106
|
+
_expr('"$('), *@shell.sudo(), *_target_contents(), _expr('| md5sum)" ]'),
|
107
|
+
]
|
108
|
+
|
109
|
+
return @shell.run(command, verbose: false)[0] != 0
|
110
|
+
end
|
111
|
+
|
112
|
+
def _source_contents()
|
113
|
+
return ['cat', _source_path()]
|
114
|
+
end
|
115
|
+
|
116
|
+
def _target_contents()
|
117
|
+
return ['cat', _target_path()]
|
118
|
+
end
|
119
|
+
|
120
|
+
def _source_path()
|
121
|
+
return _files()[0]
|
122
|
+
end
|
123
|
+
|
124
|
+
def _target_path()
|
125
|
+
return _files()[1]
|
126
|
+
end
|
127
|
+
|
128
|
+
def _expr(expression)
|
129
|
+
return @shell.expression(expression)
|
130
|
+
end
|
131
|
+
|
132
|
+
def _owner()
|
133
|
+
return @owner || ENV['USER']
|
134
|
+
end
|
135
|
+
|
136
|
+
def _storage_owner()
|
137
|
+
return @storage_owner || ENV['USER']
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def _files()
|
143
|
+
if @action == 'pull'
|
144
|
+
return _resolve_source_path(), @shell.expand(@file)
|
145
|
+
else
|
146
|
+
return @shell.expand(@file), _resolve_source_path()
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def _resolve_source_path()
|
151
|
+
if !@source.nil?()
|
152
|
+
return @shell.expand(@source)
|
153
|
+
end
|
154
|
+
|
155
|
+
storage = @shell.expand(@storage)
|
156
|
+
|
157
|
+
if @file.start_with?('~/')
|
158
|
+
result = ::File.join(storage, @file[1..-1])
|
159
|
+
elsif @file.start_with?('/')
|
160
|
+
result = ::File.join(storage, @file[1..-1])
|
161
|
+
else
|
162
|
+
result = ::File.join(storage, @file)
|
163
|
+
end
|
164
|
+
|
165
|
+
return result
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
class Balmora::Command::Files < Balmora::Command
|
2
|
+
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
def init()
|
6
|
+
super()
|
7
|
+
|
8
|
+
@files = @variables.inject(@files)
|
9
|
+
@storage = @variables.inject(@storage)
|
10
|
+
@exclude = @variables.inject(@exclude)
|
11
|
+
end
|
12
|
+
|
13
|
+
def options()
|
14
|
+
return super().concat([:action, :options, :files, :storage, :exclude])
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify()
|
18
|
+
if @files.nil?() && @storage.nil?()
|
19
|
+
raise Error.new('"files" or "storage" should be defined')
|
20
|
+
end
|
21
|
+
|
22
|
+
if @files.nil?() || @files.empty?()
|
23
|
+
raise Error.new('"files" should be defined')
|
24
|
+
end
|
25
|
+
|
26
|
+
if !@options.nil?() && @options.has_key?(:storage) && !@storage.nil?()
|
27
|
+
raise Error.new('"file.storage" and "storage" could not be defined ' +
|
28
|
+
'together')
|
29
|
+
end
|
30
|
+
|
31
|
+
if @action.nil?()
|
32
|
+
raise Error.new('"action" should be defined')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def run()
|
37
|
+
_files().each() { |file|
|
38
|
+
command = _get_command(file)
|
39
|
+
@balmora.run_command(@state, command)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def _files()
|
44
|
+
files = _find_files()
|
45
|
+
files = _filter_files(files)
|
46
|
+
return files
|
47
|
+
end
|
48
|
+
|
49
|
+
def _find_files()
|
50
|
+
storage = @shell.expand(@storage)
|
51
|
+
|
52
|
+
files = []
|
53
|
+
@files.each() { |file|
|
54
|
+
path = file
|
55
|
+
if path.instance_of?(::Hash)
|
56
|
+
path = path[:file]
|
57
|
+
end
|
58
|
+
|
59
|
+
if @action == 'pull'
|
60
|
+
path = ::File.join(storage, path.gsub(/^(\~\/|\~$|\/)/, ''))
|
61
|
+
else
|
62
|
+
path = @shell.expand(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
command = ['test', '-d', path, @shell.expression('&&'), 'find', path,
|
66
|
+
'-type', 'f']
|
67
|
+
|
68
|
+
dir_status, dir_files = @shell.run(command, verbose: false)
|
69
|
+
if dir_status != 0
|
70
|
+
files.push(file)
|
71
|
+
next
|
72
|
+
end
|
73
|
+
|
74
|
+
dir_files.
|
75
|
+
strip().
|
76
|
+
split("\n").
|
77
|
+
each() { |found|
|
78
|
+
found = found[(path.length + 1)..-1]
|
79
|
+
if file.instance_of?(::Hash)
|
80
|
+
files.push(file.merge(file: ::File.join(file[:file], found)))
|
81
|
+
else
|
82
|
+
files.push(::File.join(file, found))
|
83
|
+
end
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
return files
|
88
|
+
end
|
89
|
+
|
90
|
+
def _filter_files(files)
|
91
|
+
if !@exclude.nil?()
|
92
|
+
exclude = Regexp.new('(' + @exclude.collect() { |part| "(#{part})" }.
|
93
|
+
join('|') + ')')
|
94
|
+
|
95
|
+
files = files.select() { |file|
|
96
|
+
result =
|
97
|
+
if file.instance_of?(::Hash)
|
98
|
+
!file[:file].match(exclude)
|
99
|
+
else
|
100
|
+
!file.match(exclude)
|
101
|
+
end
|
102
|
+
|
103
|
+
next result
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
return files
|
108
|
+
end
|
109
|
+
|
110
|
+
def _get_command(file)
|
111
|
+
command = (@options || {}).merge(command: 'file', file: file)
|
112
|
+
|
113
|
+
if file.instance_of?(::Hash)
|
114
|
+
command.merge!(file)
|
115
|
+
end
|
116
|
+
|
117
|
+
command.merge!(action: @action, storage: @storage)
|
118
|
+
|
119
|
+
return command
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Balmora::Command::Pacman < Balmora::Command
|
2
|
+
|
3
|
+
def initialize(state, command)
|
4
|
+
super(state, command)
|
5
|
+
@bin = ['sudo', 'pacman']
|
6
|
+
end
|
7
|
+
|
8
|
+
def init()
|
9
|
+
super()
|
10
|
+
@action = @variables.inject(@action)
|
11
|
+
@packages = @variables.inject(@packages)
|
12
|
+
@synchronize = @variables.inject(@synchronize)
|
13
|
+
end
|
14
|
+
|
15
|
+
def options()
|
16
|
+
return super().concat([:action, :packages, :synchronize])
|
17
|
+
end
|
18
|
+
|
19
|
+
def verify()
|
20
|
+
if @action.nil?()
|
21
|
+
raise Error.new('"action" should be set')
|
22
|
+
end
|
23
|
+
|
24
|
+
if !['install', 'update', 'remove'].include?(@action)
|
25
|
+
raise Error.new('wrong "action" value; allowed values: install, ' +
|
26
|
+
'update, remove')
|
27
|
+
end
|
28
|
+
|
29
|
+
if @packages.nil?() || @packages.empty?()
|
30
|
+
raise Error.new('"packages" should be set')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def run()
|
35
|
+
command = '-S'
|
36
|
+
|
37
|
+
if @synchronize != false
|
38
|
+
command += 'y'
|
39
|
+
end
|
40
|
+
|
41
|
+
if @action == 'install'
|
42
|
+
packages = @packages - _installed()
|
43
|
+
elsif @action == 'update'
|
44
|
+
packages = @packages
|
45
|
+
elsif @action == 'remove'
|
46
|
+
packages = @packages & _installed()
|
47
|
+
command = '-R'
|
48
|
+
else
|
49
|
+
raise Error.new("Wrong action #{@action.inspect()}")
|
50
|
+
end
|
51
|
+
|
52
|
+
if packages.length == 0
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
@shell.system([*@bin, command, *packages, '--noconfirm'])
|
57
|
+
end
|
58
|
+
|
59
|
+
def _installed()
|
60
|
+
packages =
|
61
|
+
@shell.
|
62
|
+
run!(['pacman', '-Q'], verbose: false).
|
63
|
+
split("\n").
|
64
|
+
collect() { |package|
|
65
|
+
package.split(' ')[0]
|
66
|
+
}
|
67
|
+
|
68
|
+
return packages
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Balmora::Command::SetVariable < Balmora::Command
|
2
|
+
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
def init()
|
6
|
+
super()
|
7
|
+
|
8
|
+
@variable = option(:variable)
|
9
|
+
@value = option(:value)
|
10
|
+
end
|
11
|
+
|
12
|
+
def options()
|
13
|
+
return super().concat([:variable, :value])
|
14
|
+
end
|
15
|
+
|
16
|
+
def verify()
|
17
|
+
if @variable.nil?()
|
18
|
+
raise Error.new('"variable" should be defined')
|
19
|
+
end
|
20
|
+
|
21
|
+
if @value.nil?()
|
22
|
+
raise Error.new('"value" should be defined')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def run()
|
27
|
+
parts = @variable.split('.').collect() { |part| part.to_sym() }
|
28
|
+
@config.config[:variables] ||= {}
|
29
|
+
parent = parts[0...-1].inject(@config.config[:variables]) { |current, variable|
|
30
|
+
if !current.instance_of?(::Hash)
|
31
|
+
raise Error.new("wrong variable name #{@variable}: target is not hash")
|
32
|
+
end
|
33
|
+
|
34
|
+
current[variable] ||= {}
|
35
|
+
next current[variable]
|
36
|
+
}
|
37
|
+
|
38
|
+
parent[parts[-1]] = @value
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|