elecksee 1.1.8 → 2.0.0
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/elecksee.gemspec +2 -0
- data/lib/elecksee.rb +1 -0
- data/lib/elecksee/ephemeral.rb +4 -3
- data/lib/elecksee/helpers.rb +14 -5
- data/lib/elecksee/lxc_file_config.rb +77 -121
- data/lib/elecksee/storage/overlay_directory.rb +1 -1
- data/lib/elecksee/version.rb +1 -1
- metadata +31 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fa238c10437677255df26d118e761553342b5a6
|
4
|
+
data.tar.gz: f22d8b320fde7d3a531728bf77b3613883d2e6d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de48a9a73b02e227bffbc8f8094355157acdd54bdb1214f3e2b281009827de15ac4261cb084749a840f5b30a1090796eb036eace96badb3ef91d1237eee6d2d0
|
7
|
+
data.tar.gz: 2cd3efa4127547d4ecb1f5f09abf93dfad46313bd38a0baac1686fe29506908c9405d22398fdd4e72423862e34c0f7c262cca99ec2865e6186d487747f14d620
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## v2.0.0
|
2
|
+
* [fix] Use sudo helper when cloning
|
3
|
+
* [enhancement] Disable retry on ephemeral command
|
4
|
+
* [enhancement] Dynamic parsing/generation of configuration files
|
5
|
+
* [fix] Do not register traps when executing inline
|
6
|
+
* [fix] Synchronize childprocess access to prevent race
|
7
|
+
|
8
|
+
_WARNING: Updated configuration file handling may cause breakage_
|
9
|
+
|
1
10
|
## v1.1.8
|
2
11
|
* Add `include` support for file config
|
3
12
|
|
data/elecksee.gemspec
CHANGED
@@ -10,6 +10,8 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.description = 'LXC helpers'
|
11
11
|
s.require_path = 'lib'
|
12
12
|
s.executables = %w(lxc-awesome-ephemeral)
|
13
|
+
s.add_dependency 'bogo'
|
14
|
+
s.add_dependency 'attribute_struct'
|
13
15
|
s.add_dependency 'childprocess'
|
14
16
|
s.add_dependency 'rye'
|
15
17
|
s.files = Dir['{bin,lib}/**/**/*'] + %w(elecksee.gemspec README.md CHANGELOG.md LICENSE CONTRIBUTING.md)
|
data/lib/elecksee.rb
CHANGED
data/lib/elecksee/ephemeral.rb
CHANGED
@@ -93,7 +93,7 @@ class Lxc
|
|
93
93
|
lxc.start
|
94
94
|
if(ephemeral_command)
|
95
95
|
lxc.wait_for_state(:running)
|
96
|
-
lxc.container_command(ephemeral_command)
|
96
|
+
lxc.container_command(ephemeral_command, 0) # no retries on ephemeral commands
|
97
97
|
else
|
98
98
|
cli_output
|
99
99
|
lxc.wait_for_state(:stopped)
|
@@ -137,7 +137,6 @@ class Lxc
|
|
137
137
|
start_action
|
138
138
|
end
|
139
139
|
else
|
140
|
-
register_traps
|
141
140
|
start_action
|
142
141
|
end
|
143
142
|
true
|
@@ -194,7 +193,9 @@ class Lxc
|
|
194
193
|
content << 'trap scrub SIGTERM SIGINT SIGQUIT'
|
195
194
|
content << "lxc-start -n #{lxc.name} -d"
|
196
195
|
content << 'sleep 1'
|
197
|
-
content <<
|
196
|
+
content << 'until [ `lxc-wait -n #{lxc.name} -s STOPPED -t 2` ]'
|
197
|
+
content << 'do'
|
198
|
+
content << 'done'
|
198
199
|
content << 'scrub'
|
199
200
|
tmp = Tempfile.new('elecksee')
|
200
201
|
tmp.chmod(0700)
|
data/lib/elecksee/helpers.rb
CHANGED
@@ -4,6 +4,10 @@ class Lxc
|
|
4
4
|
# Helper modules
|
5
5
|
module Helpers
|
6
6
|
|
7
|
+
class << self
|
8
|
+
attr_accessor :child_process_lock
|
9
|
+
end
|
10
|
+
|
7
11
|
autoload :Copies, 'elecksee/helpers/copies'
|
8
12
|
autoload :Options, 'elecksee/helpers/options'
|
9
13
|
|
@@ -56,11 +60,14 @@ class Lxc
|
|
56
60
|
s_err = Tempfile.new('stderr')
|
57
61
|
s_out.sync
|
58
62
|
s_err.sync
|
59
|
-
c_proc =
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
c_proc = nil
|
64
|
+
Lxc::Helpers.child_process_lock.synchronize do
|
65
|
+
c_proc = ChildProcess.build(*Shellwords.split(cmd))
|
66
|
+
c_proc.environment.merge('HOME' => detect_home)
|
67
|
+
c_proc.io.stdout = s_out
|
68
|
+
c_proc.io.stderr = s_err
|
69
|
+
c_proc.start
|
70
|
+
end
|
64
71
|
begin
|
65
72
|
c_proc.poll_for_exit(args[:timeout] || 1200)
|
66
73
|
rescue ChildProcess::TimeoutError
|
@@ -228,3 +235,5 @@ class Lxc
|
|
228
235
|
|
229
236
|
end
|
230
237
|
end
|
238
|
+
|
239
|
+
Lxc::Helpers.child_process_lock = Mutex.new
|
@@ -1,145 +1,101 @@
|
|
1
1
|
require 'elecksee'
|
2
|
+
require 'attribute_struct'
|
2
3
|
|
3
|
-
class
|
4
|
-
# Configuration file interface
|
5
|
-
class FileConfig
|
4
|
+
class LxcStruct < AttributeStruct
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
def network(*args, &block)
|
7
|
+
unless(self[:network])
|
8
|
+
set!(:network, ::AttributeStruct::CollapseArray.new)
|
9
|
+
self[:network].push(_klass_new)
|
10
|
+
end
|
11
|
+
if(self[:network].last._data[:type].is_a?(::AttributeStruct::CollapseArray))
|
12
|
+
val = self[:network].last._data[:type].pop
|
13
|
+
self[:network].push(_klass_new)
|
14
|
+
self[:network].last.set!(:type, val)
|
15
|
+
end
|
16
|
+
self[:network].last
|
17
|
+
end
|
13
18
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# @return [Hash]
|
18
|
-
# @note used mostly for the lxc resource within chef
|
19
|
-
def convert_to_hash(thing)
|
20
|
-
if(defined?(Chef) && thing.is_a?(Chef::Resource))
|
21
|
-
result = Hash[*(
|
22
|
-
(thing.methods - Chef::Resource.instance_methods).map{ |key|
|
23
|
-
unless(key.to_s.start_with?('_') || thing.send(key).nil?)
|
24
|
-
[key, thing.send(key)]
|
25
|
-
end
|
26
|
-
}.compact.flatten(1)
|
27
|
-
)]
|
28
|
-
else
|
29
|
-
unless(thing.is_a?(Hash))
|
30
|
-
result = defined?(Mash) ? Mash.new : {}
|
31
|
-
thing.to_hash.each do |k,v|
|
32
|
-
result[k] = v.respond_to?(:keys) && v.respond_to?(:values) ? convert_to_hash(v) : v
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
result || thing
|
37
|
-
end
|
19
|
+
def _klass
|
20
|
+
::LxcStruct
|
21
|
+
end
|
38
22
|
|
39
|
-
|
40
|
-
#
|
41
|
-
# @param thing [Hashish]
|
42
|
-
# @return [Hash]
|
43
|
-
def symbolize_hash(thing)
|
44
|
-
if(defined?(Mash))
|
45
|
-
Mash.new(thing)
|
46
|
-
else
|
47
|
-
result = {}
|
48
|
-
thing.each do |k,v|
|
49
|
-
result[k.to_sym] = v.is_a?(Hash) ? symbolize_hash(v) : v
|
50
|
-
end
|
51
|
-
result
|
52
|
-
end
|
53
|
-
end
|
23
|
+
end
|
54
24
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# @return [String]
|
59
|
-
def generate_config(resource)
|
60
|
-
resource = symbolize_hash(convert_to_hash(resource))
|
61
|
-
config = []
|
62
|
-
config << "lxc.utsname = #{resource[:utsname]}"
|
63
|
-
if(resource[:aa_profile])
|
64
|
-
config << "lxc.aa_profile = #{resource[:aa_profile]}"
|
65
|
-
end
|
66
|
-
[resource[:network]].flatten.each do |net_hash|
|
67
|
-
nhsh = Mash.new(net_hash)
|
68
|
-
flags = nhsh.delete(:flags)
|
69
|
-
%w(type link).each do |k|
|
70
|
-
config << "lxc.network.#{k} = #{nhsh.delete(k)}" if nhsh[k]
|
71
|
-
end
|
72
|
-
nhsh.each_pair do |k,v|
|
73
|
-
config << "lxc.network.#{k} = #{v}"
|
74
|
-
end
|
75
|
-
if(flags)
|
76
|
-
config << "lxc.network.flags = #{flags}"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
if(resource[:cap_drop])
|
80
|
-
config << "lxc.cap.drop = #{Array(resource[:cap_drop]).join(' ')}"
|
81
|
-
end
|
82
|
-
%w(include pts tty arch devttydir mount mount_entry rootfs rootfs_mount pivotdir).each do |k|
|
83
|
-
config << "lxc.#{k.sub('_', '.')} = #{resource[k.to_sym]}" if resource[k.to_sym]
|
84
|
-
end
|
85
|
-
prefix = 'lxc.cgroup'
|
86
|
-
resource[:cgroup].each_pair do |key, value|
|
87
|
-
if(value.is_a?(Array))
|
88
|
-
value.each do |val|
|
89
|
-
config << "#{prefix}.#{key} = #{val}"
|
90
|
-
end
|
91
|
-
else
|
92
|
-
config << "#{prefix}.#{key} = #{value}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
config.join("\n") + "\n"
|
96
|
-
end
|
25
|
+
class Lxc
|
26
|
+
# Configuration file interface
|
27
|
+
class FileConfig
|
97
28
|
|
98
|
-
|
29
|
+
# @return [String] path to config file
|
30
|
+
attr_reader :path
|
31
|
+
# @return [AttrubuteStruct] config file contents
|
32
|
+
attr_accessor :state
|
99
33
|
|
100
34
|
# Create new instance
|
101
35
|
#
|
102
36
|
# @param path [String]
|
103
37
|
def initialize(path)
|
104
|
-
raise 'LXC config file not found' unless File.exists?(path)
|
105
38
|
@path = path
|
106
|
-
|
107
|
-
|
108
|
-
|
39
|
+
if(File.exists?(path))
|
40
|
+
parse!
|
41
|
+
else
|
42
|
+
@state = LxcStruct.new
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Smash] hash like dump of state
|
47
|
+
def state_hash
|
48
|
+
state._dump.to_smash
|
49
|
+
end
|
50
|
+
|
51
|
+
# Overwrite the config file
|
52
|
+
#
|
53
|
+
# @return [Integer]
|
54
|
+
def write!
|
55
|
+
File.write(path, generate_content)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generate config file content from current value of state
|
59
|
+
#
|
60
|
+
# @return [String]
|
61
|
+
def generate_content
|
62
|
+
process_item(state_hash).flatten.join("\n")
|
109
63
|
end
|
110
64
|
|
111
65
|
private
|
112
66
|
|
67
|
+
# Convert item to configuration file line
|
68
|
+
#
|
69
|
+
# @param item [Object]
|
70
|
+
# @param parents [Array<String>] parent hash keys
|
71
|
+
# @return [Array<String>]
|
72
|
+
def process_item(item, parents=[])
|
73
|
+
case item
|
74
|
+
when Hash
|
75
|
+
item.map do |k,v|
|
76
|
+
process_item(v, parents + [k])
|
77
|
+
end
|
78
|
+
when Array
|
79
|
+
item.map do |v|
|
80
|
+
process_item(v, parents)
|
81
|
+
end
|
82
|
+
else
|
83
|
+
["#{parents.join('.')} = #{item}"]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
113
87
|
# Parse the configuration file
|
114
88
|
#
|
115
|
-
# @return [
|
89
|
+
# @return [AttributeStruct]
|
116
90
|
def parse!
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
@network << cur_net if cur_net
|
124
|
-
cur_net = Mash.new
|
125
|
-
end
|
126
|
-
if(cur_net)
|
127
|
-
cur_net[name] = parts.last.strip
|
128
|
-
else
|
129
|
-
raise "Expecting 'lxc.network.type' to start network config block. Found: 'lxc.network.#{name}'"
|
130
|
-
end
|
131
|
-
else
|
132
|
-
parts = line.split('=')
|
133
|
-
name = parts.first.sub('lxc.', '').strip
|
134
|
-
if(@base[name])
|
135
|
-
@base[name] = [@base[name], parts.last.strip].flatten
|
136
|
-
else
|
137
|
-
@base[name] = parts.last
|
138
|
-
end
|
139
|
-
end
|
91
|
+
struct = LxcStruct.new
|
92
|
+
struct._set_state(:value_collapse => true)
|
93
|
+
File.read(path).split("\n").each do |line|
|
94
|
+
parts = line.split('=').map(&:strip)
|
95
|
+
parts.last.replace("'#{parts.last}'")
|
96
|
+
struct.instance_eval(parts.join(' = '))
|
140
97
|
end
|
141
|
-
@
|
142
|
-
true
|
98
|
+
@state = struct
|
143
99
|
end
|
144
100
|
|
145
101
|
end
|
data/lib/elecksee/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elecksee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bogo
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: attribute_struct
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: childprocess
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -83,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
111
|
version: '0'
|
84
112
|
requirements: []
|
85
113
|
rubyforge_project:
|
86
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.4.8
|
87
115
|
signing_key:
|
88
116
|
specification_version: 4
|
89
117
|
summary: LXC helpers
|