diff --git a/lib/gems/pending/util/miq_ftp_lib.rb b/lib/gems/pending/util/miq_ftp_lib.rb deleted file mode 100644 index 16b934d20..000000000 --- a/lib/gems/pending/util/miq_ftp_lib.rb +++ /dev/null @@ -1,76 +0,0 @@ -require 'net/ftp' - -# Helper methods for net/ftp based classes and files. -# -# Will setup a `@ftp` attr_accessor to be used as the return value for -# `.connect`, the main method being provided in this class. -module MiqFtpLib - def self.included(klass) - klass.send(:attr_accessor, :ftp) - end - - def connect(cred_hash = nil) - host = URI(uri).hostname - - begin - _log.info("Connecting to FTP host #{host_ref}...") - @ftp = Net::FTP.new(host) - # Use passive mode to avoid firewall issues see http://slacksite.com/other/ftp.html#passive - @ftp.passive = true - # @ftp.debug_mode = true if settings[:debug] # TODO: add debug option - creds = cred_hash ? [cred_hash[:username], cred_hash[:password]] : login_credentials - @ftp.login(*creds) - _log.info("Successfully connected FTP host #{host_ref}...") - rescue SocketError => err - _log.error("Failed to connect. #{err.message}") - raise - rescue Net::FTPPermError => err - _log.error("Failed to login. #{err.message}") - raise - else - @ftp - end - end - - def file_exists?(file_or_directory) - !ftp.nlst(file_or_directory.to_s).empty? - rescue Net::FTPPermError - false - end - - private - - def host_ref - return @host_ref if @host_ref - @host_ref = URI(uri).hostname - @host_ref << " (#{name})" if respond_to?(:name) - @host_ref - end - - def create_directory_structure(directory_path) - pwd = ftp.pwd - directory_path.to_s.split('/').each do |directory| - unless ftp.nlst.include?(directory) - _log.info("creating #{directory}") - ftp.mkdir(directory) - end - ftp.chdir(directory) - end - rescue Net::FTPPermError - raise unless @username.nil? && @password.nil? - _log.info("introspection of directories disabled. skipping create_directory_structure") - ensure - ftp.chdir(pwd) if pwd - end - - def with_connection(cred_hash = nil) - raise _("no block given") unless block_given? - _log.info("Connecting through #{self.class.name}: [#{host_ref}]") - begin - connect(cred_hash) - yield @ftp - ensure - @ftp.try(:close) && @ftp = nil - end - end -end diff --git a/lib/gems/pending/util/miq_object_storage.rb b/lib/gems/pending/util/miq_object_storage.rb deleted file mode 100644 index 19b499e6c..000000000 --- a/lib/gems/pending/util/miq_object_storage.rb +++ /dev/null @@ -1,62 +0,0 @@ -require 'net/protocol' -require 'util/miq_file_storage' - -class MiqObjectStorage < MiqFileStorage::Interface - require 'util/object_storage/miq_s3_storage' - require 'util/object_storage/miq_ftp_storage' - require 'util/object_storage/miq_swift_storage' - - attr_accessor :settings - attr_writer :logger - - DEFAULT_CHUNKSIZE = Net::BufferedIO::BUFSIZE - - def initialize(settings) - raise "URI missing" unless settings.key?(:uri) - @settings = settings.dup - end - - def logger - @logger ||= $log.nil? ? :: Logger.new(STDOUT) : $log - end - - private - - DONE_READING = "".freeze - def read_single_chunk(chunksize = DEFAULT_CHUNKSIZE) - @buf_left ||= byte_count - return DONE_READING.dup unless @buf_left.nil? || @buf_left.positive? - cur_readsize = if @buf_left.nil? || @buf_left - chunksize >= 0 - chunksize - else - @buf_left - end - buf = source_input.read(cur_readsize) - @buf_left -= chunksize if @buf_left - buf.to_s - end - - def write_single_split_file_for(file_io) - loop do - input_data = read_single_chunk - break if input_data.empty? - file_io.write(input_data) - end - clear_split_vars - end - - def write_chunk_proc(destination) - # We use a `proc` here instead of `lambda` because we are only concerned - # about the first argument, and other arguments (additional ones added by - # Excon's response_call signature, for example) are unneeded. - # - # `lambda do` will do argument checking, while `proc do` won't. - proc do |chunk| - destination.write(chunk.force_encoding(destination.external_encoding)) - end - end - - def clear_split_vars - @buf_left = nil - end -end diff --git a/lib/gems/pending/util/mount/miq_local_mount_session.rb b/lib/gems/pending/util/mount/miq_local_mount_session.rb deleted file mode 100644 index 0395e7c20..000000000 --- a/lib/gems/pending/util/mount/miq_local_mount_session.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'util/mount/miq_generic_mount_session' - -# MiqLocalMountSession is meant to be a representation of the local file system -# that conforms to the same interface as MiqLocalMountSession (and by proxy, -# MiqFileSystem::Interface). -# -# See MiqGenericMountSession for info on methods available. -class MiqLocalMountSession < MiqGenericMountSession - def self.uri_scheme - "file".freeze - end - - # no-op these since they are not relavent to the local file system - # - # rubocop:disable Style/SingleLineMethods, Layout/EmptyLineBetweenDefs - def connect; end # :nodoc: - def disconnect; end # :nodoc: - def mount_share; end # :nodoc: - # rubocop:enable Style/SingleLineMethods, Layout/EmptyLineBetweenDefs - - def relative_to_mount(remote_file) # :nodoc: - remote_file - end - - def uri_to_local_path(remote_file) # :nodoc: - File.expand_path(remote_file) - end -end diff --git a/lib/gems/pending/util/mount/miq_smb_session.rb b/lib/gems/pending/util/mount/miq_smb_session.rb deleted file mode 100644 index ca7dc290e..000000000 --- a/lib/gems/pending/util/mount/miq_smb_session.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'util/mount/miq_generic_mount_session' - -class MiqSmbSession < MiqGenericMountSession - PORTS = [445, 139] - - def self.uri_scheme - "smb".freeze - end - - def initialize(log_settings) - super(log_settings.merge(:ports => PORTS)) - raise "username is a required value!" if @settings[:username].nil? - raise "password is a required value!" if @settings[:password].nil? - end - - def connect - scheme, userinfo, @host, port, registry, @mount_root, opaque, query, fragment = URI.split(URI::DEFAULT_PARSER.escape(@settings[:uri])) - @mount_path = @mount_root.split("/")[0..1].join("/") - super - end - - def mount_root - File.join(@mnt_point, (@mount_root.split("/") - @mount_path.split("/"))) - end - - def mount_share - super - - log_header = "MIQ(#{self.class.name}-mount_share)" - # Convert backslashes to slashes in case the username is in domain\username format - @settings[:username] = @settings[:username].tr('\\', '/') - - # To work around 2.6.18 kernel issue where a domain could be passed along incorrectly if not specified, explicitly provide both the username and domain (set the domain 'null' if not provided) - # https://bugzilla.samba.org/show_bug.cgi?id=4176 - split_username = @settings[:username].split('/') - case split_username.length - when 1 - # No domain provided - user = split_username.first - domain = 'null' - when 2 - domain, user = split_username - else - raise "Expected 'domain/username' or 'domain\\username' format, received: '#{@settings[:username]}'" - end - - mount_args = {:t => "cifs"} - mount_args[:r] = nil if settings_read_only? - mount_args[nil] = %W[//#{File.join(@host, @mount_path)} #{@mnt_point}] - mount_args[:o] = "rw,username=#{user},password=#{@settings[:password]},domain=#{domain}" - - logger.info("#{log_header} Connecting to host: [#{@host}], share: [#{@mount_path}], domain: [#{domain}], user: [#{user}], using mount point: [#{@mnt_point}]...") - # mount -t cifs //192.168.252.140/temp /media/windows_share/ -o rw,username=jrafaniello,password=blah,domain=manageiq.com - - mount(mount_args) - logger.info("#{log_header} Connecting to host: [#{@host}], share: [#{@mount_path}]...Complete") - end -end diff --git a/lib/gems/pending/util/object_storage/miq_ftp_storage.rb b/lib/gems/pending/util/object_storage/miq_ftp_storage.rb deleted file mode 100644 index da81a0d16..000000000 --- a/lib/gems/pending/util/object_storage/miq_ftp_storage.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'util/miq_ftp_lib' -require 'util/miq_object_storage' -require 'logger' - -class MiqFtpStorage < MiqObjectStorage - include MiqFtpLib - - attr_reader :uri, :username, :password - - def self.uri_scheme - "ftp".freeze - end - - def self.new_with_opts(opts) - new(opts.slice(:uri, :username, :password)) - end - - def initialize(settings) - super - @uri = @settings[:uri] - @username = @settings[:username] - @password = @settings[:password] - end - - # Override for connection handling - def add(*upload_args) - with_connection { super } - end - - # Override for connection handling - def download(*download_args) - with_connection { super } - end - - # Override for connection handling - def magic_number_for(*magic_number_for_args) - with_connection { super } - end - - # Specific version of Net::FTP#storbinary that doesn't use an existing local - # file, and only uploads a specific size (byte_count) from the input_file - def upload_single(dest_uri) - ftp.synchronize do - ftp.send(:with_binary, true) do - conn = ftp.send(:transfercmd, "STOR #{uri_to_relative(dest_uri)}") - IO.copy_stream(source_input, conn, byte_count) - conn.close - ftp.send(:voidresp) - end - end - dest_uri - rescue Errno::EPIPE - # EPIPE, in this case, means that the data connection was unexpectedly - # terminated. Rather than just raising EPIPE to the caller, check the - # response on the control connection. If getresp doesn't raise a more - # appropriate exception, re-raise the original exception. - ftp.send(:getresp) - raise - end - - def download_single(source, destination) - ftp.synchronize do - ftp.send(:with_binary, true) do - begin - conn = ftp.send(:transfercmd, "RETR #{uri_to_relative(source)}") - IO.copy_stream(conn.io, destination, byte_count) - conn.shutdown(Socket::SHUT_WR) - conn.read_timeout = 1 - ensure - conn.close if conn - end - end - end - end - - def mkdir(dir) - create_directory_structure(uri_to_relative(dir)) - end - - private - - def login_credentials - [username, password].compact - end - - # Currently assumes you have just connected and are at the root logged in - # dir. Net::FTP (or ftp in general) doesn't seem to have a concept of a - # "root dir" based on your login, so this should be used right after - # `.connect`, or shortly there after. - # - # Or, you should be returning to the directory you came from prior to using - # this method again, or not using `ftp.chdir` at all. - def uri_to_relative(filepath) - result = URI.split(filepath)[5] - result = result[1..-1] if result[0] == "/".freeze - result - end - - def _log - logger - end -end diff --git a/lib/gems/pending/util/object_storage/miq_s3_storage.rb b/lib/gems/pending/util/object_storage/miq_s3_storage.rb deleted file mode 100644 index 63696d4c6..000000000 --- a/lib/gems/pending/util/object_storage/miq_s3_storage.rb +++ /dev/null @@ -1,105 +0,0 @@ -require 'util/miq_object_storage' - -class MiqS3Storage < MiqObjectStorage - attr_reader :bucket_name - - def self.uri_scheme - "s3".freeze - end - - def self.new_with_opts(opts) - new(opts.slice(:uri, :username, :password, :region)) - end - - def initialize(settings) - super(settings) - - # NOTE: This line to be removed once manageiq-ui-class region change implemented. - @settings[:region] ||= "us-east-1" - @bucket_name = URI(@settings[:uri]).host - - raise "username, password, and region are required values!" if @settings[:username].nil? || @settings[:password].nil? || @settings[:region].nil? - end - - # Extract the path from the URI, so strip off the "s3://" scheme, the bucket - # hostname, leaving only the path minus the leading '/' - def uri_to_object_key(remote_file) - # `path` is `[5]` in the returned result of URI.split - URI.split(remote_file)[5][1..-1] - end - - def upload_single(dest_uri) - object_key = uri_to_object_key(dest_uri) - logger.debug("Writing [#{source_input}] to => Bucket [#{bucket_name}] Key [#{dest_uri}]") - - with_standard_s3_error_handling("uploading", source_input) do - bucket.object(object_key).upload_stream do |write_stream| - IO.copy_stream(source_input, write_stream, byte_count) - end - end - end - - def download_single(source, destination) - object_key = uri_to_object_key(source) - logger.debug("Downloading [#{source}] from bucket [#{bucket_name}] to local file [#{destination}]") - - with_standard_s3_error_handling("downloading", source) do - if destination.kind_of?(IO) || destination.kind_of?(StringIO) - get_object_opts = { - :bucket => bucket_name, - :key => object_key - } - # :range is indexed starting at zero - get_object_opts[:range] = "bytes=0-#{byte_count - 1}" if byte_count - - s3.client.get_object(get_object_opts, &write_chunk_proc(destination)) - else # assume file path - bucket.object(source).download_file(destination) - end - end - end - - # no-op mostly - # - # dirs don't need to be created ahead of time in s3, unlike mounted file - # systems. - # - # For convenience though, calling bucket, which will initialize and create - # (if needed) the s3 bucket to be used for this instance. - def mkdir(_dir) - bucket - end - - def bucket - @bucket ||= s3.bucket(bucket_name).tap do |bucket| - if bucket.exists? - logger.debug("Found bucket #{bucket_name}") - else - logger.debug("Bucket #{bucket_name} does not exist, creating.") - bucket.create - end - end - end - - private - - def s3 - require 'aws-sdk-s3' - - @s3 ||= Aws::S3::Resource.new(:region => @settings[:region], - :access_key_id => @settings[:username], - :secret_access_key => @settings[:password]) - end - - def with_standard_s3_error_handling(action, object) - yield - rescue Aws::S3::Errors::AccessDenied, Aws::S3::Errors::Forbidden => err - logger.error("Access to S3 bucket #{bucket_name} restricted. Try a different name. #{err}") - msg = "Access to S3 bucket #{bucket_name} restricted. Try a different name. #{err}" - raise err, msg, err.backtrace - rescue => err - logger.error("Error #{action} #{object} from S3. #{err}") - msg = "Error #{action} #{object} from S3. #{err}" - raise err, msg, err.backtrace - end -end diff --git a/lib/gems/pending/util/object_storage/miq_swift_storage.rb b/lib/gems/pending/util/object_storage/miq_swift_storage.rb deleted file mode 100644 index 7de63e117..000000000 --- a/lib/gems/pending/util/object_storage/miq_swift_storage.rb +++ /dev/null @@ -1,184 +0,0 @@ -require 'util/miq_object_storage' - -class MiqSwiftStorage < MiqObjectStorage - attr_reader :container_name - - def self.uri_scheme - "swift".freeze - end - - def self.new_with_opts(opts) - new(opts.slice(:uri, :username, :password)) - end - - def initialize(settings) - super(settings) - @bucket_name = URI(@settings[:uri]).host - - raise "username and password are required values!" if @settings[:username].nil? || @settings[:password].nil? - _scheme, _userinfo, @host, @port, _registry, path, _opaque, query, _fragment = URI.split(URI::DEFAULT_PARSER.escape(@settings[:uri])) - query_params(query) if query - @swift = nil - @username = @settings[:username] - @password = @settings[:password] - - # Omit leading slash (if it exists), and grab the rest of the characters - # before the next file separator - @container_name = path.gsub(/^\/?([^\/]+).*/, '\1') - end - - def uri_to_object_path(remote_file) - # Strip off the leading "swift://" and the container name from the URI" - # Also remove the leading delimiter. - object_file_with_bucket = URI.split(URI::DEFAULT_PARSER.escape(remote_file))[5] - object_file_with_bucket.split(File::Separator)[2..-1].join(File::Separator) - end - - def upload_single(dest_uri) - # - # Get the remote path, and parse out the bucket name. - # - object_file = uri_to_object_path(dest_uri) - # - # write dump file to swift - # - logger.debug("Writing [#{source_input}] to => Bucket [#{container_name}] using object file name [#{object_file}]") - - with_standard_swift_error_handling("uploading") do - swift_file = container.files.new(:key => object_file) - params = { - :expects => [201, 202], - :headers => {}, - :request_block => -> { read_single_chunk }, - :idempotent => false, - :method => "PUT", - :path => "#{Fog::OpenStack.escape(swift_file.directory.key)}/#{Fog::OpenStack.escape(swift_file.key)}" - } - # - # Because of how `Fog::OpenStack` (and probably `Fog::Core`) is designed, - # it has hidden the functionality to provide a block for streaming - # uploads that is available out of the box with Excon. - # - # we use .send here because #request is private - # - # we can't use #put_object (public) directly because it doesn't allow a - # 202 response code, which is what swift responds with when we pass it - # the :request_block (This allows us to stream the response in chunks) - # - swift_file.service.send(:request, params) - - clear_split_vars - end - end - - def download_single(source, destination) - object_file = uri_to_object_path(source) - logger.debug("Downloading [#{source}] from Container [#{container_name}] to local file [#{destination}]") - - with_standard_swift_error_handling("downloading") do - container_key = container.key # also makes sure 'fog/openstack' is loaded - params = { - :expects => [200, 206], - :headers => {}, - :response_block => write_chunk_proc(destination), - :method => "GET", - :path => "#{Fog::OpenStack.escape(container_key)}/#{Fog::OpenStack.escape(object_file)}" - } - # Range is indexed starting at zero - params[:headers]['Range'] = "bytes=0-#{byte_count - 1}" if byte_count - swift.send(:request, params) - end - end - - def mkdir(_dir) - container - end - - # - # Some calls to Fog::Storage::OpenStack::Directories#get will - # return 'nil', and not return an error. This would cause errors down the - # line in '#upload' or '#download'. - # - # Instead of investigating further, we created a new method that is in charge of - # OpenStack container creation, '#create_container', and that is called from '#container' - # if 'nil' is returned from 'swift.directories.get(container_name)', or in the rescue case - # for 'NotFound' to cover that scenario as well - # - - def container(create_if_missing = true) - @container ||= begin - container = swift.directories.get(container_name) - logger.debug("Swift container [#{container}] found") if container - raise Fog::Storage::OpenStack::NotFound unless container - container - rescue Fog::Storage::OpenStack::NotFound - if create_if_missing - logger.debug("Swift container #{container_name} does not exist. Creating.") - create_container - else - msg = "Swift container #{container_name} does not exist. #{err}" - logger.error(msg) - raise err, msg, err.backtrace - end - rescue => err - msg = "Error getting Swift container #{container_name}. #{err}" - logger.error(msg) - raise err, msg, err.backtrace - end - end - - private - - def auth_url - URI::Generic.build( - :scheme => @security_protocol == 'non-ssl' ? "http" : "https", - :host => @host, - :port => @port.to_i, - :path => "/#{@api_version}#{@api_version == "v3" ? "/auth" : ".0"}/tokens" - ).to_s - end - - def swift - return @swift if @swift - require 'fog/openstack' - - connection_params = { - :openstack_auth_url => auth_url, - :openstack_username => @username, - :openstack_api_key => @password, - :openstack_project_domain_id => @domain_id, - :openstack_user_domain_id => @domain_id, - :openstack_region => @region, - :connection_options => { :debug_request => true } - } - - @swift = Fog::Storage::OpenStack.new(connection_params) - end - - def create_container - container = swift.directories.create(:key => container_name) - logger.debug("Swift container [#{container_name}] created") - container - rescue => err - msg = "Error creating Swift container #{container_name}. #{err}" - logger.error(msg) - raise err, msg, err.backtrace - end - - def query_params(query_string) - parts = URI.decode_www_form(query_string).to_h - @region, @api_version, @domain_id, @security_protocol = parts.values_at("region", "api_version", "domain_id", "security_protocol") - end - - def with_standard_swift_error_handling(action) - yield - rescue Excon::Errors::Unauthorized => err - msg = "Access to Swift container #{@container_name} failed due to a bad username or password. #{err}" - logger.error(msg) - raise err, msg, err.backtrace - rescue => err - msg = "Error #{action} #{source_input} to Swift container #{@container_name}. #{err}" - logger.error(msg) - raise err, msg, err.backtrace - end -end diff --git a/spec/util/miq_file_storage_spec.rb b/spec/util/miq_file_storage_spec.rb deleted file mode 100644 index 53050f3a9..000000000 --- a/spec/util/miq_file_storage_spec.rb +++ /dev/null @@ -1,435 +0,0 @@ -require "util/mount/miq_generic_mount_session" -require "util/miq_object_storage" - -describe MiqFileStorage do - def opts_for_nfs - opts[:uri] = "nfs://example.com/share/path/to/file.txt" - end - - def opts_for_smb - opts[:uri] = "smb://example.com/share/path/to/file.txt" - opts[:username] = "user" - opts[:password] = "pass" - end - - def opts_for_glusterfs - opts[:uri] = "glusterfs://example.com/share/path/to/file.txt" - end - - def opts_for_ftp - opts[:uri] = "ftp://example.com/share/path/to/file.txt" - end - - def opts_for_swift_without_params - opts[:uri] = "swift://example.com/share/path/to/file.txt" - opts[:username] = "user" - opts[:password] = "pass" - end - - def opts_for_swift_with_params - opts[:uri] = "swift://example.com/share/path/to/file.txt?region=foo" - opts[:username] = "user" - opts[:password] = "pass" - end - - def opts_for_fakefs - opts[:uri] = "foo://example.com/share/path/to/file.txt" - end - - describe ".with_interface_class" do - let(:opts) { {} } - - shared_examples ".with_interface_class implementation" do |class_name| - let(:klass) { Object.const_get(class_name) } - - it "instanciates as #{class_name}" do - interface_instance = described_class.with_interface_class(opts) - expect(interface_instance.class).to eq(klass) - end - - it "with a block, passes the instance, and returns the result" do - instance_double = double(class_name.to_s) - interface_block = ->(instance) { instance.add } - - expect(klass).to receive(:new).and_return(instance_double) - expect(instance_double).to receive(:add).and_return(:foo) - - expect(described_class.with_interface_class(opts, &interface_block)).to eq(:foo) - end - end - - context "with a nil uri" do - it "returns nil" do - expect(described_class.with_interface_class(opts)).to eq(nil) - end - end - - context "with an nfs:// uri" do - before { opts_for_nfs } - - include_examples ".with_interface_class implementation", "MiqNfsSession" - end - - context "with an smb:// uri" do - before { opts_for_smb } - - include_examples ".with_interface_class implementation", "MiqSmbSession" - end - - context "with an glusterfs:// uri" do - before { opts_for_glusterfs } - - include_examples ".with_interface_class implementation", "MiqGlusterfsSession" - end - - context "with an ftp:// uri" do - before { opts_for_ftp } - - include_examples ".with_interface_class implementation", "MiqFtpStorage" - end - - context "with an swift:// uri" do - before { opts_for_swift_with_params } - - include_examples ".with_interface_class implementation", "MiqSwiftStorage" - end - - context "with an swift:// uri and no query params" do - before { opts_for_swift_without_params } - - include_examples ".with_interface_class implementation", "MiqSwiftStorage" - end - - context "with an unknown uri scheme" do - before { opts_for_fakefs } - - it "raises an MiqFileStorage::InvalidSchemeError" do - valid_schemes = MiqFileStorage.storage_interface_classes.keys - error_class = MiqFileStorage::InvalidSchemeError - error_message = "foo is not a valid MiqFileStorage uri scheme. Accepted schemes are #{valid_schemes}" - - expect { described_class.with_interface_class(opts) }.to raise_error(error_class).with_message(error_message) - end - end - end - - ##### Interface Methods ##### - - describe MiqFileStorage::Interface do - shared_examples "an interface method" do |method_str, *args| - subject { method_str[0] == "#" ? described_class.new : described_class } - let(:method) { method_str[1..-1] } - - it "raises NotImplementedError" do - expected_error_message = "MiqFileStorage::Interface#{method_str} is not defined" - expect { subject.send(method, *args) }.to raise_error(NotImplementedError, expected_error_message) - end - end - - shared_examples "upload functionality" do |method| - let(:local_io) { IO.pipe.first } - let(:remote_file_path) { "baz/bar/foo" } - let(:byte_count) { 1234 } - let(:args) { [local_io, remote_file_path] } - - before do - subject.instance_variable_set(:@position, 0) - expect(subject).to receive(:initialize_upload_vars).with(*args).and_call_original - expect(subject).to receive(:handle_io_block).with(no_args) - expect(subject).to receive(:mkdir).with("baz/bar") - end - - it "resets all vars" do - subject.instance_variable_set(:@position, 10) - subject.instance_variable_set(:@byte_count, 10) - allow(subject).to receive(:upload_single) - allow(subject).to receive(:upload_splits) - - subject.send(method, *args) - - expect(subject.instance_variable_get(:@position)).to be nil - expect(subject.byte_count).to be nil - expect(subject.remote_file_path).to be nil - expect(subject.source_input).to be nil - expect(subject.input_writer).to be nil - end - - context "without a byte_count" do - it "calls #upload_single" do - expect(subject).to receive(:upload_single).with(remote_file_path).once - expect(subject).to receive(:upload_splits).never - subject.send(method, *args) - end - end - - context "with a byte_count" do - let(:args) { [local_io, remote_file_path, byte_count] } - - it "calls #upload_splits" do - expect(subject).to receive(:upload_splits).once - expect(subject).to receive(:upload_single).never - subject.send(method, *args) - end - end - end - - describe "#add" do - include_examples "upload functionality", :add - end - - describe "#upload" do - include_examples "upload functionality", :upload - end - - describe "#mkdir" do - it_behaves_like "an interface method", "#mkdir", "foo/bar/baz" - end - - describe "#upload_single" do - it_behaves_like "an interface method", "#upload_single", "path/to/file" - end - - describe "#download_single" do - it_behaves_like "an interface method", "#download_single", "nfs://1.2.3.4/foo", "foo" - end - - describe ".new_with_opts" do - it_behaves_like "an interface method", ".new_with_opts", {} - end - - describe ".uri_scheme" do - it "returns nil by default" do - expect(described_class.uri_scheme).to eq(nil) - end - end - - describe "#upload_splits" do - let(:file_name) { "path/to/file" } - - it "uploads multiple files of the byte count size" do - subject.instance_variable_set(:@position, 0) - subject.instance_variable_set(:@byte_count, 10) - subject.instance_variable_set(:@remote_file_path, file_name) - - source_input_stub = double('@source_input') - allow(subject).to receive(:source_input).and_return(source_input_stub) - allow(source_input_stub).to receive(:eof?).and_return(false, false, true) - - expect(subject).to receive(:upload_single).with("#{file_name}.00001") - expect(subject).to receive(:upload_single).with("#{file_name}.00002") - - subject.send(:upload_splits) - end - end - - describe "#initialize_upload_vars (private)" do - let(:local_io) { File.open(local_io_str) } - let(:local_io_str) { Tempfile.new.path } - let(:remote_path) { "/path/to/remote_file" } - let(:byte_count_int) { 1024 } - let(:byte_count_str) { "5M" } - let(:upload_args) { [] } - let(:pty_master) { double("pty_master") } - let(:pty_slave) { double("pty_slave") } - - before do - subject.send(:initialize_upload_vars, *upload_args) - end - after { FileUtils.rm_rf local_io_str } - - context "with byte_count passed" do - let(:upload_args) { [remote_path, byte_count_int] } - - it "assigns @byte_count to the parse value" do - expect(subject.byte_count).to eq(1024) - end - - it "assigns @remote_file_path" do - expect(subject.remote_file_path).to eq("/path/to/remote_file") - end - - it "assigns @source_input nil (set in #handle_io_block)" do - expect(subject.source_input).to eq(nil) - end - - it "assigns @input_writer nil (set in #handle_io_block)" do - expect(subject.input_writer).to eq(nil) - end - - context "with local_io as an IO object passed" do - let(:upload_args) { [local_io, remote_path, byte_count_str] } - - it "assigns @byte_count to the parse value" do - expect(subject.byte_count).to eq(5.megabytes) - end - - it "assigns @source_input to the passed value" do - expect(subject.source_input).to eq(local_io) - end - - it "@input_writer is nil" do - expect(subject.input_writer).to eq(nil) - end - end - - context "with local_io passed" do - let(:upload_args) { [local_io_str, remote_path, byte_count_str] } - - it "assigns @byte_count to the parse value" do - expect(subject.byte_count).to eq(5.megabytes) - end - - it "assigns @source_input to the passed value" do - expect(File.identical?(subject.source_input, local_io_str)).to be true - end - - it "@input_writer is nil" do - expect(subject.input_writer).to eq(nil) - end - end - end - - context "without byte_count passed" do - let(:upload_args) { [remote_path] } - - it "@byte_count is nil" do - expect(subject.byte_count).to eq(nil) - end - - it "assigns @remote_file_path" do - expect(subject.remote_file_path).to eq("/path/to/remote_file") - end - - it "assigns @source_input nil (set in #handle_io_block)" do - expect(subject.source_input).to eq(nil) - end - - it "assigns @input_writer nil (set in #handle_io_block)" do - expect(subject.input_writer).to eq(nil) - end - - context "with local_io passed" do - let(:upload_args) { [local_io, remote_path] } - - it "assigns @byte_count to the parse value" do - expect(subject.byte_count).to eq(nil) - end - - it "assigns @source_input to the passed value" do - expect(subject.source_input).to eq(local_io) - end - - it "@input_writer is nil" do - expect(subject.input_writer).to eq(nil) - end - end - - context "with local_io passed" do - let(:upload_args) { [local_io_str, remote_path] } - - it "assigns @byte_count to the parse value" do - expect(subject.byte_count).to eq(nil) - end - - it "assigns @source_input to the passed value" do - expect(File.identical?(subject.source_input, local_io_str)).to be true - end - - it "@input_writer is nil" do - expect(subject.input_writer).to eq(nil) - end - end - end - end - - describe "#parse_byte_value (private)" do - it "returns 2 for '2'" do - expect(subject.send(:parse_byte_value, "2")).to eq(2) - end - - it "returns 2048 for '2k'" do - expect(subject.send(:parse_byte_value, "2k")).to eq(2048) - end - - it "returns 1536 for '1.5K'" do - expect(subject.send(:parse_byte_value, "1.5K")).to eq(1536) - end - - it "returns 3145728 for '3M'" do - expect(subject.send(:parse_byte_value, "3M")).to eq(3.megabytes) - end - - it "returns 1073741824 for '1g'" do - expect(subject.send(:parse_byte_value, "1g")).to eq(1.gigabyte) - end - - it "returns nil for nil" do - expect(subject.send(:parse_byte_value, nil)).to eq(nil) - end - - it "returns 100 for 100 (integer)" do - expect(subject.send(:parse_byte_value, 100)).to eq(100) - end - end - - describe "#handle_io_block" do - let(:input_writer) { Tempfile.new } - let(:source_input) { Tempfile.new } - - after do - input_writer.unlink - source_input.unlink - end - - context "with a block" do - let(:block) { ->(_input_writer) { sleep 0.1 } } - - before do - expect(File).to receive(:mkfifo) - expect(File).to receive(:open).and_return(source_input, input_writer) - end - - it "creates a thread for handling the input IO" do - thread_count = Thread.list.count - thread = subject.send(:handle_io_block, &block) - expect(Thread.list.count).to eq(thread_count + 1) - thread.join - end - - it "closes input_writer" do - expect(input_writer.closed?).to eq(false) - thread = subject.send(:handle_io_block, &block) - thread.join - expect(input_writer.closed?).to eq(true) - end - end - - context "without a block" do - it "doesn't create a new thread for IO generation" do - thread_count = Thread.list.count - nil_result = subject.send(:handle_io_block) - - expect(nil_result).to be(nil) - expect(Thread.list.count).to eq(thread_count) - end - end - - context "with a block that causes an error" do - let(:err_block) { ->(_input_writer) { raise "err-mah-gerd" } } - - before do - skip "currently fails consistenly on Travis" - expect(File).to receive(:mkfifo) - expect(File).to receive(:open).and_return(source_input, input_writer) - end - - it "does not hang the process and closes the writer" do - expect(input_writer.closed?).to eq(false) - thread = subject.send(:handle_io_block, &err_block) - expect { thread.join }.to raise_error StandardError - expect(input_writer.closed?).to eq(true) - end - end - end - end -end diff --git a/spec/util/miq_ftp_lib_spec.rb b/spec/util/miq_ftp_lib_spec.rb deleted file mode 100644 index 21792c5d5..000000000 --- a/spec/util/miq_ftp_lib_spec.rb +++ /dev/null @@ -1,193 +0,0 @@ -require 'util/miq_ftp_lib' -require 'logger' # probably loaded elsewhere, but for the below classes - -class FTPKlass - include MiqFtpLib - - attr_accessor :uri - - def self.instance_logger - Logger.new(File::NULL) # null logger (for testing) - end - - private - - def _log - self.class.instance_logger - end -end - -class OtherFTPKlass - include MiqFtpLib - - attr_accessor :uri - - def _log - private_log_method - end - - private - - def private_log_method - Logger.new(File::NULL) # null logger (for testing) - end - - def login_credentials - %w(ftpuser ftppass) - end -end - -shared_examples "connecting" do |valid_cred_hash| - let(:cred_hash) { valid_cred_hash } - - before { subject.uri = "ftp://localhost" } - - it "logs in with valid credentials" do - expect { subject.connect(cred_hash) }.not_to raise_error - end - - it "sets the connection to passive" do - subject.connect(cred_hash) - expect(subject.ftp.passive).to eq(true) - end - - context "with an invalid ftp credentials" do - let(:cred_hash) { { :username => "invalid", :password => "alsoinvalid" } } - - it "raises a Net::FTPPermError" do - expect { subject.connect(cred_hash) }.to raise_error(Net::FTPPermError) - end - end -end - -shared_examples "with a connection" do |valid_cred_hash| - let(:cred_hash) { valid_cred_hash } - let(:error_msg) { "no block given" } - - before do - subject.uri = "ftp://localhost" - allow(subject).to receive(:_).with(error_msg).and_return(error_msg) - end - - def with_connection(&block) - subject.send(:with_connection, cred_hash, &block) - end - - def get_socket(ftp) - ftp.instance_variable_get(:@sock).instance_variable_get(:@io) - end - - it "passes the ftp object to the block" do - with_connection do |ftp| - expect(ftp).to be_a(Net::FTP) - expect(subject.ftp).to be(ftp) - end - end - - it "closes the ftp connection after the block is finished" do - ftp_instance = subject.connect(cred_hash) - # stub further calls to `#connect` - expect(subject).to receive(:connect).and_return(ftp_instance) - - with_connection { |ftp| } - expect(subject.ftp).to eq(nil) - expect(ftp_instance.closed?).to eq(true) - end - - it "raises an error if no block is given" do - expect { with_connection }.to raise_error(RuntimeError, error_msg) - end -end - -describe MiqFtpLib do - subject { FTPKlass.new } - - describe "when included" do - it "has a `ftp` accessor" do - ftp_instance = Net::FTP.new - subject.ftp = ftp_instance - - expect(subject.ftp).to eq ftp_instance - end - end - - describe "#connect", :with_ftp_server do - context "with credentials hash" do - subject { FTPKlass.new } - - include_examples "connecting", :username => "ftpuser", :password => "ftppass" - end - - context "with login_credentials method" do - subject { OtherFTPKlass.new } - - include_examples "connecting" - end - end - - describe "#with_connection", :with_ftp_server do - context "with credentials hash" do - subject { FTPKlass.new } - - include_examples "with a connection", :username => "ftpuser", :password => "ftppass" - end - - context "with login_credentials method" do - subject { OtherFTPKlass.new } - - include_examples "with a connection" - end - end - - describe "#file_exists?", :with_ftp_server do - let(:existing_file) { File.basename(existing_ftp_file) } - - subject { FTPKlass.new.tap { |ftp| ftp.uri = "ftp://localhost" } } - before { subject.connect(valid_ftp_creds) } - - it "returns true if the file exists" do - expect(subject.file_exists?(existing_file)).to eq(true) - end - - it "returns false if the file does not exist" do - expect(subject.file_exists?("#{existing_file}.fake")).to eq(false) - end - end - - # Note: Don't use `file_exists?` to try and test the directory existance. - # Most FTP implementations will send the results of `nlst` as the contents of - # a directory if a directory is given. - # - # In our current implementation, this will return a empty list if the - # directory is empty, thus causing the check to fail. Testing against the - # `ftp.nlst(parent_dir)` will make sure the directory in question is included - # in it's parent. - describe "#create_directory_structure", :with_ftp_server do - subject { OtherFTPKlass.new.tap { |ftp| ftp.uri = "ftp://localhost" } } - before { subject.connect(valid_ftp_creds) } - - it "creates a new nested directory" do - new_dir = "foo/bar/baz" - parent_dir = File.dirname(new_dir) - - expect(subject.ftp.nlst(parent_dir).include?("baz")).to eq(false) - subject.send(:create_directory_structure, new_dir) - expect(subject.ftp.nlst(parent_dir).include?("baz")).to eq(true) - end - - context "to an existing directory" do - it "creates the nested directory without messing with the existing" do - existing_dir = existing_ftp_dir - new_dir = File.join(existing_ftp_dir, "foo/bar/baz") - parent_dir = File.dirname(new_dir) - - expect(subject.ftp.nlst.include?(existing_dir)).to eq(true) - expect(subject.ftp.nlst(parent_dir).include?("baz")).to eq(false) - - subject.send(:create_directory_structure, new_dir) - expect(subject.ftp.nlst.include?(existing_dir)).to eq(true) - expect(subject.ftp.nlst(parent_dir).include?("baz")).to eq(true) - end - end - end -end diff --git a/spec/util/miq_object_storage_spec.rb b/spec/util/miq_object_storage_spec.rb deleted file mode 100644 index 901390549..000000000 --- a/spec/util/miq_object_storage_spec.rb +++ /dev/null @@ -1,120 +0,0 @@ -require "fileutils" -require "util/mount/miq_generic_mount_session" -require "util/miq_object_storage" - -class MockLocalFileStorage < MiqObjectStorage - def initialize(source_path = nil, byte_count = 2.megabytes) - @byte_count = byte_count - @source_input = File.open(source_path, "rb") if source_path - @root_dir = Dir.tmpdir - end - - def mkdir(dir) - FileUtils.mkdir_p(File.join(@root_dir, dir)) - end -end - -describe MiqObjectStorage do - describe "#write_single_split_file_for (private)" do - include_context "generated tmp files" - - subject { MockLocalFileStorage.new source_path } - let(:dest_path) { Dir::Tmpname.create("") { |name| name } } - - it "copies file to splits" do - expected_splitfiles = (1..5).map do |suffix| - "#{dest_path}.0000#{suffix}" - end - - expected_splitfiles.each do |file| - subject.send(:write_single_split_file_for, File.open(file, "wb")) - end - - expected_splitfiles.each do |filename| - expect(File.exist?(filename)).to be true - expect(Pathname.new(filename).lstat.size).to eq(2.megabytes) - end - end - - context "with slightly a slightly smaller input file than 10MB" do - let(:tmpfile_size) { 10.megabytes - 1.kilobyte } - subject { MockLocalFileStorage.new source_path, 1.megabyte } - - it "properly chunks the file" do - expected_splitfiles = (1..10).map do |suffix| - "#{dest_path}.%05d" % {:suffix => suffix} - end - - expected_splitfiles.each do |file| - subject.send(:write_single_split_file_for, File.open(file, "wb")) - end - - expected_splitfiles[0, 9].each do |filename| - expect(File.exist?(filename)).to be true - expect(File.size(filename)).to eq(1.megabytes) - end - - last_split = expected_splitfiles.last - expect(File.exist?(last_split)).to be true - expect(File.size(last_split)).to eq(1.megabyte - 1.kilobyte) - end - end - - context "non-split files (byte_count == nil)" do - subject { MockLocalFileStorage.new source_path, byte_count } - let(:byte_count) { nil } - - it "streams the whole file over" do - subject.send(:write_single_split_file_for, File.open(dest_path, "wb")) - expect(File.exist?(dest_path)).to be true - expect(Pathname.new(dest_path).lstat.size).to eq(tmpfile_size) - end - end - end - - describe "#read_single_chunk (private)" do - include_context "generated tmp files" - - subject { MockLocalFileStorage.new source_path } - let(:dest_path) { Dir::Tmpname.create("") { |name| name } } - let(:chunksize) { MockLocalFileStorage::DEFAULT_CHUNKSIZE } - - it "reads 16384 by default" do - chunk_of_data = subject.send(:read_single_chunk) - expect(chunk_of_data).to eq("0" * chunksize) - end - - it "reads the amount of data equal to chunksize when that is passed" do - chunk_of_data = subject.send(:read_single_chunk, 1.kilobyte) - expect(chunk_of_data).to eq("0" * 1.kilobyte) - end - - context "near the end of the split file" do - let(:data_left) { 123 } - let(:penultimate_chunkize) { chunksize - data_left } - - before do - # read an odd amount of data - read_times = 2.megabytes / chunksize - (read_times - 1).times { subject.send(:read_single_chunk) } - subject.send(:read_single_chunk, penultimate_chunkize) - end - - it "reads only what is necessary to finish the split file" do - chunk_of_data = subject.send(:read_single_chunk) - expect(chunk_of_data).to eq("0" * data_left) - end - - it "stops reading until `#clear_split_vars` is called" do - expect(subject.send(:read_single_chunk)).to eq("0" * data_left) - expect(subject.send(:read_single_chunk)).to eq("") - expect(subject.send(:read_single_chunk)).to eq("") - expect(subject.send(:read_single_chunk)).to eq("") - - subject.send(:clear_split_vars) - - expect(subject.send(:read_single_chunk)).to eq("0" * chunksize) - end - end - end -end diff --git a/spec/util/object_storage/miq_ftp_storage_spec.rb b/spec/util/object_storage/miq_ftp_storage_spec.rb deleted file mode 100644 index 09d3e2e82..000000000 --- a/spec/util/object_storage/miq_ftp_storage_spec.rb +++ /dev/null @@ -1,140 +0,0 @@ -require 'util/object_storage/miq_ftp_storage.rb' - -describe MiqFtpStorage, :with_ftp_server do - subject { described_class.new(ftp_creds.merge(:uri => "ftp://localhost")) } - let(:ftp_creds) { { :username => "ftpuser", :password => "ftppass" } } - - describe "#add" do - include_context "generated tmp files" - - shared_examples "adding files" do |dest_path| - let(:dest_path) { dest_path } - - it "copies single files" do - expect(subject.add(source_path.to_s, dest_path.to_s)).to eq(dest_path.to_s) - expect(dest_path).to exist_on_ftp_server - expect(dest_path).to have_size_on_ftp_server_of(10.megabytes) - end - - it "copies file to splits" do - expected_splitfiles = (1..5).map do |suffix| - "#{dest_path}.0000#{suffix}" - end - - File.open(source_path) do |f| # with an IO object this time - subject.add(f, dest_path.to_s, "2M") - end - - expected_splitfiles.each do |filename| - expect(filename).to exist_on_ftp_server - expect(filename).to have_size_on_ftp_server_of(2.megabytes) - end - end - - it "can take input from a command" do - expected_splitfiles = (1..5).map do |suffix| - "#{dest_path}.0000#{suffix}" - end - - subject.add(dest_path.to_s, "2M") do |input_writer| - `#{Gem.ruby} -e "File.write('#{input_writer}', '0' * #{tmpfile_size})"` - end - - expected_splitfiles.each do |filename| - expect(filename).to exist_on_ftp_server - expect(filename).to have_size_on_ftp_server_of(2.megabytes) - end - end - - context "with slightly a slightly smaller input file than 10MB" do - let(:tmpfile_size) { 10.megabytes - 1.kilobyte } - - it "properly chunks the file" do - expected_splitfiles = (1..10).map do |suffix| - "#{dest_path}.%05d" % {:suffix => suffix} - end - - # using pathnames this time - subject.add(source_path, dest_path.to_s, 1.megabyte) - - expected_splitfiles[0, 9].each do |filename| - expect(filename).to exist_on_ftp_server - expect(filename).to have_size_on_ftp_server_of(1.megabytes) - end - - last_split = expected_splitfiles.last - expect(last_split).to exist_on_ftp_server - expect(last_split).to have_size_on_ftp_server_of(1.megabyte - 1.kilobyte) - end - end - end - - context "using a 'relative path'" do - include_examples "adding files", "path/to/file" - end - - context "using a 'absolute path'" do - include_examples "adding files", "/path/to/my_file" - end - - context "using a uri" do - include_examples "adding files", "ftp://localhost/foo/bar/baz" - end - end - - describe "#download" do - let(:dest_path) { Dir::Tmpname.create("") { |name| name } } - let(:source_file) { existing_ftp_file(10.megabytes) } - let(:source_path) { File.basename(source_file.path) } - - after { File.delete(dest_path) if File.exist?(dest_path) } - - it "downloads the file" do - subject.download(dest_path, source_path) - - # Sanity check that what we are downloading is the size we expect - expect(source_path).to exist_on_ftp_server - expect(source_path).to have_size_on_ftp_server_of(10.megabytes) - - expect(File.exist?(dest_path)).to be true - expect(File.stat(dest_path).size).to eq(10.megabytes) - end - - it "can take input from a command" do - source_data = nil - subject.download(nil, source_path) do |input_writer| - source_data = `#{Gem.ruby} -e "print File.read('#{input_writer}')"` - end - - # Sanity check that what we are downloading is the size we expect - # (and we didn't actually download the file to disk) - expect(File.exist?(dest_path)).to be false - expect(source_path).to exist_on_ftp_server - expect(source_path).to have_size_on_ftp_server_of(10.megabytes) - - # Nothing written, just printed the streamed file in the above command - expect(source_data.size).to eq(10.megabytes) - end - end - - describe "#magic_number_for" do - let(:source_file) { existing_ftp_file(10.megabytes) } - let(:source_path) { File.basename(source_file.path) } - - it "returns 256 bytes by default" do - result = subject.magic_number_for(source_path) - - expect(result.size).to eq(256) - expect(result).to eq("0" * 256) - end - - describe "with a hash of accepted magics" do - it "returns key for the passed in magic number value" do - magics = { :zero => "000", :one => "1", :foo => "bar" } - result = subject.magic_number_for(source_path, :accepted => magics) - - expect(result).to eq(:zero) - end - end - end -end diff --git a/spec/util/object_storage/miq_s3_storage_spec.rb b/spec/util/object_storage/miq_s3_storage_spec.rb deleted file mode 100644 index 1d62c998a..000000000 --- a/spec/util/object_storage/miq_s3_storage_spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "util/object_storage/miq_s3_storage" - -describe MiqS3Storage do - before(:each) do - @uri = "s3://tmp/abc/def" - @session = described_class.new(:uri => @uri, :username => 'user', :password => 'pass', :region => 'region') - end - - it "#uri_to_object_path returns a new object path" do - result = @session.uri_to_object_key(@uri) - expect(result).to eq("abc/def") - end -end diff --git a/spec/util/object_storage/miq_swift_storage_spec.rb b/spec/util/object_storage/miq_swift_storage_spec.rb deleted file mode 100644 index 5d54edd3d..000000000 --- a/spec/util/object_storage/miq_swift_storage_spec.rb +++ /dev/null @@ -1,111 +0,0 @@ -require "util/object_storage/miq_swift_storage" - -describe MiqSwiftStorage do - let(:object_storage) { described_class.new(:uri => uri, :username => 'user', :password => 'pass') } - - describe "#initialize" do - context "using a uri with query parameters" do - let(:uri) { "swift://foo.com:5678/abc/def?region=region&api_version=v3&security_protocol=non-ssl" } - - it "sets the container_name" do - expect(object_storage.container_name).to eq("abc") - end - - it "#uri_to_object_path returns a new object path" do - result = object_storage.uri_to_object_path(uri) - expect(result).to eq("def") - end - end - - context "using a uri without query parameters" do - let(:uri) { "swift://foo.com/abc/def/my_file.tar.gz" } - - it "sets the container_name" do - expect(object_storage.container_name).to eq("abc") - end - - it "#uri_to_object_path returns a new object path" do - result = object_storage.uri_to_object_path(uri) - expect(result).to eq("def/my_file.tar.gz") - end - end - - context "using a uri with only a container_name" do - let(:uri) { "swift://foo.com/container_name" } - - it "sets the container_name" do - expect(object_storage.container_name).to eq("container_name") - end - end - - context "using a uri with only a container_name and params" do - let(:uri) { "swift://foo.com/container_name?region=region&api_version=v3&security_protocol=non-ssl" } - - it "sets the container_name" do - expect(object_storage.container_name).to eq("container_name") - end - - it "sets the region" do - expect(object_storage.instance_variable_get(:@region)).to eq("region") - end - - it "sets the api_version" do - expect(object_storage.instance_variable_get(:@api_version)).to eq("v3") - end - - it "sets the security_protocol" do - expect(object_storage.instance_variable_get(:@security_protocol)).to eq("non-ssl") - end - end - end - - describe "#auth_url (private)" do - context "with non-ssl security protocol" do - let(:uri) { "swift://foo.com:5678/abc/def?region=region&api_version=v3&security_protocol=non-ssl" } - - it "sets the scheme to http" do - expect(URI(object_storage.send(:auth_url)).scheme).to eq("http") - end - - it "sets the host to foo.com" do - expect(URI(object_storage.send(:auth_url)).host).to eq("foo.com") - end - - it "unsets the query string" do - expect(URI(object_storage.send(:auth_url)).query).to eq(nil) - end - end - - context "with ssl security protocol" do - let(:uri) { "swift://foo.com:5678/abc/def?region=region&api_version=v3&security_protocol=ssl" } - - it "sets the scheme to https" do - expect(URI(object_storage.send(:auth_url)).scheme).to eq("https") - end - - it "sets the host to foo.com" do - expect(URI(object_storage.send(:auth_url)).host).to eq("foo.com") - end - - it "unsets the query string" do - expect(URI(object_storage.send(:auth_url)).query).to eq(nil) - end - end - - context "with v3 api version" do - let(:uri) { "swift://foo.com:5678/abc/def?region=region&api_version=v3&security_protocol=ssl" } - - it "sets the path to a v3 path" do - expect(URI(object_storage.send(:auth_url)).path).to eq("/v3/auth/tokens") - end - end - - context "with v2 api version" do - let(:uri) { "swift://foo.com:5678/abc/def?region=region&api_version=v2&security_protocol=ssl" } - - it "sets the path to a v2 path" do - expect(URI(object_storage.send(:auth_url)).path).to eq("/v2.0/tokens") - end - end - end -end