lxd-common 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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