cloudkeeper 1.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.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +61 -0
  6. data/.travis.yml +21 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +17 -0
  10. data/README.md +122 -0
  11. data/Rakefile +17 -0
  12. data/bin/cloudkeeper +5 -0
  13. data/cloudkeeper.gemspec +45 -0
  14. data/config/cloudkeeper.yml +27 -0
  15. data/lib/cloudkeeper.rb +16 -0
  16. data/lib/cloudkeeper/backend_connector.rb +123 -0
  17. data/lib/cloudkeeper/cli.rb +174 -0
  18. data/lib/cloudkeeper/command_executioner.rb +22 -0
  19. data/lib/cloudkeeper/entities.rb +11 -0
  20. data/lib/cloudkeeper/entities/appliance.rb +84 -0
  21. data/lib/cloudkeeper/entities/conversions.rb +48 -0
  22. data/lib/cloudkeeper/entities/convertables.rb +8 -0
  23. data/lib/cloudkeeper/entities/convertables/convertable.rb +63 -0
  24. data/lib/cloudkeeper/entities/convertables/ova.rb +54 -0
  25. data/lib/cloudkeeper/entities/image.rb +40 -0
  26. data/lib/cloudkeeper/entities/image_file.rb +23 -0
  27. data/lib/cloudkeeper/entities/image_formats.rb +7 -0
  28. data/lib/cloudkeeper/entities/image_formats/ova.rb +41 -0
  29. data/lib/cloudkeeper/entities/image_list.rb +84 -0
  30. data/lib/cloudkeeper/errors.rb +20 -0
  31. data/lib/cloudkeeper/errors/appliance.rb +7 -0
  32. data/lib/cloudkeeper/errors/appliance/propagation_error.rb +7 -0
  33. data/lib/cloudkeeper/errors/argument_error.rb +5 -0
  34. data/lib/cloudkeeper/errors/backend_error.rb +5 -0
  35. data/lib/cloudkeeper/errors/command_execution_error.rb +5 -0
  36. data/lib/cloudkeeper/errors/convertables.rb +7 -0
  37. data/lib/cloudkeeper/errors/convertables/convertability_error.rb +7 -0
  38. data/lib/cloudkeeper/errors/image.rb +9 -0
  39. data/lib/cloudkeeper/errors/image/conversion_error.rb +7 -0
  40. data/lib/cloudkeeper/errors/image/download_error.rb +7 -0
  41. data/lib/cloudkeeper/errors/image/format.rb +12 -0
  42. data/lib/cloudkeeper/errors/image/format/no_format_recognized_error.rb +9 -0
  43. data/lib/cloudkeeper/errors/image/format/no_required_format_available_error.rb +9 -0
  44. data/lib/cloudkeeper/errors/image/format/ova.rb +12 -0
  45. data/lib/cloudkeeper/errors/image/format/ova/invalid_archive_error.rb +11 -0
  46. data/lib/cloudkeeper/errors/image/format/ova/ova_format_error.rb +11 -0
  47. data/lib/cloudkeeper/errors/image/format/recognition_error.rb +9 -0
  48. data/lib/cloudkeeper/errors/image_list.rb +9 -0
  49. data/lib/cloudkeeper/errors/image_list/download_error.rb +7 -0
  50. data/lib/cloudkeeper/errors/image_list/retrieval_error.rb +7 -0
  51. data/lib/cloudkeeper/errors/image_list/verification_error.rb +7 -0
  52. data/lib/cloudkeeper/errors/invalid_configuration_error.rb +5 -0
  53. data/lib/cloudkeeper/errors/invalid_url_error.rb +5 -0
  54. data/lib/cloudkeeper/errors/network_connection_error.rb +5 -0
  55. data/lib/cloudkeeper/errors/nginx_error.rb +5 -0
  56. data/lib/cloudkeeper/errors/no_such_file_error.rb +5 -0
  57. data/lib/cloudkeeper/errors/not_implemented_error.rb +5 -0
  58. data/lib/cloudkeeper/errors/parsing.rb +10 -0
  59. data/lib/cloudkeeper/errors/parsing/invalid_appliance_hash_error.rb +7 -0
  60. data/lib/cloudkeeper/errors/parsing/invalid_image_hash_error.rb +7 -0
  61. data/lib/cloudkeeper/errors/parsing/invalid_image_list_hash_error.rb +7 -0
  62. data/lib/cloudkeeper/errors/parsing/parsing_error.rb +7 -0
  63. data/lib/cloudkeeper/errors/permission_denied_error.rb +5 -0
  64. data/lib/cloudkeeper/errors/standard_error.rb +5 -0
  65. data/lib/cloudkeeper/managers.rb +7 -0
  66. data/lib/cloudkeeper/managers/appliance_manager.rb +152 -0
  67. data/lib/cloudkeeper/managers/image_list_manager.rb +88 -0
  68. data/lib/cloudkeeper/managers/image_manager.rb +82 -0
  69. data/lib/cloudkeeper/nginx.rb +5 -0
  70. data/lib/cloudkeeper/nginx/http_server.rb +113 -0
  71. data/lib/cloudkeeper/nginx/templates/nginx.conf.erb +32 -0
  72. data/lib/cloudkeeper/settings.rb +19 -0
  73. data/lib/cloudkeeper/utils.rb +7 -0
  74. data/lib/cloudkeeper/utils/checksum.rb +9 -0
  75. data/lib/cloudkeeper/utils/hash.rb +9 -0
  76. data/lib/cloudkeeper/utils/url.rb +11 -0
  77. data/lib/cloudkeeper/version.rb +3 -0
  78. data/lib/cloudkeeper_grpc.rb +5 -0
  79. metadata +416 -0
@@ -0,0 +1,40 @@
1
+ module Cloudkeeper
2
+ module Entities
3
+ class Image
4
+ attr_accessor :image_files, :size, :uri, :checksum
5
+
6
+ def initialize(uri, checksum, size = 0, image_files = [])
7
+ raise Cloudkeeper::Errors::ArgumentError, 'uri and checksum cannot be nil nor empty' if uri.blank? || checksum.blank?
8
+
9
+ @uri = uri
10
+ @checksum = checksum
11
+ @size = size
12
+ @image_files = image_files
13
+ end
14
+
15
+ def add_image_file(file)
16
+ raise Cloudkeeper::Errors::ArgumentError, 'image file cannot be nil' if file.nil?
17
+
18
+ image_files << file
19
+ end
20
+
21
+ def available_formats
22
+ image_files.map(&:format).sort
23
+ end
24
+
25
+ def image_file(format)
26
+ image_files.select { |file| file.format == format }.first
27
+ end
28
+
29
+ def self.from_hash(image_hash)
30
+ raise Cloudkeeper::Errors::Parsing::InvalidImageHashError, 'invalid image hash' if image_hash.blank?
31
+
32
+ image_hash.deep_symbolize_keys!
33
+ Image.new image_hash[:'hv:uri'], image_hash[:'sl:checksum:sha512'], image_hash[:'hv:size']
34
+ rescue Cloudkeeper::Errors::ArgumentError => ex
35
+ raise Cloudkeeper::Errors::Parsing::InvalidImageHashError, ex, "image hash #{image_hash.inspect} " \
36
+ "doesn't contain all the necessary data"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,23 @@
1
+ module Cloudkeeper
2
+ module Entities
3
+ class ImageFile
4
+ attr_accessor :file, :checksum, :format, :original
5
+
6
+ include Cloudkeeper::Entities::Convertables::Convertable
7
+
8
+ def initialize(file, format, checksum, original = false)
9
+ raise Cloudkeeper::Errors::ArgumentError, 'file, format and checksum cannot be nil nor empty'\
10
+ if file.blank? || format.blank? || checksum.blank?
11
+
12
+ @file = file
13
+ @checksum = checksum
14
+ @format = format
15
+ @original = original
16
+
17
+ format_const_symbol = format.to_s.classify.to_sym
18
+ extend(Cloudkeeper::Entities::Convertables.const_get(format_const_symbol)) \
19
+ if Cloudkeeper::Entities::Convertables.const_defined? format_const_symbol
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Entities
3
+ module ImageFormats
4
+ autoload :Ova, 'cloudkeeper/entities/image_formats/ova'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ module Cloudkeeper
2
+ module Entities
3
+ module ImageFormats
4
+ module Ova
5
+ OVF_REGEX = /^.+\.ovf$/i
6
+ VMDK_REGEX = /^.+\.vmdk$/i
7
+ ARCHIVE_MAX_FILES = 100
8
+
9
+ def ova?(archive)
10
+ ova_structure?(archive_files(archive))
11
+ rescue Cloudkeeper::Errors::CommandExecutionError, Cloudkeeper::Errors::Image::Format::Ova::InvalidArchiveError => ex
12
+ raise Cloudkeeper::Errors::Image::Format::Ova::OvaFormatError, ex
13
+ end
14
+
15
+ def archive_files(archive)
16
+ Cloudkeeper::CommandExecutioner.list_archive archive
17
+ end
18
+
19
+ def ova_structure?(files)
20
+ check_count! files
21
+ has_ovf = has_vmdk = false
22
+
23
+ files.each do |file|
24
+ has_ovf ||= OVF_REGEX =~ file
25
+ has_vmdk ||= VMDK_REGEX =~ file
26
+ break if has_ovf && has_vmdk
27
+ end
28
+
29
+ has_ovf && has_vmdk
30
+ end
31
+
32
+ def check_count!(files)
33
+ return unless files.count > ARCHIVE_MAX_FILES
34
+
35
+ raise Cloudkeeper::Errors::Image::Format::Ova::InvalidArchiveError, "Too many files in archive: #{files.count}. "\
36
+ "Maximum is #{ARCHIVE_MAX_FILES}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,84 @@
1
+ require 'date'
2
+
3
+ module Cloudkeeper
4
+ module Entities
5
+ class ImageList
6
+ attr_accessor :identifier, :creation_date, :expiration_date, :description, :title, :source, :appliances
7
+
8
+ DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'.freeze
9
+
10
+ def initialize(identifier, expiration_date, creation_date = nil, source = '', title = '', description = '', appliances = {})
11
+ raise Cloudkeeper::Errors::ArgumentError, 'identifier cannot be nil nor empty' if identifier.blank? || expiration_date.blank?
12
+
13
+ @identifier = identifier
14
+ @expiration_date = expiration_date
15
+ @creation_date = creation_date
16
+ @description = description
17
+ @title = title
18
+ @source = source
19
+ @appliances = appliances
20
+ end
21
+
22
+ def add_appliance(appliance)
23
+ raise Cloudkeeper::Errors::ArgumentError, 'appliance cannot be nil' unless appliance
24
+
25
+ appliances[appliance.identifier] = appliance
26
+ end
27
+
28
+ def expired?
29
+ expiration_date < DateTime.now
30
+ end
31
+
32
+ class << self
33
+ def from_hash(image_list_hash)
34
+ image_list_hash.deep_symbolize_keys!
35
+ image_list_hash = image_list_hash[:'hv:imagelist']
36
+
37
+ image_list = populate_image_list image_list_hash
38
+ populate_appliances!(image_list, image_list_hash)
39
+
40
+ image_list
41
+ end
42
+
43
+ def prepare_appliance_hash(image_hash, endorser, expiration, vo, image_list_identifier)
44
+ appliance_hash = {}
45
+
46
+ appliance_hash = image_hash[:'hv:image'] if image_hash && image_hash.key?(:'hv:image')
47
+ appliance_hash.merge!(vo: vo, expiration: expiration, image_list_identifier: image_list_identifier)
48
+ appliance_hash.merge!(endorser[:'hv:x509']) if endorser && endorser.key?(:'hv:x509')
49
+
50
+ appliance_hash
51
+ end
52
+
53
+ def populate_image_list(image_list_hash)
54
+ raise Cloudkeeper::Errors::Parsing::InvalidImageListHashError, 'invalid image list hash' if image_list_hash.blank?
55
+
56
+ ImageList.new image_list_hash[:'dc:identifier'],
57
+ parse_date(image_list_hash[:'dc:date:expires']),
58
+ parse_date(image_list_hash[:'dc:date:created']),
59
+ image_list_hash[:'dc:source'],
60
+ image_list_hash[:'dc:title'],
61
+ image_list_hash[:'dc:description']
62
+ rescue Cloudkeeper::Errors::ArgumentError => ex
63
+ raise Cloudkeeper::Errors::Parsing::InvalidImageListHashError, ex, "image list hash #{image_list_hash.inspect} " \
64
+ "doesn't contain all the necessary data"
65
+ end
66
+
67
+ def parse_date(date)
68
+ date.blank? ? '' : DateTime.strptime(date, DATE_FORMAT)
69
+ end
70
+
71
+ def populate_appliances!(image_list, image_list_hash)
72
+ expiration = parse_date(image_list_hash[:'dc:date:expires'])
73
+ vo = image_list_hash[:'ad:vo']
74
+ endorser = image_list_hash[:'hv:endorser']
75
+
76
+ image_list_hash[:'hv:images'].each do |image_hash|
77
+ appliance = Appliance.from_hash(prepare_appliance_hash(image_hash, endorser, expiration, vo, image_list.identifier))
78
+ image_list.add_appliance appliance
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,20 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ autoload :StandardError, 'cloudkeeper/errors/standard_error'
4
+ autoload :ArgumentError, 'cloudkeeper/errors/argument_error'
5
+ autoload :NotImplementedError, 'cloudkeeper/errors/not_implemented_error'
6
+ autoload :InvalidURLError, 'cloudkeeper/errors/invalid_url_error'
7
+ autoload :NoSuchFileError, 'cloudkeeper/errors/no_such_file_error'
8
+ autoload :PermissionDeniedError, 'cloudkeeper/errors/permission_denied_error'
9
+ autoload :CommandExecutionError, 'cloudkeeper/errors/command_execution_error'
10
+ autoload :NginxError, 'cloudkeeper/errors/nginx_error'
11
+ autoload :BackendError, 'cloudkeeper/errors/backend_error'
12
+ autoload :InvalidConfigurationError, 'cloudkeeper/errors/invalid_configuration_error'
13
+
14
+ autoload :Parsing, 'cloudkeeper/errors/parsing'
15
+ autoload :ImageList, 'cloudkeeper/errors/image_list'
16
+ autoload :Image, 'cloudkeeper/errors/image'
17
+ autoload :Convertables, 'cloudkeeper/errors/convertables'
18
+ autoload :Appliance, 'cloudkeeper/errors/appliance'
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Appliance
4
+ autoload :PropagationError, 'cloudkeeper/errors/appliance/propagation_error'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Appliance
4
+ class PropagationError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ class ArgumentError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ class BackendError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ class CommandExecutionError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Convertables
4
+ autoload :ConvertabilityError, 'cloudkeeper/errors/convertables/convertability_error'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Convertables
4
+ class ConvertabilityError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ autoload :Format, 'cloudkeeper/errors/image/format'
5
+ autoload :DownloadError, 'cloudkeeper/errors/image/download_error'
6
+ autoload :ConversionError, 'cloudkeeper/errors/image/conversion_error'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ class ConversionError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ class DownloadError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ autoload :Ova, 'cloudkeeper/errors/image/format/ova'
6
+ autoload :NoFormatRecognizedError, 'cloudkeeper/errors/image/format/no_format_recognized_error'
7
+ autoload :RecognitionError, 'cloudkeeper/errors/image/format/recognition_error'
8
+ autoload :NoRequiredFormatAvailableError, 'cloudkeeper/errors/image/format/no_required_format_available_error'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ class NoFormatRecognizedError < StandardError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ class NoRequiredFormatAvailableError < StandardError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ module Ova
6
+ autoload :OvaFormatError, 'cloudkeeper/errors/image/format/ova/ova_format_error'
7
+ autoload :InvalidArchiveError, 'cloudkeeper/errors/image/format/ova/invalid_archive_error'
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ module Ova
6
+ class InvalidArchiveError < StandardError; end
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ module Ova
6
+ class OvaFormatError < StandardError; end
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module Image
4
+ module Format
5
+ class RecognitionError < StandardError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module ImageList
4
+ autoload :VerificationError, 'cloudkeeper/errors/image_list/verification_error'
5
+ autoload :RetrievalError, 'cloudkeeper/errors/image_list/retrieval_error'
6
+ autoload :DownloadError, 'cloudkeeper/errors/image_list/download_error'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module ImageList
4
+ class DownloadError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module ImageList
4
+ class RetrievalError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ module ImageList
4
+ class VerificationError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ class InvalidConfigurationError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Cloudkeeper
2
+ module Errors
3
+ class InvalidURLError < StandardError; end
4
+ end
5
+ end