lxd-common 0.8.1 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4232e85c055f7dc0ca02c732241ec3045cd71291ab9cd3a2b17c85698a1c8002
4
- data.tar.gz: 8ff20ac3b41f2a07312cf7e9fd3fa542fdd23cc74bb6821551fea9511b5e07f3
3
+ metadata.gz: 032aa7f8a09b027c6254b6e42c5c36328a0325804780ed7a6db13ec4f905d197
4
+ data.tar.gz: b52cf26ede270ceb806dfd552d97a6ef0b5693e10a98943d2d6f4e708ed0ca2f
5
5
  SHA512:
6
- metadata.gz: 9b7706d7598d89e2b5e1b08863b12ecbe3b8404db520d61b2cba1acffc41ec7a217cd8f31a0c760548285428ef580eec3bd085847a065088eeab3072e1da5719
7
- data.tar.gz: 5c1e444616de2a81b74c08ec5b57d4daced4a11a4875e2c3008488133ddb872758ef3c4ff4edca6348dfa547e4dfffafaf9d1d50744e9fe0bd716390dc5b11ab
6
+ metadata.gz: ae77de9d2025c2cdba5cd71740fec1766486520844b29f4dc11ebb786f69da90310033c2c722bdfb0db0234c19737b4c7c868cc3000b05a824caf12500ba9f15
7
+ data.tar.gz: 99dbeed1e5731e1050197a244c16c91215ba41b11c78d555d2ed16cb368b1cde11ff4f63975b6aedb83e38bb345df66c41f0b88fdd3e58687e63effb69868097
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in lxd-common.gemspec
4
- gemspec
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Rakefile CHANGED
@@ -1,9 +1,10 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
- RSpec::Core::RakeTask.new(:mock) do |task|
6
- task.pattern = 'spec/**{,/*/**}/*_mock.rb'
7
- end
8
-
9
- task default: :spec
1
+
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RSpec::Core::RakeTask.new(:mock) do |task|
7
+ task.pattern = 'spec/**{,/*/**}/*_mock.rb'
8
+ end
9
+
10
+ task default: :spec
@@ -92,9 +92,7 @@ module NexusSW
92
92
  end
93
93
 
94
94
  def wait_for_operation(operation_id)
95
- get "/1.0/operations/#{operation_id}/wait" do |response|
96
- LXD.symbolize_keys(JSON.parse(response.body))
97
- end
95
+ get "/1.0/operations/#{operation_id}/wait"
98
96
  end
99
97
 
100
98
  private
@@ -35,8 +35,8 @@ module NexusSW
35
35
  url: baseurl,
36
36
  ssl: {
37
37
  verify: verify_ssl,
38
- client_cert: OpenSSL::X509::Certificate.new(cert),
39
- client_key: OpenSSL::PKey::RSA.new(key),
38
+ client_cert: client_cert,
39
+ client_key: client_key,
40
40
  },
41
41
  }
42
42
 
@@ -51,12 +51,12 @@ module NexusSW
51
51
  api_options[:ssl] || {}
52
52
  end
53
53
 
54
- def cert
55
- File.read(ssl_opts[:client_cert] || "#{ENV['HOME']}/.config/lxc/client.crt")
54
+ def client_cert
55
+ @client_cert ||= OpenSSL::X509::Certificate.new(File.read(ssl_opts[:client_cert] || "#{ENV['HOME']}/.config/lxc/client.crt"))
56
56
  end
57
57
 
58
- def key
59
- File.read(ssl_opts[:client_key] || "#{ENV['HOME']}/.config/lxc/client.key")
58
+ def client_key
59
+ @client_key ||= OpenSSL::PKey::RSA.new(File.read(ssl_opts[:client_key] || "#{ENV['HOME']}/.config/lxc/client.key"))
60
60
  end
61
61
 
62
62
  def verify_ssl
@@ -69,6 +69,7 @@ module NexusSW
69
69
  end
70
70
 
71
71
  def send_request(verb, relative_url, content = nil)
72
+ fileop = false
72
73
  response = connection.send(verb) do |req|
73
74
  req.url relative_url
74
75
  if content.is_a? Hash
@@ -77,6 +78,7 @@ module NexusSW
77
78
  elsif content # Only upon file upload at this time
78
79
  yield req if block_given?
79
80
  req.body = content.to_s
81
+ fileop = true
80
82
  end
81
83
  end
82
84
  if response.status >= 400
@@ -87,7 +89,7 @@ module NexusSW
87
89
  else raise RestAPI::Error, "Error #{err['error_code']}: #{err['error']}"
88
90
  end
89
91
  end
90
- block_given? ? yield(response) : parse_response(response)
92
+ block_given? && !fileop ? yield(response) : parse_response(response)
91
93
  end
92
94
  end
93
95
  end
@@ -1,4 +1,5 @@
1
1
  require 'nexussw/lxd'
2
+ require 'tempfile'
2
3
 
3
4
  module NexusSW
4
5
  module LXD
@@ -23,6 +24,10 @@ module NexusSW
23
24
  raise "#{self.class}#download_file not implemented"
24
25
  end
25
26
 
27
+ def download_folder(_path, _local_path)
28
+ raise "#{self.class}#download_folder not implemented"
29
+ end
30
+
26
31
  def upload_file(_local_path, _path, _options = {})
27
32
  raise "#{self.class}#upload_file not implemented"
28
33
  end
@@ -30,6 +35,21 @@ module NexusSW
30
35
  def upload_folder(_local_path, _path, _options = {})
31
36
  raise "#{self.class}#upload_folder not implemented"
32
37
  end
38
+
39
+ # kludge for windows environment
40
+ def self.remote_tempname(basename)
41
+ tfile = Tempfile.new(basename)
42
+ "/tmp/#{File.basename tfile.path}"
43
+ ensure
44
+ tfile.unlink
45
+ end
46
+
47
+ def self.local_tempdir
48
+ return ENV['TEMP'] unless !ENV['TEMP'] || ENV['TEMP'].empty?
49
+ return ENV['TMP'] unless !ENV['TMP'] || ENV['TMP'].empty?
50
+ return ENV['TMPDIR'] unless !ENV['TMPDIR'] || ENV['TMPDIR'].empty?
51
+ '/tmp'
52
+ end
33
53
  end
34
54
  end
35
55
  end
@@ -1,6 +1,6 @@
1
1
  require 'nexussw/lxd/transport/mixins/local'
2
2
  require 'nexussw/lxd/transport/mixins/helpers/users'
3
- require 'nexussw/lxd/transport/mixins/helpers/upload_folder'
3
+ require 'nexussw/lxd/transport/mixins/helpers/folder_txfr'
4
4
  require 'tempfile'
5
5
  require 'shellwords'
6
6
 
@@ -18,7 +18,7 @@ module NexusSW
18
18
 
19
19
  attr_reader :inner_transport, :punt, :container_name, :config
20
20
 
21
- include Helpers::UploadFolder
21
+ include Helpers::FolderTxfr
22
22
  include Helpers::UsersMixin
23
23
 
24
24
  def execute(command, options = {}, &block)
@@ -33,7 +33,7 @@ module NexusSW
33
33
  end
34
34
 
35
35
  def read_file(path)
36
- tfile = inner_mktmp
36
+ tfile = Transport.remote_tempname(container_name)
37
37
  retval = execute("#{@container_name}#{path} #{tfile}", subcommand: 'file pull', capture: false)
38
38
  # return '' if retval.exitstatus == 1
39
39
  retval.error!
@@ -45,7 +45,7 @@ module NexusSW
45
45
  def write_file(path, content, options = {})
46
46
  perms = file_perms(options)
47
47
 
48
- tfile = inner_mktmp
48
+ tfile = Transport.remote_tempname(container_name)
49
49
  inner_transport.write_file tfile, content
50
50
  execute("#{tfile} #{container_name}#{path}", subcommand: "file push#{perms}", capture: false).error!
51
51
  ensure
@@ -53,9 +53,9 @@ module NexusSW
53
53
  end
54
54
 
55
55
  def download_file(path, local_path)
56
- tfile = inner_mktmp if punt
56
+ tfile = Transport.remote_tempname(container_name) if punt
57
57
  localname = tfile || local_path
58
- execute("#{container_name}#{path} #{localname}", subcommand: 'file pull', capture: false).error!
58
+ execute("#{container_name}#{path} #{localname}", subcommand: 'file pull').error!
59
59
  inner_transport.download_file tfile, local_path if tfile
60
60
  ensure
61
61
  inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
@@ -64,10 +64,10 @@ module NexusSW
64
64
  def upload_file(local_path, path, options = {})
65
65
  perms = file_perms(options)
66
66
 
67
- tfile = inner_mktmp if punt
67
+ tfile = Transport.remote_tempname(container_name) if punt
68
68
  localname = tfile || local_path
69
69
  inner_transport.upload_file local_path, tfile if tfile
70
- execute("#{localname} #{container_name}#{path}", subcommand: "file push#{perms}", capture: false).error!
70
+ execute("#{localname} #{container_name}#{path}", subcommand: "file push#{perms}").error!
71
71
  ensure
72
72
  inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
73
73
  end
@@ -79,6 +79,12 @@ module NexusSW
79
79
  execute("-r #{local_path} #{container_name}#{path}", subcommand: "file push#{perms}", capture: false).error!
80
80
  end
81
81
 
82
+ def download_folder(path, local_path)
83
+ return super unless config[:info] && config[:info]['api_extensions'] && config[:info]['api_extensions'].include?('directory_manipulation')
84
+
85
+ execute("-r #{container_name}#{path} #{local_path}", subcommand: 'file pull', capture: false).error!
86
+ end
87
+
82
88
  def add_remote(host_name)
83
89
  execute("add #{host_name} --accept-certificate", subcommand: 'remote').error! unless remote? host_name
84
90
  end
@@ -101,14 +107,6 @@ module NexusSW
101
107
 
102
108
  private
103
109
 
104
- # kludge for windows environment
105
- def inner_mktmp
106
- tfile = Tempfile.new(container_name)
107
- "/tmp/#{File.basename tfile.path}"
108
- ensure
109
- tfile.unlink
110
- end
111
-
112
110
  def file_perms(options = {})
113
111
  perms = ''
114
112
  perms += " --uid=#{options[:uid] || uid || 0}"
@@ -1,41 +1,69 @@
1
+ require 'zlib'
2
+ require 'archive/tar/minitar'
3
+
1
4
  module NexusSW
2
5
  module LXD
3
6
  class Transport
4
7
  module Mixins
5
8
  module Helpers
6
- module UploadFolder
9
+ module FolderTxfr
7
10
  def upload_folder(local_path, path, options = {})
8
11
  upload_using_tarball(local_path, path, options) || upload_files_individually(local_path, path, options)
9
12
  end
10
13
 
14
+ def download_folder(path, local_path)
15
+ download_using_tarball(path, local_path) || download_files_individually(path, local_path)
16
+ end
17
+
11
18
  def upload_files_individually(local_path, path, options = {})
19
+ dest = File.join(path, File.basename(local_path))
20
+ execute('mkdir -p ' + dest).error! # for parity with tarball extract
12
21
  Dir.entries(local_path).map { |f| (f == '.' || f == '..') ? nil : File.join(local_path, f) }.compact.each do |f|
13
- dest = File.join(path, File.basename(local_path))
14
22
  upload_files_individually f, dest, options if File.directory? f
15
23
  upload_file f, File.join(dest, File.basename(f)), options if File.file? f
16
24
  end
17
25
  end
18
26
 
27
+ def download_files_individually(path, local_path)
28
+ dest = File.join(local_path, File.basename(path))
29
+ execute("bash -c 'cd #{path} && find -type d'").error!.stdout.each_line do |line|
30
+ newdir = line.strip.sub(/^\./, dest)
31
+ Dir.mkdir newdir unless Dir.exist? newdir
32
+ end
33
+ execute("bash -c 'cd #{path} && find ! -type d'").error!.stdout.each_line do |line|
34
+ download_file line.strip.sub(/^\./, path), line.strip.sub(/^\./, dest)
35
+ end
36
+ end
37
+
38
+ # gzip(-z) or bzip2(-j) (these are the only 2 on trusty atm)
39
+ def download_using_tarball(path, local_path)
40
+ return false unless can_archive?
41
+ tfile = Transport.remote_tempname(container_name)
42
+ tarball_name = File.join Transport.local_tempdir, File.basename(tfile) + '.tgz'
43
+ execute("tar -czf #{tfile} -C #{File.dirname path} #{File.basename path}").error!
44
+
45
+ download_file tfile, tarball_name
46
+
47
+ Archive::Tar::Minitar.unpack Zlib::GzipReader.new(File.open(tarball_name, 'rb')), local_path
48
+ ensure
49
+ if tarball_name
50
+ File.delete tarball_name if File.exist? tarball_name
51
+ execute "rm -rf #{tfile}"
52
+ end
53
+ end
54
+
19
55
  def upload_using_tarball(local_path, path, options = {})
20
56
  return false unless can_archive?
21
- # TODO: should I return false upon error? i.e. retry with individual file uploads if this fails?
22
- # lets see how this does in the wild before deciding
23
- flag, ext = compression
24
57
  begin
25
58
  tfile = Tempfile.new(container_name)
26
59
  tfile.close
27
- `tar -c#{flag}f #{tfile.path} -C #{File.dirname local_path} ./#{File.basename local_path}`
28
- # on that above note we'll do this at least
29
- # raise "Unable to create archive #{tfile.path}" if File.zero? tfile.path
30
- if File.zero? tfile.path
31
- @can_archive = false
32
- return false
60
+ Dir.chdir File.dirname(local_path) do
61
+ Archive::Tar::Minitar.pack File.basename(local_path), Zlib::GzipWriter.new(File.open(tfile.path, 'wb'))
33
62
  end
34
- fname = '/tmp/' + File.basename(tfile.path) + ".tar#{ext}"
63
+ # `tar -c#{flag}f #{tfile.path} -C #{File.dirname local_path} ./#{File.basename local_path}`
64
+ fname = '/tmp/' + File.basename(tfile.path) + '.tgz'
35
65
  upload_file tfile.path, fname, options
36
- # TODO: serious: make sure the tar extract does an overwrite of existing files
37
- # multiple converge support as well as CI cycle/dev updated files get updated instead of .1 suffixed (?)
38
- # I think I need a flag (it's been a while)
66
+
39
67
  myuid = options[:uid] || uid || (0 if is_a?(Mixins::CLI))
40
68
  mygid = options[:gid] || gid || (0 if is_a?(Mixins::CLI))
41
69
  mymode = options[:file_mode] || file_mode
@@ -57,25 +85,11 @@ module NexusSW
57
85
  return false if respond_to?(:inner_transport) && inner_transport.respond_to?(:mock)
58
86
  return false if respond_to?(:inner_transport) && inner_transport.respond_to?(:inner_transport) && inner_transport.inner_transport.respond_to?(:mock)
59
87
  return false if respond_to?(:inner_transport) && inner_transport.respond_to?(:api) && inner_transport.api.respond_to?(:mock)
60
- `tar --version`
61
88
  true
62
89
  rescue
63
90
  false
64
91
  end
65
92
  end
66
-
67
- # gzip(-z) or bzip2(-j) (these are the only 2 on trusty atm)
68
- def compression
69
- @compression ||= begin
70
- which = execute('bash -c "which gzip || which bzip2 || true"').stdout.strip
71
- which = File.basename(which) if which
72
- case which
73
- when 'gzip' then ['z', '.gz']
74
- when 'bzip2' then ['j', '.bzip2']
75
- else ['', '']
76
- end
77
- end
78
- end
79
93
  end
80
94
  end
81
95
  end
@@ -1,6 +1,6 @@
1
1
  require 'nexussw/lxd/transport/mixins/helpers/execute'
2
2
  require 'nexussw/lxd/transport/mixins/helpers/users'
3
- require 'nexussw/lxd/transport/mixins/helpers/upload_folder'
3
+ require 'nexussw/lxd/transport/mixins/helpers/folder_txfr'
4
4
  require 'nio/websocket'
5
5
  require 'tempfile'
6
6
  require 'json'
@@ -23,7 +23,7 @@ module NexusSW
23
23
  attr_reader :api, :rest_endpoint, :container_name, :config
24
24
 
25
25
  include Helpers::ExecuteMixin
26
- include Helpers::UploadFolder
26
+ include Helpers::FolderTxfr
27
27
  include Helpers::UsersMixin
28
28
 
29
29
  class StdinStub
@@ -1,5 +1,5 @@
1
1
  module NexusSW
2
2
  module LXD
3
- VERSION = '0.8.1'.freeze
3
+ VERSION = '0.9.0'.freeze
4
4
  end
5
5
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_dependency 'faraday', '~> 0.13'
23
23
  spec.add_dependency 'nio4r-websocket', '~> 0.6'
24
+ spec.add_dependency 'minitar', '~> 0.5'
24
25
 
25
26
  spec.add_development_dependency 'bundler'
26
27
  spec.add_development_dependency 'rake'
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.8.1
4
+ version: 0.9.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-21 00:00:00.000000000 Z
11
+ date: 2018-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.5'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -126,7 +140,7 @@ files:
126
140
  - lib/nexussw/lxd/transport/local.rb
127
141
  - lib/nexussw/lxd/transport/mixins/cli.rb
128
142
  - lib/nexussw/lxd/transport/mixins/helpers/execute.rb
129
- - lib/nexussw/lxd/transport/mixins/helpers/upload_folder.rb
143
+ - lib/nexussw/lxd/transport/mixins/helpers/folder_txfr.rb
130
144
  - lib/nexussw/lxd/transport/mixins/helpers/users.rb
131
145
  - lib/nexussw/lxd/transport/mixins/local.rb
132
146
  - lib/nexussw/lxd/transport/mixins/rest.rb