bin/vidispine-notification-handler in vidispine-1.4.0 vs bin/vidispine-notification-handler in vidispine-1.5.0

- old
+ new

@@ -2,338 +2,42 @@ require 'rubygems' require 'logger' require 'optparse' require 'pp' -ARGV << '--uri' -ARGV << 'https://o6h5m0r0ih.execute-api.us-east-1.amazonaws.com/latest/vidispine/notification' -ARGV << '{changeSetId=[VX-460], userName=[admin], itemId=[VX-90], portal_mf201890=[3], sequenceNumber=[0]}' -puts 'Arguments:' -pp ARGV - - module Vidispine - class HTTPClient - - class HTTPAuthorizationError < RuntimeError; end - - attr_accessor :logger, :http, :http_host_address, :http_host_port, :base_uri, :default_base_path - attr_accessor :username, :password - - attr_accessor :default_request_headers, - :authorization_header_key, :authorization_header_value - - attr_accessor :log_request_body, :log_response_body, :log_pretty_print_body - - attr_accessor :request, :response, :use_exceptions - - DEFAULT_HTTP_HOST_ADDRESS = 'localhost' - DEFAULT_HTTP_HOST_PORT = 80 - - DEFAULT_USERNAME = '' - DEFAULT_PASSWORD = '' - DEFAULT_BASE_PATH = '/' - - DEFAULT_HEADER_CONTENT_TYPE = 'application/json; charset=utf-8' - DEFAULT_HEADER_ACCEPTS = 'application/json' - - def initialize(args = { }) - args = args.dup - - @use_exceptions = args.fetch(:use_exceptions, true) - - initialize_logger(args) - initialize_http(args) - - logger.debug { "#{self.class.name}::#{__method__} Arguments: #{args.inspect}" } - - @username = args[:username] || DEFAULT_USERNAME - @password = args[:password] || DEFAULT_PASSWORD - @authorization_header_value = args[:authorization_header_value] - - @base_uri = "http#{http.use_ssl? ? 's' : ''}://#{http.address}:#{http.port}" - @default_base_path = args[:default_base_path] || DEFAULT_BASE_PATH - - content_type = args[:content_type_header] ||= DEFAULT_HEADER_CONTENT_TYPE - accepts = args[:accepts_header] ||= args[:accept_header] || DEFAULT_HEADER_ACCEPTS - - @default_request_headers = { - 'Content-Type' => content_type, - 'Accept' => accepts, - } - - if !username.empty? && !password.empty? - @authorization_header_key ||= 'Authorization' #CaseSensitiveHeaderKey.new('Authorization') - @authorization_header_value ||= %(Basic #{["#{username}:#{password}"].pack('m').delete("\r\n")}) - @default_request_headers[authorization_header_key] = authorization_header_value - end - - @log_request_body = args.fetch(:log_request_body, true) - @log_response_body = args.fetch(:log_response_body, true) - @log_pretty_print_body = args.fetch(:log_pretty_print_body, true) - - @parse_response = args.fetch(:parse_response, true) - end - - def initialize_logger(args = { }) - @logger = args[:logger] ||= Logger.new(args[:log_to] || STDOUT) - log_level = args[:log_level] - if log_level - @logger.level = log_level - args[:logger] = @logger - end - @logger - end - - def initialize_http(args = { }) - @http_host_address = args[:http_host_address] ||= DEFAULT_HTTP_HOST_ADDRESS - @http_host_port = args[:http_host_port] ||= DEFAULT_HTTP_HOST_PORT - @http = Net::HTTP.new(http_host_address, http_host_port) - - use_ssl = args[:http_host_use_ssl] - if use_ssl - # @TODO Add SSL Support - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - http - end - - # Formats a HTTPRequest or HTTPResponse body for log output. - # @param [HTTPRequest|HTTPResponse] obj - # @return [String] - def format_body_for_log_output(obj) - if obj.content_type == 'application/json' - if @log_pretty_print_body - _body = obj.body - output = JSON.pretty_generate(JSON.parse(_body)) rescue _body - return output - else - return obj.body - end - elsif obj.content_type == 'application/xml' - return obj.body - else - return obj.body.inspect - end - end - - # @param [HTTPRequest] request - def send_request(request) - @response_parsed = nil - @request = request - logger.debug { %(REQUEST: #{request.method} http#{http.use_ssl? ? 's' : ''}://#{http.address}:#{http.port}#{request.path} HEADERS: #{request.to_hash.inspect} #{log_request_body and request.request_body_permitted? ? "\n-- BODY BEGIN --\n#{format_body_for_log_output(request)}\n-- BODY END --" : ''}) } - - @request_time_start = Time.now - @response = http.request(request) - @request_time_end = Time.now - logger.debug { %(RESPONSE: #{response.inspect} HEADERS: #{response.to_hash.inspect} #{log_response_body and response.respond_to?(:body) ? "\n-- BODY BEGIN --\n#{format_body_for_log_output(response)}\n-- BODY END--" : ''}\nTook: #{@request_time_end - @request_time_start} seconds) } - #logger.debug { "Parse Response? #{@parse_response}" } - - raise HTTPAuthorizationError if @use_exceptions && @response.code == '401' - - @parse_response ? response_parsed : response.body - end - - def response_parsed - @response_parsed ||= begin - response_body = response.respond_to?(:body) ? response.body : '' - logger.debug { "Parsing Response. #{response_body.inspect}" } - - case response.content_type - when 'application/json' - response_body.empty? ? response_body : JSON.parse(response_body) # rescue response - else - response_body - end - end - end - - # @param [String] path - # @param [Hash|String|Nil] query - # @return [URI] - def build_uri(path = '', query = nil) - _query = query.is_a?(Hash) ? query.map { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.respond_to?(:to_s) ? v.to_s : v)}" }.join('&') : query - _path = "#{path}#{_query and _query.respond_to?(:empty?) and !_query.empty? ? "?#{_query}" : ''}" - URI.parse(File.join(base_uri, _path)) - end - - if RUBY_VERSION.start_with? '1.8.' - def request_method_name_to_class_name(method_name) - method_name.to_s.capitalize - end - else - def request_method_name_to_class_name(method_name) - method_name.to_s.capitalize.to_sym - end - end - - # @param [Symbol] method_name (:get) - # @param [Hash] args - # @option args [Hash] :headers ({}) - # @option args [String] :path ('') - # @option args [Hash] :query ({}) - # @option args [Any] :body (nil) - # @param [Hash] options - # @option options [Hash] :default_request_headers (@default_request_headers) - def call_method(method_name = :get, args = { }, options = { }) - headers = args[:headers] || options[:headers] || { } - path = args[:path] || '' - query = args[:query] || { } - body = args[:body] - - # Allow the default request headers to be overridden - _default_request_headers = options.fetch(:default_request_headers, default_request_headers) - _default_request_headers ||= { } - _headers = _default_request_headers.merge(headers) - - @uri = build_uri(path, query) - klass_name = request_method_name_to_class_name(method_name) - klass = Net::HTTP.const_get(klass_name) - - request = klass.new(@uri.request_uri, _headers) - - if request.request_body_permitted? - _body = (body and !body.is_a?(String)) ? JSON.generate(body) : body - logger.debug { "Processing Body: '#{_body}'" } - request.body = _body if _body - end - - send_request(request) - end - - def delete(path, options = { }) - call_method(:delete, { :path => path }, options) - end - - def get(path, options = { }) - call_method(:get, { :path => path }, options) - end - - def head(path, options = { }) - call_method(:head, { :path => path }, options) - end - - def options(path, options = { }) - call_method(:options, { :path => path }, options) - end - - def put(path, body, options = { }) - call_method(:put, { :path => path, :body => body }, options) - end - - def post(path, body, options = { }) - call_method(:post, { :path => path, :body => body }, options) - end - - # HTTPClient - end - class NotificationHandler attr_accessor :logger def initialize(args = { }) initialize_logger(args) - initialize_http(args) end def initialize_logger(args = { }) @logger = args[:logger] ||= begin _logger = Logger.new(args[:log_to] || STDERR) _logger.level = args[:log_level] || Logger::DEBUG _logger end end - def initialize_http(args = { }) - uri_as_str = args[:uri] - - uri = URI(uri_as_str) - - args[:http_host_address] = uri.host - args[:http_host_port] = uri.port - args[:http_host_use_ssl] = uri.scheme == 'https' - args[:username] = uri.user - args[:password] = uri.password - args[:default_base_path] = uri.request_uri - - @http_client = HTTPClient.new(args) - end - - def forward_notification(notification) - @http_client.call_method(:post, :body => notification) - end - end end -LOGGING_LEVELS = { - :debug => Logger::DEBUG, - :info => Logger::INFO, - :warn => Logger::WARN, - :error => Logger::ERROR, - :fatal => Logger::FATAL -} -DEFAULT_HEADER_CONTENT_TYPE = 'application/json; charset=utf-8' - -def log_to_as_string - _log_to = arguments[:log_to] - case _log_to - when STDERR; 'STDERR' - when STDOUT; 'STDOUT' - else _log_to - end -end - - -default_arguments = { +args = { :log_to => "/tmp/#{File.basename($0)}.log", - :log_level => Logger::DEBUG, - :options_file_path => File.expand_path(File.basename($0, '.*'), '~/.options'), - :http_method => :post + :log_level => Logger::DEBUG } -@arguments = default_arguments.dup -def arguments; @arguments end -argument_parser = OptionParser.new -argument_parser.on('--uri URI', 'The address of the server to communicate with.') { |v| arguments[:uri] = v } +@handler = Vidispine::NotificationHandler.new(args) +def logger; @handler.logger end +logger.debug { "ARGUMENTS: #{ARGV.inspect}" } -argument_parser.on('--content-type VALUE', 'The value for the Content-Type header sent in each request.', "\tdefault: #{DEFAULT_HEADER_CONTENT_TYPE}") { |v| arguments[:content_type] = v } -argument_parser.on('--method METHOD', 'The HTTP method to use when submitting the notification.', "\tdefault: #{arguments[:http_method]}") { |v| arguments[:http_method] = v.to_sym } -argument_parser.on('--pretty-print', 'Will format the output to be more human readable.') { |v| arguments[:pretty_print] = v } - -argument_parser.on('--log-to FILENAME', 'Log file location.', "\tdefault: #{log_to_as_string}") { |v| arguments[:log_to] = v } -argument_parser.on('--log-level LEVEL', LOGGING_LEVELS.keys, "Logging level. Available Options: #{LOGGING_LEVELS.keys.join(', ')}", - "\tdefault: #{LOGGING_LEVELS.invert[arguments[:log_level]]}") { |v| arguments[:log_level] = LOGGING_LEVELS[v] } - -argument_parser.on('--[no-]options-file [FILENAME]', 'Path to a file which contains default command line arguments.', "\tdefault: #{arguments[:options_file_path]}" ) { |v| arguments[:options_file_path] = v} -argument_parser.on_tail('-h', '--help', 'Display this message.') { puts help; exit } - -arguments.clear -original_argv_args = ARGV.dup -argument_parser.parse!(ARGV) -remaining_argv_args = ARGV.dup -arguments_from_command_line = arguments.dup - -options_file_path = arguments_from_command_line[:options_file_path] || default_arguments[:options_file_path] - -arguments.clear -argument_parser.load(options_file_path) -arguments_from_options_file = arguments.dup - -arguments = default_arguments.merge(arguments_from_options_file).merge(arguments_from_command_line) - -pp arguments -# @handler = Vidispine::NotificationHandler.new(arguments) -# def logger; @handler.logger end -# logger.debug { "ARGUMENTS: #{remaining_argv_args.inspect}" } - - - -# @handler.forward_notification(remaining_argv_args) +# ARGV << '{changeSetId=[VX-460], userName=[admin], itemId=[VX-90], portal_mf201890=[3], sequenceNumber=[0]}' +# puts 'Arguments:' +# pp ARGV