lxd-common 0.7.0 → 0.8.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/lib/nexussw/lxd/rest_api.rb +9 -4
- data/lib/nexussw/lxd/rest_api/connection.rb +3 -6
- data/lib/nexussw/lxd/transport.rb +7 -3
- data/lib/nexussw/lxd/transport/mixins/cli.rb +31 -15
- data/lib/nexussw/lxd/transport/mixins/helpers/execute.rb +2 -0
- data/lib/nexussw/lxd/transport/mixins/helpers/upload_folder.rb +13 -9
- data/lib/nexussw/lxd/transport/mixins/helpers/users.rb +37 -0
- data/lib/nexussw/lxd/transport/mixins/rest.rb +12 -4
- data/lib/nexussw/lxd/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43d858bed713fa5394649fad875abd9cbf868cf572fb02599e3811e170f8f9fc
|
4
|
+
data.tar.gz: 47e0b0fb09991a4ef903a0ec4b2ddb89308a057e28923e7a5647f50247305ce9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3840c037a9364eec153a4f9cc67ff4a4c81e0df0efa5f1fe6eb6e6d89e9c976ef69ba59386bd58e9c8510b79d51180fc37469a1e4c623d8fc2d55579dad5e7e
|
7
|
+
data.tar.gz: b0c51acca0425ccedf6285d9da0c616baf5b25c9c73de12855e8f4652d5331572b107b93b0dd7a73fe0db682bf49ae72c52fedc9f6cac8e868168d118a146cf1
|
data/lib/nexussw/lxd/rest_api.rb
CHANGED
@@ -54,12 +54,17 @@ module NexusSW
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def write_file(container_name, path, options)
|
57
|
-
post "/1.0/containers/#{container_name}/files?path=#{path}", options[:content]
|
57
|
+
post "/1.0/containers/#{container_name}/files?path=#{path}", options[:content] do |req|
|
58
|
+
req.headers['Content-Type'] = 'application/octet-stream'
|
59
|
+
req.headers['X-LXD-uid'] = options[:uid] if options[:uid]
|
60
|
+
req.headers['X-LXD-gid'] = options[:gid] if options[:gid]
|
61
|
+
req.headers['X-LXD-mode'] = options[:file_mode] if options[:file_mode]
|
62
|
+
end
|
58
63
|
end
|
59
64
|
|
60
|
-
def push_file(local_path, container_name, remote_path)
|
61
|
-
|
62
|
-
end
|
65
|
+
# def push_file(local_path, container_name, remote_path)
|
66
|
+
# write_file container_name, remote_path, content: IO.binread(local_path)
|
67
|
+
# end
|
63
68
|
|
64
69
|
def pull_file(container_name, remote_path, local_path)
|
65
70
|
IO.binwrite(local_path, read_file(container_name, remote_path))
|
@@ -74,11 +74,8 @@ module NexusSW
|
|
74
74
|
if content.is_a? Hash
|
75
75
|
req.headers['Content-Type'] = 'application/json'
|
76
76
|
req.body = content.to_json
|
77
|
-
elsif content # Only upon file upload
|
78
|
-
req
|
79
|
-
req.headers['X-LXD-uid'] = '0'
|
80
|
-
req.headers['X-LXD-gid'] = '0'
|
81
|
-
req.headers['X-LXD-mode'] = '0600'
|
77
|
+
elsif content # Only upon file upload at this time
|
78
|
+
yield req if block_given?
|
82
79
|
req.body = content.to_s
|
83
80
|
end
|
84
81
|
end
|
@@ -87,7 +84,7 @@ module NexusSW
|
|
87
84
|
case err['error_code']
|
88
85
|
when 404 then raise RestAPI::Error::NotFound, err['error']
|
89
86
|
when 400 then raise RestAPI::Error::BadRequest, err['error']
|
90
|
-
else raise "Error #{err['error_code']}: #{err['error']}"
|
87
|
+
else raise RestAPI::Error, "Error #{err['error_code']}: #{err['error']}"
|
91
88
|
end
|
92
89
|
end
|
93
90
|
block_given? ? yield(response) : parse_response(response)
|
@@ -7,11 +7,15 @@ module NexusSW
|
|
7
7
|
raise "#{self.class}#execute not implemented"
|
8
8
|
end
|
9
9
|
|
10
|
+
def user(_user, _options = {})
|
11
|
+
raise "#{self.class}#user not implemented"
|
12
|
+
end
|
13
|
+
|
10
14
|
def read_file(_path)
|
11
15
|
raise "#{self.class}#read_file not implemented"
|
12
16
|
end
|
13
17
|
|
14
|
-
def write_file(_path, _content)
|
18
|
+
def write_file(_path, _content, _options = {})
|
15
19
|
raise "#{self.class}#write_file not implemented"
|
16
20
|
end
|
17
21
|
|
@@ -19,11 +23,11 @@ module NexusSW
|
|
19
23
|
raise "#{self.class}#download_file not implemented"
|
20
24
|
end
|
21
25
|
|
22
|
-
def upload_file(_local_path, _path)
|
26
|
+
def upload_file(_local_path, _path, _options = {})
|
23
27
|
raise "#{self.class}#upload_file not implemented"
|
24
28
|
end
|
25
29
|
|
26
|
-
def upload_folder(_local_path, _path)
|
30
|
+
def upload_folder(_local_path, _path, _options = {})
|
27
31
|
raise "#{self.class}#upload_folder not implemented"
|
28
32
|
end
|
29
33
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'nexussw/lxd/transport/mixins/local'
|
2
|
+
require 'nexussw/lxd/transport/mixins/helpers/users'
|
2
3
|
require 'nexussw/lxd/transport/mixins/helpers/upload_folder'
|
3
4
|
require 'tempfile'
|
4
|
-
require '
|
5
|
+
require 'shellwords'
|
5
6
|
|
6
7
|
module NexusSW
|
7
8
|
module LXD
|
@@ -18,17 +19,17 @@ module NexusSW
|
|
18
19
|
attr_reader :inner_transport, :punt, :container_name, :config
|
19
20
|
|
20
21
|
include Helpers::UploadFolder
|
22
|
+
include Helpers::UsersMixin
|
21
23
|
|
22
24
|
def execute(command, options = {}, &block)
|
23
|
-
|
25
|
+
command = runas_command(command, options) unless options[:subcommand]
|
26
|
+
command = command.shelljoin if command.is_a?(Array)
|
24
27
|
subcommand = options[:subcommand] || "exec #{container_name} --"
|
25
|
-
|
26
|
-
|
27
|
-
options
|
28
|
-
|
29
|
-
|
30
|
-
# with_timeout_and_retries(options) do
|
31
|
-
inner_transport.execute mycommand, options, &block
|
28
|
+
command = "lxc #{subcommand} #{command}"
|
29
|
+
|
30
|
+
options.reject! { |k, _| [:subcommand, :runas].include? k }
|
31
|
+
|
32
|
+
inner_transport.execute command, options, &block
|
32
33
|
end
|
33
34
|
|
34
35
|
def read_file(path)
|
@@ -41,10 +42,12 @@ module NexusSW
|
|
41
42
|
inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
|
42
43
|
end
|
43
44
|
|
44
|
-
def write_file(path, content)
|
45
|
+
def write_file(path, content, options = {})
|
46
|
+
perms = file_perms(options)
|
47
|
+
|
45
48
|
tfile = inner_mktmp
|
46
49
|
inner_transport.write_file tfile, content
|
47
|
-
execute("#{tfile} #{container_name}#{path}", subcommand:
|
50
|
+
execute("#{tfile} #{container_name}#{path}", subcommand: "file push#{perms}", capture: false).error!
|
48
51
|
ensure
|
49
52
|
inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
|
50
53
|
end
|
@@ -58,18 +61,22 @@ module NexusSW
|
|
58
61
|
inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
|
59
62
|
end
|
60
63
|
|
61
|
-
def upload_file(local_path, path)
|
64
|
+
def upload_file(local_path, path, options = {})
|
65
|
+
perms = file_perms(options)
|
66
|
+
|
62
67
|
tfile = inner_mktmp if punt
|
63
68
|
localname = tfile || local_path
|
64
69
|
inner_transport.upload_file local_path, tfile if tfile
|
65
|
-
execute("#{localname} #{container_name}#{path}", subcommand:
|
70
|
+
execute("#{localname} #{container_name}#{path}", subcommand: "file push#{perms}", capture: false).error!
|
66
71
|
ensure
|
67
72
|
inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
|
68
73
|
end
|
69
74
|
|
70
|
-
def upload_folder(local_path, path)
|
75
|
+
def upload_folder(local_path, path, options = {})
|
71
76
|
return super unless config[:info] && config[:info]['api_extensions'] && config[:info]['api_extensions'].include?('directory_manipulation')
|
72
|
-
|
77
|
+
|
78
|
+
perms = file_perms(options)
|
79
|
+
execute("-r #{local_path} #{container_name}#{path}", subcommand: "file push#{perms}", capture: false).error!
|
73
80
|
end
|
74
81
|
|
75
82
|
def add_remote(host_name)
|
@@ -101,6 +108,15 @@ module NexusSW
|
|
101
108
|
ensure
|
102
109
|
tfile.unlink
|
103
110
|
end
|
111
|
+
|
112
|
+
def file_perms(options = {})
|
113
|
+
perms = ''
|
114
|
+
perms += " --uid=#{options[:uid] || uid || 0}"
|
115
|
+
perms += " --gid=#{options[:gid] || gid || 0}"
|
116
|
+
fmode = options[:file_mode] || file_mode
|
117
|
+
perms += " --mode=#{fmode}" if fmode
|
118
|
+
perms
|
119
|
+
end
|
104
120
|
end
|
105
121
|
end
|
106
122
|
end
|
@@ -26,12 +26,14 @@ module NexusSW
|
|
26
26
|
def error!
|
27
27
|
return self if exitstatus == 0
|
28
28
|
msg = "Error: '#{command}' failed with exit code #{exitstatus}.\n"
|
29
|
+
# msg += (" while running as '#{username}'.\n" if username) || ".\n"
|
29
30
|
msg += "STDOUT: #{stdout}" if stdout.is_a?(String) && !stdout.empty?
|
30
31
|
msg += "STDERR: #{stderr}" if stderr.is_a?(String) && !stderr.empty?
|
31
32
|
raise ::NexusSW::LXD::RestAPI::Error, msg
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
36
|
+
# LocalTransport does not have the users mixin, so code the `su` command on the rest & cli transports directly
|
35
37
|
def execute(command, options = {}, &block)
|
36
38
|
options ||= {}
|
37
39
|
return execute_chunked(command, options) if options[:capture] == false && !block_given?
|
@@ -4,19 +4,19 @@ module NexusSW
|
|
4
4
|
module Mixins
|
5
5
|
module Helpers
|
6
6
|
module UploadFolder
|
7
|
-
def upload_folder(local_path, path)
|
8
|
-
upload_using_tarball(local_path, path) || upload_files_individually(local_path, path)
|
7
|
+
def upload_folder(local_path, path, options = {})
|
8
|
+
upload_using_tarball(local_path, path, options) || upload_files_individually(local_path, path, options)
|
9
9
|
end
|
10
10
|
|
11
|
-
def upload_files_individually(local_path, path)
|
11
|
+
def upload_files_individually(local_path, path, options = {})
|
12
12
|
Dir.entries(local_path).map { |f| (f == '.' || f == '..') ? nil : File.join(local_path, f) }.compact.each do |f|
|
13
13
|
dest = File.join(path, File.basename(local_path))
|
14
|
-
upload_files_individually f, dest if File.directory? f
|
15
|
-
upload_file f, File.join(dest, File.basename(f)) if File.file? f
|
14
|
+
upload_files_individually f, dest, options if File.directory? f
|
15
|
+
upload_file f, File.join(dest, File.basename(f)), options if File.file? f
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def upload_using_tarball(local_path, path)
|
19
|
+
def upload_using_tarball(local_path, path, options = {})
|
20
20
|
return false unless can_archive?
|
21
21
|
# TODO: should I return false upon error? i.e. retry with individual file uploads if this fails?
|
22
22
|
# lets see how this does in the wild before deciding
|
@@ -32,12 +32,16 @@ module NexusSW
|
|
32
32
|
return false
|
33
33
|
end
|
34
34
|
fname = '/tmp/' + File.basename(tfile.path) + ".tar#{ext}"
|
35
|
-
upload_file tfile.path, fname
|
35
|
+
upload_file tfile.path, fname, options
|
36
36
|
# TODO: serious: make sure the tar extract does an overwrite of existing files
|
37
37
|
# multiple converge support as well as CI cycle/dev updated files get updated instead of .1 suffixed (?)
|
38
38
|
# I think I need a flag (it's been a while)
|
39
|
-
|
40
|
-
|
39
|
+
myuid = options[:uid] || uid || (0 if is_a?(Mixins::CLI))
|
40
|
+
mygid = options[:gid] || gid || (0 if is_a?(Mixins::CLI))
|
41
|
+
mymode = options[:file_mode] || file_mode
|
42
|
+
chown = " && chown -R #{myuid}:#{mygid} #{File.basename(local_path)}" if myuid
|
43
|
+
chmod = " && chmod -R #{mymode} #{File.basename(local_path)}" if mymode
|
44
|
+
execute("bash -c 'mkdir -p #{path} && cd #{path} && tar -xf #{fname} && rm -rf #{fname}#{chmod}#{chown}'").error!
|
41
45
|
ensure
|
42
46
|
tfile.unlink
|
43
47
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module NexusSW
|
4
|
+
module LXD
|
5
|
+
class Transport
|
6
|
+
module Mixins
|
7
|
+
module Helpers
|
8
|
+
module UsersMixin
|
9
|
+
def user(user_nameorid, options = {})
|
10
|
+
passwd = read_file options[:passwd_file] || '/etc/passwd'
|
11
|
+
|
12
|
+
# rework into .split(':') if this gets more complicated
|
13
|
+
@uid = user_nameorid.is_a?(String) ? passwd[/^#{user_nameorid}:[^:]*:([^:]*):/, 1] : user_nameorid
|
14
|
+
@username = user_nameorid.is_a?(String) ? user_nameorid : passwd[/^([^:]*):[^:]*:#{user_nameorid}:/, 1]
|
15
|
+
|
16
|
+
# gotcha: we're always setting the default group here, but it's changeable by the user, afterwards
|
17
|
+
# so if `user` gets called again, and the caller wants an alternative gid, the caller will need to re-set the gid
|
18
|
+
@gid = passwd[/^[^:]*:[^:]*:#{uid}:([^:]*):/, 1]
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :file_mode, :gid
|
22
|
+
attr_reader :uid, :username
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def runas_command(command, options = {})
|
27
|
+
uname = options[:runas] || username
|
28
|
+
return command unless uname
|
29
|
+
command = command.shelljoin if command.is_a? Array
|
30
|
+
['su', uname, '-c', command]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'nexussw/lxd/transport/mixins/helpers/execute'
|
2
|
+
require 'nexussw/lxd/transport/mixins/helpers/users'
|
2
3
|
require 'nexussw/lxd/transport/mixins/helpers/upload_folder'
|
3
4
|
require 'nio/websocket'
|
4
5
|
require 'tempfile'
|
5
6
|
require 'json'
|
7
|
+
require 'shellwords'
|
6
8
|
|
7
9
|
module NexusSW
|
8
10
|
module LXD
|
@@ -22,6 +24,7 @@ module NexusSW
|
|
22
24
|
|
23
25
|
include Helpers::ExecuteMixin
|
24
26
|
include Helpers::UploadFolder
|
27
|
+
include Helpers::UsersMixin
|
25
28
|
|
26
29
|
class StdinStub
|
27
30
|
# return self as an IO (un)like object
|
@@ -62,6 +65,7 @@ module NexusSW
|
|
62
65
|
opid = nil
|
63
66
|
backchannel = nil
|
64
67
|
getlogs = false
|
68
|
+
command = runas_command(command, options)
|
65
69
|
if block_given? && (options[:capture] || !config[:info][:api_extensions].include?('container_exec_recording'))
|
66
70
|
apiopts = { :'wait-for-websocket' => true, interactive: false, sync: false }
|
67
71
|
apiopts[:interactive] = true if options[:capture] == :interactive
|
@@ -114,17 +118,21 @@ module NexusSW
|
|
114
118
|
api.read_file container_name, path
|
115
119
|
end
|
116
120
|
|
117
|
-
def write_file(path, content)
|
118
|
-
|
121
|
+
def write_file(path, content, options = {})
|
122
|
+
options = options.merge content: content
|
123
|
+
options[:uid] ||= uid if uid
|
124
|
+
options[:gid] ||= gid if gid
|
125
|
+
options[:file_mode] ||= file_mode if file_mode
|
126
|
+
api.write_file container_name, path, options
|
119
127
|
end
|
120
128
|
|
121
129
|
def download_file(path, local_path)
|
122
130
|
api.pull_file container_name, path, local_path
|
123
131
|
end
|
124
132
|
|
125
|
-
def upload_file(local_path, path)
|
133
|
+
def upload_file(local_path, path, options = {})
|
126
134
|
# return api.push_file(local_path, container_name, path)
|
127
|
-
write_file(path, IO.binread(local_path))
|
135
|
+
write_file(path, IO.binread(local_path), options)
|
128
136
|
end
|
129
137
|
|
130
138
|
protected
|
data/lib/nexussw/lxd/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lxd-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Zachariasen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -127,6 +127,7 @@ files:
|
|
127
127
|
- lib/nexussw/lxd/transport/mixins/cli.rb
|
128
128
|
- lib/nexussw/lxd/transport/mixins/helpers/execute.rb
|
129
129
|
- lib/nexussw/lxd/transport/mixins/helpers/upload_folder.rb
|
130
|
+
- lib/nexussw/lxd/transport/mixins/helpers/users.rb
|
130
131
|
- lib/nexussw/lxd/transport/mixins/local.rb
|
131
132
|
- lib/nexussw/lxd/transport/mixins/rest.rb
|
132
133
|
- lib/nexussw/lxd/transport/rest.rb
|