From 014236dbdb071f3b8fa658d29068d69d7fe8cfd3 Mon Sep 17 00:00:00 2001 From: greggyd Date: Sat, 24 Mar 2018 14:23:10 +0000 Subject: [PATCH 1/5] initial go at using faraday to make requests --- etcd.gemspec | 1 + lib/etcd/client.rb | 78 ++++++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/etcd.gemspec b/etcd.gemspec index 3521403..cb38656 100644 --- a/etcd.gemspec +++ b/etcd.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 1.9' spec.add_dependency "mixlib-log" + spec.add_dependency "faraday" spec.add_development_dependency "uuid" spec.add_development_dependency "bundler" spec.add_development_dependency "rake" diff --git a/lib/etcd/client.rb b/lib/etcd/client.rb index 04a2960..e90b842 100644 --- a/lib/etcd/client.rb +++ b/lib/etcd/client.rb @@ -1,9 +1,8 @@ # Encoding: utf-8 require 'openssl' -require 'net/http' -require 'net/https' require 'json' +require 'faraday' require 'etcd/log' require 'etcd/stats' require 'etcd/keys' @@ -18,10 +17,6 @@ module Etcd class Client extend Forwardable - HTTP_REDIRECT = ->(r) { r.is_a? Net::HTTPRedirection } - HTTP_SUCCESS = ->(r) { r.is_a? Net::HTTPSuccess } - HTTP_CLIENT_ERROR = ->(r) { r.is_a? Net::HTTPClientError } - include Stats include Keys @@ -33,13 +28,13 @@ class Client :ca_file, :user_name, :password, - :ssl_cert + :ssl_cert, ) def_delegators :@config, :use_ssl, :verify_mode, :read_timeout def_delegators :@config, :user_name, :password - attr_reader :host, :port, :http, :config + attr_reader :host, :port, :http, :active_endpoint, :endpoints, :config ## # Creates an Etcd::Client object. It accepts a hash +opts+ as argument @@ -50,8 +45,14 @@ class Client # @opts [Fixnum] :read_timeout set HTTP read timeouts (default 60) # rubocop:disable CyclomaticComplexity def initialize(opts = {}) + raise ArgumentError.new('either set endpoints OR host/port options') if (opts[:host] or opts [:port]) and opts[:endpoints] + raise ArgumentError.new('when using endpoints instead of host/port options set protocol in endpoint instead of using use_ssl option(ie: "http://host:port" or https://host:port)') if not opts[:use_ssl].nil? and opts[:endpoints] @host = opts[:host] || '127.0.0.1' @port = opts[:port] || 4001 + proto = (opts.key?(:use_ssl) and opts[:use_ssl]) ? "https" : "http" + @endpoints = opts[:endpoints] || ["#{proto}://#{@host}:#{@port}"] + @active_endpoint = @endpoints.sample + Log.debug("initialised etcd client with endpoints: #{@endpoints}") @config = Config.new @config.read_timeout = opts[:read_timeout] || 60 @config.use_ssl = opts[:use_ssl] || false @@ -74,7 +75,20 @@ def version_prefix # Returns the etcd daemon version def version - api_execute('/version', :get).body + version_response = api_execute('/version', :get).body + begin + "etcd v" + JSON.parse(version_response)['etcdserver'] + rescue JSON::ParserError + version_response + end + end + + def members + JSON.parse(api_execute(version_prefix + '/members', :get).body.strip)['members'] + end + + def refresh_endpoints + @endpoints = members.collect{|member| member['clientURLs']}.flatten end # Get the current leader @@ -91,65 +105,63 @@ def leader # rubocop:disable MethodLength, CyclomaticComplexity def api_execute(path, method, options = {}) params = options[:params] + request_params = nil + request_body = nil case method - when :get - req = build_http_request(Net::HTTP::Get, path, params) - when :post - req = build_http_request(Net::HTTP::Post, path, nil, params) - when :put - req = build_http_request(Net::HTTP::Put, path, nil, params) - when :delete - req = build_http_request(Net::HTTP::Delete, path, params) + when :get, :delete + request_params = params + when :post, :put + request_body = params else fail "Unknown http action: #{method}" end - http = Net::HTTP.new(host, port) - http.read_timeout = options[:timeout] || read_timeout + http = Faraday.new(@active_endpoint, request: { + timeout: options[:timeout] || read_timeout + }) setup_https(http) - req.basic_auth(user_name, password) if [user_name, password].all? - Log.debug("Invoking: '#{req.class}' against '#{path}") - res = http.request(req) - Log.debug("Response code: #{res.code}") + http.basic_auth(user_name, password) if [user_name, password].all? + Log.debug("Invoking: '#{method}' against '#{path}") + http.params = request_params if not request_params.nil? + res = http.run_request(method, path, request_body, {}) + Log.debug("Response code: #{res.status}") Log.debug("Response body: #{res.body}") process_http_request(res) end def setup_https(http) - http.use_ssl = use_ssl - http.verify_mode = verify_mode + http.ssl.verify = verify_mode if config.ssl_cert Log.debug('Setting up ssl cert') - http.cert = config.ssl_cert + http.ssl.client_cert = config.ssl_cert end if config.ssl_key Log.debug('Setting up ssl key') - http.key = config.ssl_key + http.ssl.client_key = config.ssl_key end if config.ca_file Log.debug('Setting up ssl ca file to :' + config.ca_file) - http.ca_file = config.ca_file + http.ssl.ca_file = config.ca_file end end # need to have original request to process the response when it redirects def process_http_request(res) - case res - when HTTP_SUCCESS + case res.success? + when true Log.debug('Http success') res - when HTTP_CLIENT_ERROR + when false fail Error.from_http_response(res) else Log.debug('Http error') Log.debug(res.body) - res.error! end end # rubocop:enable MethodLength def build_http_request(klass, path, params = nil, body = nil) path += '?' + URI.encode_www_form(params) unless params.nil? - req = klass.new(path) + req = Faraday::Request.new('get') req.body = URI.encode_www_form(body) unless body.nil? Etcd::Log.debug("Built #{klass} path:'#{path}' body:'#{req.body}'") req From 3827a6a52a82323793c10dc46262242cd21b8263 Mon Sep 17 00:00:00 2001 From: greggyd Date: Sat, 24 Mar 2018 14:27:30 +0000 Subject: [PATCH 2/5] travis build from feature branch --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 611d9ee..acdf6e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,5 +10,5 @@ rvm: - 2.2.0 branches: only: - - master + - use_faraday script: "ETCD_BIN=./etcd-v2.0.0-rc.1-linux-amd64/etcd bundle exec rake spec" From 338e2318f69e21a003fb09ab718bccc2f894f890 Mon Sep 17 00:00:00 2001 From: greggyd Date: Sat, 24 Mar 2018 14:42:54 +0000 Subject: [PATCH 3/5] also run travis tests on newer versions of ruby --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index acdf6e7..b957b27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ rvm: - 1.9.3 - 2.1.0 - 2.2.0 + - 2.4.2 + - 2.5.0 branches: only: - use_faraday From 16920e163830907e683e9eae9df445327af31147 Mon Sep 17 00:00:00 2001 From: greggyd Date: Sat, 24 Mar 2018 14:48:05 +0000 Subject: [PATCH 4/5] travis only test on newest ruby versions --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b957b27..6b71860 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,9 @@ before_install: - bundle install rvm: - - 1.9.3 - - 2.1.0 - - 2.2.0 - - 2.4.2 + - 2.2.9 + - 2.3.6 + - 2.4.3 - 2.5.0 branches: only: From 206f599ca4d2feb8d61399af83b5d21fbbf17198 Mon Sep 17 00:00:00 2001 From: greggyd Date: Sat, 24 Mar 2018 14:55:36 +0000 Subject: [PATCH 5/5] travis point to master branch --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b71860..ea94c29 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,5 +11,5 @@ rvm: - 2.5.0 branches: only: - - use_faraday + - master script: "ETCD_BIN=./etcd-v2.0.0-rc.1-linux-amd64/etcd bundle exec rake spec"