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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +61 -0
- data/.travis.yml +21 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +17 -0
- data/README.md +122 -0
- data/Rakefile +17 -0
- data/bin/cloudkeeper +5 -0
- data/cloudkeeper.gemspec +45 -0
- data/config/cloudkeeper.yml +27 -0
- data/lib/cloudkeeper.rb +16 -0
- data/lib/cloudkeeper/backend_connector.rb +123 -0
- data/lib/cloudkeeper/cli.rb +174 -0
- data/lib/cloudkeeper/command_executioner.rb +22 -0
- data/lib/cloudkeeper/entities.rb +11 -0
- data/lib/cloudkeeper/entities/appliance.rb +84 -0
- data/lib/cloudkeeper/entities/conversions.rb +48 -0
- data/lib/cloudkeeper/entities/convertables.rb +8 -0
- data/lib/cloudkeeper/entities/convertables/convertable.rb +63 -0
- data/lib/cloudkeeper/entities/convertables/ova.rb +54 -0
- data/lib/cloudkeeper/entities/image.rb +40 -0
- data/lib/cloudkeeper/entities/image_file.rb +23 -0
- data/lib/cloudkeeper/entities/image_formats.rb +7 -0
- data/lib/cloudkeeper/entities/image_formats/ova.rb +41 -0
- data/lib/cloudkeeper/entities/image_list.rb +84 -0
- data/lib/cloudkeeper/errors.rb +20 -0
- data/lib/cloudkeeper/errors/appliance.rb +7 -0
- data/lib/cloudkeeper/errors/appliance/propagation_error.rb +7 -0
- data/lib/cloudkeeper/errors/argument_error.rb +5 -0
- data/lib/cloudkeeper/errors/backend_error.rb +5 -0
- data/lib/cloudkeeper/errors/command_execution_error.rb +5 -0
- data/lib/cloudkeeper/errors/convertables.rb +7 -0
- data/lib/cloudkeeper/errors/convertables/convertability_error.rb +7 -0
- data/lib/cloudkeeper/errors/image.rb +9 -0
- data/lib/cloudkeeper/errors/image/conversion_error.rb +7 -0
- data/lib/cloudkeeper/errors/image/download_error.rb +7 -0
- data/lib/cloudkeeper/errors/image/format.rb +12 -0
- data/lib/cloudkeeper/errors/image/format/no_format_recognized_error.rb +9 -0
- data/lib/cloudkeeper/errors/image/format/no_required_format_available_error.rb +9 -0
- data/lib/cloudkeeper/errors/image/format/ova.rb +12 -0
- data/lib/cloudkeeper/errors/image/format/ova/invalid_archive_error.rb +11 -0
- data/lib/cloudkeeper/errors/image/format/ova/ova_format_error.rb +11 -0
- data/lib/cloudkeeper/errors/image/format/recognition_error.rb +9 -0
- data/lib/cloudkeeper/errors/image_list.rb +9 -0
- data/lib/cloudkeeper/errors/image_list/download_error.rb +7 -0
- data/lib/cloudkeeper/errors/image_list/retrieval_error.rb +7 -0
- data/lib/cloudkeeper/errors/image_list/verification_error.rb +7 -0
- data/lib/cloudkeeper/errors/invalid_configuration_error.rb +5 -0
- data/lib/cloudkeeper/errors/invalid_url_error.rb +5 -0
- data/lib/cloudkeeper/errors/network_connection_error.rb +5 -0
- data/lib/cloudkeeper/errors/nginx_error.rb +5 -0
- data/lib/cloudkeeper/errors/no_such_file_error.rb +5 -0
- data/lib/cloudkeeper/errors/not_implemented_error.rb +5 -0
- data/lib/cloudkeeper/errors/parsing.rb +10 -0
- data/lib/cloudkeeper/errors/parsing/invalid_appliance_hash_error.rb +7 -0
- data/lib/cloudkeeper/errors/parsing/invalid_image_hash_error.rb +7 -0
- data/lib/cloudkeeper/errors/parsing/invalid_image_list_hash_error.rb +7 -0
- data/lib/cloudkeeper/errors/parsing/parsing_error.rb +7 -0
- data/lib/cloudkeeper/errors/permission_denied_error.rb +5 -0
- data/lib/cloudkeeper/errors/standard_error.rb +5 -0
- data/lib/cloudkeeper/managers.rb +7 -0
- data/lib/cloudkeeper/managers/appliance_manager.rb +152 -0
- data/lib/cloudkeeper/managers/image_list_manager.rb +88 -0
- data/lib/cloudkeeper/managers/image_manager.rb +82 -0
- data/lib/cloudkeeper/nginx.rb +5 -0
- data/lib/cloudkeeper/nginx/http_server.rb +113 -0
- data/lib/cloudkeeper/nginx/templates/nginx.conf.erb +32 -0
- data/lib/cloudkeeper/settings.rb +19 -0
- data/lib/cloudkeeper/utils.rb +7 -0
- data/lib/cloudkeeper/utils/checksum.rb +9 -0
- data/lib/cloudkeeper/utils/hash.rb +9 -0
- data/lib/cloudkeeper/utils/url.rb +11 -0
- data/lib/cloudkeeper/version.rb +3 -0
- data/lib/cloudkeeper_grpc.rb +5 -0
- 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,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,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,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,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
|