stefan-kolb/nucleus

View on GitHub
lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Nucleus
  module Adapters
    module V1
      class CloudFoundryV2 < Stub
        module Data
          # @see Stub#deploy
          def deploy(application_name_or_id, file, file_compression_format)
            # could be made async, too
            # resources: [] says that no previous data shall be reused, see also:
            # http://apidocs.cloudfoundry.org/202/apps/uploads_the_bits_for_an_app.html

            app_guid = app_guid(application_name_or_id)
            # deploy by guid
            # deploy_response = put("/v2/apps/#{app_guid}/bits", body: { resources: [], application: file.read },
            #                       headers: { 'Content-Type' => 'multipart/form-data; '\
            #                       'boundary=nucleus-cloud-foundry-adapter-file-upload-boundary' })

            begin
              # convert all archives to .zip archives
              converted_file = ArchiveConverter.convert(file, file_compression_format, 'zip', true)
              unless converted_file.respond_to?(:path) && converted_file.respond_to?(:read)
                tmpfile = Tempfile.new(["nucleus-cf-deploy-upload-#{app_guid}", '.zip'])
                tmpfile.binmode
                tmpfile.write converted_file.read
                tmpfile.rewind
                converted_file = tmpfile
              end

              # TODO: this is only a temporary solution until excon supports multipart requests
              # See also: https://github.com/excon/excon/issues/353
              url = "#{@endpoint_url}/v2/apps/#{app_guid}/bits"
              request_body = { multipart: true, application: converted_file, async: false, resources: '[]' }
              begin
                RestClient::Request.execute(method: :put, url: url, payload: request_body,
                                            headers: headers, verify_ssl: @check_certificates)
              rescue RestClient::BadRequest => e
                raise Errors::AdapterRequestError, e.http_body
              end
            ensure
              if tmpfile
                tmpfile.close
                tmpfile.unlink # deletes this temporary file
              end
            end
          end

          # @see Stub#download
          def download(application_name_or_id, compression_format)
            app_guid = app_guid(application_name_or_id)
            # fail if there is no deployment
            raise Errors::SemanticAdapterRequestError, 'Application must be deployed before data can be downloaded' unless deployed?(app_guid)

            download_response = get("/v2/apps/#{app_guid}/download", follow_redirects: false, expects: [200, 302])
            if download_response.status == 200
              data = download_response.body
            else
              download_location = download_response.headers[:Location]
              # if IBM f*cked with the download URL, fix the address
              download_location = download_location.gsub(/objectstorage.service.networklayer.com/, 'objectstorage.softlayer.net')
              # omit_default_port: https://github.com/excon/excon/issues/475
              data = Excon.new(download_location, omit_default_port: true).get.body
            end

            # write data to tmpfile so that it can be converted
            downloaded_application_archive = Tempfile.new(["nucleus-cf-deployment-download-#{app_guid}", '.zip'])
            downloaded_application_archive.binmode
            downloaded_application_archive.write StringIO.new(data).read
            downloaded_application_archive.rewind

            # convert from current format (which is always a zip archive) to the destination format
            ArchiveConverter.convert(downloaded_application_archive, 'zip', compression_format, false)
          ensure
            if downloaded_application_archive
              downloaded_application_archive.close
              downloaded_application_archive.unlink
            end
          end

          # @see Stub#rebuild
          def rebuild(application_name_or_id)
            app_guid = app_guid(application_name_or_id)
            # fail if there is no deployment
            raise Errors::SemanticAdapterRequestError, 'Application must be deployed before it can be rebuild' unless deployed?(app_guid)

            # rebuild by name or id
            rebuild_response = post("/v2/apps/#{app_guid}/restage")
            to_nucleus_app(rebuild_response.body)
          end
        end
      end
    end
  end
end