fleet-api 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68e27564af5b67b5721f95aa609aedeb84f1fadd
4
- data.tar.gz: 40f0c7cec0121c38fd9a560bd6445b96977f7108
3
+ metadata.gz: 40cafdb1518899f8d9da9e7621e01bb0b77b2282
4
+ data.tar.gz: 29fdaa40bb4ff55aa9af252a2f75658d9b5d1c61
5
5
  SHA512:
6
- metadata.gz: 3c0a1bc9e12034e59186ee1abdc87a025475a027e038b564d3c8e1fb90c1873a0da79a1afb1534be69f301758261fbf53bf25fe81bbea8e2d5795b53caeb2752
7
- data.tar.gz: 69d67b8d08c127b5771e5727ebb593ea03d3f184df22924cee95c5b88a642819ccb37f0162d545dde689fdb2a4527c1446075a8b3b38c948885646d7f8c35649
6
+ metadata.gz: 892ebd1582a5b7a84e7460e08573962dd66cf0cd446b111403f2e4f80623ad812cf6756e84df60dc48a53060bfcdba06f3b9172010530b2cda1e32fec51c0df2
7
+ data.tar.gz: 6748da6745a7a3dac060f9fbd56797cd01a91d5849da9e149bdd382373c778bd5977d8c4287c2802801f390aeee17c12cc8fd971e02efea1cb4503b02cf114d1
data/.travis.yml CHANGED
@@ -2,5 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.5
6
- - 2.2.0
5
+ - 2.1.1
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ 1.0.0 - 2015-02-17
5
+ ------------------
6
+
7
+ ### Added
8
+ - Support for official Fleet API (no longer reading/writing directly from/to etcd)
9
+ - New get_unit_state and get_unit_file methods
10
+
11
+ ### Fixed
12
+ - Proper encoding of @ symbol when submitting unit templates
13
+
4
14
  0.9.0 - 2015-01-14
5
15
  ------------------
6
16
 
data/Gemfile.lock CHANGED
@@ -1,21 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fleet-api (0.8.0)
5
- faraday (= 0.8.9)
6
- faraday_middleware (= 0.9.0)
4
+ fleet-api (0.6.0)
5
+ excon (>= 0.27.4)
7
6
 
8
7
  GEM
9
8
  remote: http://rubygems.org/
10
9
  specs:
11
10
  diff-lcs (1.2.5)
12
11
  docile (1.1.5)
13
- faraday (0.8.9)
14
- multipart-post (~> 1.2.0)
15
- faraday_middleware (0.9.0)
16
- faraday (>= 0.7.4, < 0.9)
12
+ excon (0.41.0)
17
13
  multi_json (1.10.1)
18
- multipart-post (1.2.0)
19
14
  rake (10.3.2)
20
15
  rspec (3.0.0)
21
16
  rspec-core (~> 3.0.0)
data/README.md CHANGED
@@ -2,20 +2,12 @@ fleet-api
2
2
  =========
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/fleet-api.svg)](http://badge.fury.io/rb/fleet-api)
5
- [![Build Status](https://api.shippable.com/projects/540e7b283479c5ea8f9ebd66/badge?branchName=master)](https://www.shippable.com/projects/53f3a91a5491229d0207e4d9)
5
+ [![Build Status](https://api.shippable.com/projects/540e7b283479c5ea8f9ebd66/badge?branchName=master)](https://app.shippable.com/projects/540e7b283479c5ea8f9ebd66/builds/latest)
6
6
 
7
7
  Provides a Ruby wrapper around the CoreOS Fleet API.
8
8
 
9
9
  The client allows programmatic access to most of the *fleetctl* commands including the ability to load, start, stop, unload and destroy unit files.
10
10
 
11
- At this point, there is no official Fleet API (though one is [in the works](https://github.com/coreos/fleet/blob/master/Documentation/api-v1-alpha.md)) so this library mimcs the behavior of the *fleetctl* command line tool and simply writes data to the [etcd]() key-value-store. The Fleet daemon reads data out of specific keys in etcd and processes it as appropiate.
12
-
13
- As work on the actual Fleet API progresses, this library will be refactored to use the real API. An initial pass at implementing a client for the official Fleet API can be found on the [feature/official-api](https://github.com/CenturyLinkLabs/fleet-api/tree/feature/official-api) branch.
14
-
15
- An alternative implementation is available in the [cloudspace/ruby-fleetctl](https://github.com/cloudspace/ruby-fleetctl) gem. The *ruby-fleetctl* gem takes a different approach and uses SSH to interact directly with the *fleetctl* binary to send commands. Our approach of writing directly to etcd cuts out the *fleetctl* middleman but is in more danger of being broken by future releases since we're effectively using a "private API".
16
-
17
- The current version of the *fleet-api* gem is known to work with version 0.8.0 of Fleet.
18
-
19
11
  ### Installation
20
12
 
21
13
  Install the gem directly:
@@ -29,17 +21,16 @@ Alternatively, add this line to your application's Gemfile:
29
21
 
30
22
  ### Usage
31
23
 
32
- Configure the URL for the etcd API:
24
+ Configure the URL for the Fleet API:
33
25
 
34
26
  require 'fleet'
35
27
 
36
28
  Fleet.configure do |fleet|
37
- fleet.fleet_api_url = 'http://10.1.42.1:4001'
29
+ fleet.fleet_api_url = 'http://10.1.42.1:49153'
38
30
  end
39
31
 
40
- If you don't provide an explicit value for the `.fleet_api_url` attribute, it will default to using the value of the `FLEETCTL_ENDPOINT` environment variable.
32
+ If you don't provide an explicit value for the `.fleet_api_url` attribute, it will default to using the value of the `FLEETCTL_ENDPOINT` environment variable (if present) or the socket at `unix:///var/run/fleet.sock`.
41
33
 
42
- **Note: since this Fleet API is not yet available in the stable version of CoreOS, the URL value provided must be the endpoint for the etcd API.**
43
34
 
44
35
  #### Service Definitions
45
36
 
@@ -63,18 +54,18 @@ This unit file would be represented as the following Ruby hash.
63
54
  'ExecStart' => "/bin/bash -c \"while true; do sleep 1; done\""
64
55
  }
65
56
  }
66
-
67
- If you need mutiple values for a single statement (like multiple `ExecStart` instructions) you can use an array of strings:
68
57
 
69
- {
70
- 'Unit' => {
71
- 'Description' => 'Useless infinite loop'
72
- },
73
- 'Service' => {
74
- 'ExecStart' => ["/bin/bash -c \"while true; do sleep 1; done\"", "some other command"]
75
- }
76
- }
58
+ If you need mutiple values for a single statement (like multiple `ExecStart` instructions) you can use an array of strings:
77
59
 
60
+ {
61
+ 'Unit' => {
62
+ 'Description' => 'Useless infinite loop'
63
+ },
64
+ 'Service' => {
65
+ 'ExecStart' => ["/bin/bash -c \"while true; do sleep 1; done\"", "some other command"]
66
+ }
67
+ }
68
+
78
69
  #### Loading a Unit File
79
70
 
80
71
  Equivalent of `fleetctl load`:
@@ -121,16 +112,23 @@ Equivalent of `fleetctl destroy`:
121
112
  client = Fleet.new
122
113
  client.destroy('forever.service')
123
114
 
115
+ #### Listing Services
116
+
117
+ Equivalent of `fleetctl list-units`:
118
+
119
+ client = Fleet.new
120
+ client.list
121
+
124
122
  #### Retrieving Service Status
125
123
 
126
124
  Equivalent of `fleetctl status`:
127
125
 
128
126
  client = Fleet.new
129
- client.status('forever.service')
127
+ client.get_unit_state('forever.service')
130
128
 
131
- #### Listing Services
129
+ #### Retrieving a Unit File
132
130
 
133
- Equivalent of `fleetctl list-units`:
131
+ Retrieves contents and current state of a unit file:
134
132
 
135
133
  client = Fleet.new
136
- client.list
134
+ client.get_unit_file('foo.service')
data/fleet-api.gemspec CHANGED
@@ -15,8 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = %w(lib)
16
16
  gem.version = Fleet::VERSION
17
17
  gem.required_ruby_version = '>= 1.9.3'
18
- gem.add_dependency 'faraday', '= 0.8.9'
19
- gem.add_dependency 'faraday_middleware', '= 0.9.0'
18
+ gem.add_dependency 'excon', '>= 0.27.4'
20
19
  gem.add_development_dependency 'rake'
21
20
  gem.add_development_dependency 'rspec', '~> 3.0'
22
21
  gem.add_development_dependency 'simplecov', '~> 0.9.0'
@@ -5,8 +5,7 @@ module Fleet
5
5
  MACHINES_RESOURCE = 'machines'
6
6
 
7
7
  def list_machines
8
- opts = { consistent: true, recursive: true, sorted: true }
9
- get(machines_path, opts)
8
+ get(machines_path, nil)
10
9
  end
11
10
 
12
11
  private
@@ -4,14 +4,8 @@ module Fleet
4
4
 
5
5
  STATE_RESOURCE = 'state'
6
6
 
7
- def list_states
8
- opts = { consistent: true, recursive: true, sorted: false }
9
- get(state_path, opts)
10
- end
11
-
12
- def get_state(service_name)
13
- opts = { consistent: true, recursive: true, sorted: false }
14
- get(state_path(service_name), opts)
7
+ def list_states(options={})
8
+ get(state_path, options)
15
9
  end
16
10
 
17
11
  private
@@ -23,3 +17,4 @@ module Fleet
23
17
  end
24
18
  end
25
19
  end
20
+
@@ -2,29 +2,32 @@ module Fleet
2
2
  class Client
3
3
  module Unit
4
4
 
5
- UNIT_RESOURCE = 'unit'
5
+ UNITS_RESOURCE = 'units'
6
6
 
7
7
  def list_units()
8
- get(unit_path)
8
+ get(units_path)
9
9
  end
10
10
 
11
- def create_unit(unit_sha1, unit_def)
12
- opts = {
13
- querystring: { 'prevExist' => false },
14
- body: { value: unit_def.to_json }
15
- }
16
- put(unit_path(unit_sha1), opts)
11
+ def get_unit(name)
12
+ get(units_path(name))
17
13
  end
18
14
 
19
- def delete_unit(unit_sha1)
20
- opts = { dir: false, recursive: false }
21
- delete(unit_path(unit_sha1), opts)
15
+ alias_method :get_unit_file, :get_unit
16
+
17
+ def create_unit(name, unit)
18
+ put(units_path(name), unit)
19
+ end
20
+
21
+ alias_method :update_unit, :create_unit
22
+
23
+ def delete_unit(name)
24
+ delete(units_path(name))
22
25
  end
23
26
 
24
27
  private
25
28
 
26
- def unit_path(*parts)
27
- resource_path(UNIT_RESOURCE, *parts)
29
+ def units_path(*parts)
30
+ resource_path(UNITS_RESOURCE, *parts)
28
31
  end
29
32
 
30
33
  end
data/lib/fleet/client.rb CHANGED
@@ -1,20 +1,14 @@
1
- require 'json'
2
1
  require 'fleet/connection'
3
2
  require 'fleet/error'
4
3
  require 'fleet/request'
5
4
  require 'fleet/service_definition'
6
- require 'fleet/client/job'
7
5
  require 'fleet/client/machines'
8
- require 'fleet/client/state'
9
6
  require 'fleet/client/unit'
7
+ require 'fleet/client/state'
10
8
 
11
9
  module Fleet
12
10
  class Client
13
11
 
14
- FLEET_PATH = 'v2/keys/_coreos.com/fleet'
15
- MAX_RETRIES = 20
16
- SLEEP_TIME = (10.0 / MAX_RETRIES.to_f)
17
-
18
12
  attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
19
13
 
20
14
  def initialize(options={})
@@ -27,35 +21,30 @@ module Fleet
27
21
  include Fleet::Connection
28
22
  include Fleet::Request
29
23
 
30
- include Fleet::Client::Job
31
24
  include Fleet::Client::Machines
32
- include Fleet::Client::State
33
25
  include Fleet::Client::Unit
26
+ include Fleet::Client::State
34
27
 
35
28
  def list
36
- machines = list_machines['node']['nodes'] || []
29
+ machines = list_machines['machines'] || []
37
30
  machine_ips = machines.each_with_object({}) do |machine, h|
38
- m = JSON.parse(machine['nodes'].first['value'])
39
- h[m['ID']] = m['PublicIP']
31
+ h[machine['id']] = machine['primaryIP']
40
32
  end
41
33
 
42
- states = list_states['node']['nodes'] || []
34
+ states = list_states['states'] || []
43
35
  states.map do |service|
44
- s = JSON.parse(service['value'])
45
- machine_id = s['machineState']['ID']
46
-
47
36
  {
48
- name: service['key'].split('/').last,
49
- load_state: s['loadState'],
50
- active_state: s['activeState'],
51
- sub_state: s['subState'],
52
- machine_id: machine_id,
53
- machine_ip: machine_ips[machine_id]
37
+ name: service['name'],
38
+ load_state: service['systemdLoadState'],
39
+ active_state: service['systemdActiveState'],
40
+ sub_state: service['systemdSubState'],
41
+ machine_id: service['machineID'],
42
+ machine_ip: machine_ips[service['machineID']]
54
43
  }
55
44
  end
56
45
  end
57
46
 
58
- def load(name, service_def=nil, sync=false)
47
+ def load(name, service_def=nil)
59
48
 
60
49
  unless name =~ /\A[a-zA-Z0-9:_.@-]+\Z/
61
50
  raise ArgumentError, 'name may only contain [a-zA-Z0-9:_.@-]'
@@ -63,85 +52,56 @@ module Fleet
63
52
 
64
53
  if service_def
65
54
  unless service_def.is_a?(ServiceDefinition)
66
- service_def = ServiceDefinition.new(name, service_def)
55
+ service_def = ServiceDefinition.new(service_def)
67
56
  end
68
57
 
69
58
  begin
70
- create_unit(service_def.sha1, service_def.to_unit)
71
- rescue Fleet::PreconditionFailed
72
- end
73
-
74
- begin
75
- create_job(service_def.name, service_def.to_job)
59
+ create_unit(name, service_def.to_unit(name))
76
60
  rescue Fleet::PreconditionFailed
77
61
  end
62
+ else
63
+ opts = { 'desiredState' => 'loaded', 'name' => name }
64
+ update_unit(name, opts)
78
65
  end
66
+ end
79
67
 
80
- update_job_target_state(name, :loaded)
81
- wait_for_load_state(name, 'loaded') if sync
68
+ def start(name)
69
+ opts = { 'desiredState' => 'launched', 'name' => name }
70
+ update_unit(name, opts)
82
71
  end
83
72
 
84
- def start(service_name)
85
- update_job_target_state(service_name, :launched)
73
+ def stop(name)
74
+ opts = { 'desiredState' => 'loaded', 'name' => name }
75
+ update_unit(name, opts)
86
76
  end
87
77
 
88
- def stop(service_name, sync=false)
89
- update_job_target_state(service_name, :loaded)
90
- wait_for_load_state(service_name, 'loaded') if sync
78
+ def unload(name)
79
+ opts = { 'desiredState' => 'inactive', 'name' => name }
80
+ update_unit(name, opts)
91
81
  end
92
82
 
93
- def unload(service_name, sync=false)
94
- update_job_target_state(service_name, :inactive)
95
- wait_for_load_state(service_name, :no_state) if sync
83
+ def destroy(name)
84
+ delete_unit(name)
96
85
  end
97
86
 
98
- def destroy(service_name, sync=false)
99
- delete_job(service_name)
100
- wait_for_load_state(service_name, :no_state) if sync
87
+ def status(name)
88
+ get_unit(name)["currentState"].to_sym
101
89
  end
102
90
 
103
- def status(service_name)
104
- fleet_state = get_state(service_name)
105
- service_states = JSON.parse(fleet_state['node']['value'])
106
- service_states.each_with_object({}) do |(k, v), hash|
107
- hash[underscore(k).to_sym] = v
91
+ def get_unit_state(name)
92
+ options = { unitName: name }
93
+ states = list_states(options)
94
+ if states["states"]
95
+ states["states"].first
96
+ else
97
+ fail NotFound, "Unit '#{name}' not found"
108
98
  end
109
99
  end
110
100
 
111
101
  protected
112
102
 
113
103
  def resource_path(resource, *parts)
114
- parts.unshift(resource).unshift(FLEET_PATH).join('/')
115
- end
116
-
117
- def wait_for_load_state(service_name, target_state='loaded')
118
- result = MAX_RETRIES.times do
119
- begin
120
- break target_state if status(service_name)[:load_state] == target_state
121
- rescue Fleet::NotFound
122
- # :no_state is a special case of target state that indicates we
123
- # expect the state to not be found at all (useful when waiting for
124
- # a delete job call)
125
- break target_state if target_state == :no_state
126
- end
127
-
128
- sleep(SLEEP_TIME)
129
- end
130
-
131
- if result == target_state
132
- true
133
- else
134
- fail Fleet::Error,
135
- "Job state '#{target_state}' could not be achieved"
136
- end
137
- end
138
-
139
- def underscore(camel_cased_word)
140
- return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
141
- word = camel_cased_word.gsub(/([a-z\d])([A-Z])/,'\1_\2')
142
- word.tr!("-", "_")
143
- word.downcase!
144
- word
104
+ parts.unshift('fleet', fleet_api_version, resource).join('/')
145
105
  end
146
106
  end
147
107
  end
@@ -1,24 +1,20 @@
1
- require 'faraday'
2
1
  require 'logger'
3
2
 
4
3
  module Fleet
5
4
  module Configuration
6
5
 
7
6
  VALID_OPTIONS_KEYS = [
8
- :adapter,
9
7
  :fleet_api_url,
8
+ :fleet_api_version,
10
9
  :open_timeout,
11
10
  :read_timeout,
12
- :ssl_options,
13
- :proxy,
14
11
  :logger
15
12
  ]
16
13
 
17
- DEFAULT_ADAPTER = Faraday.default_adapter
18
- DEFAULT_ETCD_API_URL = ENV['FLEETCTL_ENDPOINT']
14
+ DEFAULT_FLEET_API_URL = ENV['FLEETCTL_ENDPOINT'] || 'unix:///var/run/fleet.sock'
15
+ DEFAULT_FLEET_API_VERSION = 'v1'
19
16
  DEFAULT_OPEN_TIMEOUT = 2
20
17
  DEFAULT_READ_TIMEOUT = 5
21
- DEFAULT_SSL_OPTIONS = { verify: false }
22
18
  DEFAULT_LOGGER = ::Logger.new(STDOUT)
23
19
 
24
20
  attr_accessor(*VALID_OPTIONS_KEYS)
@@ -33,11 +29,10 @@ module Fleet
33
29
  end
34
30
 
35
31
  def reset
36
- self.adapter = DEFAULT_ADAPTER
37
- self.fleet_api_url = DEFAULT_ETCD_API_URL
32
+ self.fleet_api_url = DEFAULT_FLEET_API_URL
33
+ self.fleet_api_version = DEFAULT_FLEET_API_VERSION
38
34
  self.open_timeout = DEFAULT_OPEN_TIMEOUT
39
35
  self.read_timeout = DEFAULT_READ_TIMEOUT
40
- self.ssl_options = DEFAULT_SSL_OPTIONS
41
36
  self.logger = DEFAULT_LOGGER
42
37
  end
43
38
  end
@@ -1,24 +1,33 @@
1
- require 'faraday'
2
- require 'faraday_middleware'
3
- require 'fleet/middleware/response/raise_error'
1
+ require 'excon'
4
2
 
5
3
  module Fleet
6
4
  module Connection
7
5
 
8
6
  def connection
9
7
  options = {
10
- url: fleet_api_url,
11
- ssl: ssl_options,
12
- proxy: proxy
8
+ read_timeout: read_timeout,
9
+ connect_timeout: open_timeout,
10
+ headers: { 'User-Agent' => user_agent, 'Accept' => 'application/json' }
13
11
  }
14
12
 
15
- Faraday.new(options) do |faraday|
16
- faraday.request :url_encoded
17
- faraday.response :json
18
- faraday.response :raise_fleet_error
19
- faraday.response :follow_redirects
20
- faraday.adapter adapter
13
+ uri = URI.parse(fleet_api_url)
14
+ if uri.scheme == 'unix'
15
+ uri, options = 'unix:///', { socket: uri.path }.merge(options)
16
+ else
17
+ uri = fleet_api_url
21
18
  end
19
+
20
+ Excon.new(uri, options)
21
+ end
22
+
23
+ private
24
+
25
+ def user_agent
26
+ ua_chunks = []
27
+ ua_chunks << "fleet/#{Fleet::VERSION}"
28
+ ua_chunks << "(#{RUBY_ENGINE}; #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}; #{RUBY_PLATFORM})"
29
+ ua_chunks << "excon/#{Excon::VERSION}"
30
+ ua_chunks.join(' ')
22
31
  end
23
32
  end
24
33
  end
data/lib/fleet/error.rb CHANGED
@@ -4,10 +4,9 @@ module Fleet
4
4
  attr_reader :error_code
5
5
  attr_reader :cause
6
6
 
7
- def initialize(msg, error_code=nil, cause=nil)
7
+ def initialize(msg, error_code=nil)
8
8
  super(msg)
9
9
  @error_code = error_code
10
- @cause = cause
11
10
  end
12
11
 
13
12
  HTTP_CODE_MAP = {
data/lib/fleet/request.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'json'
1
2
  require 'fleet/version'
2
3
 
3
4
  module Fleet
@@ -5,52 +6,54 @@ module Fleet
5
6
 
6
7
  private
7
8
 
8
- [:get, :head, :put, :post, :delete].each do |method|
9
- define_method(method) do |path, options={}, headers={}|
10
- request(connection, method, path, options, headers)
9
+ [:get, :put, :delete].each do |method|
10
+ define_method(method) do |path, options={}|
11
+ request(connection, method, path, options)
11
12
  end
12
13
  end
13
14
 
14
- def request(connection, method, path, options, headers)
15
- options ||= {}
16
-
17
- response = connection.send(method) do |request|
18
- request.options[:open_timeout] = open_timeout
19
- request.options[:timeout] = read_timeout
20
- request.headers = {
21
- user_agent: user_agent,
22
- accept: 'application/json'
23
- }.merge(headers)
24
-
25
- request.path = URI.escape(path)
26
-
27
- case method
28
- when :delete, :get, :head
29
- request.params = options unless options.empty?
30
- when :post, :put
31
- if options.key?(:querystring)
32
- request.params = options[:querystring]
33
- request.body = options[:body]
34
- else
35
- request.body = options unless options.empty?
36
- end
37
- end
15
+ def request(connection, method, path, options)
16
+ req = {
17
+ path: escape_path(path),
18
+ }
19
+
20
+ case method
21
+ when :get
22
+ req[:query] = options
23
+ when :put
24
+ req[:headers] = { 'Content-Type' => 'application/json' }
25
+ req[:body] = ::JSON.dump(options)
38
26
  end
39
27
 
40
- response.body
41
- rescue Faraday::Error::ConnectionFailed => ex
28
+ resp = connection.send(method, req)
29
+
30
+ if (400..600).include?(resp.status)
31
+ raise_error(resp)
32
+ end
33
+
34
+ case method
35
+ when :get
36
+ ::JSON.parse(resp.body)
37
+ else
38
+ true
39
+ end
40
+ rescue Excon::Errors::SocketError => ex
42
41
  raise Fleet::ConnectionError, ex.message
43
42
  end
44
43
 
45
44
  private
46
45
 
47
- def user_agent
48
- ua_chunks = []
49
- ua_chunks << "fleet/#{Fleet::VERSION}"
50
- ua_chunks << "(#{RUBY_ENGINE}; #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}; #{RUBY_PLATFORM})"
51
- ua_chunks << "faraday/#{Faraday::VERSION}"
52
- ua_chunks << "(#{adapter})"
53
- ua_chunks.join(' ')
46
+ def escape_path(path)
47
+ URI.escape(path).gsub(/@/, '%40')
48
+ end
49
+
50
+ def raise_error(resp)
51
+ error = JSON.parse(resp.body)['error']
52
+ class_name = Fleet::Error::HTTP_CODE_MAP.fetch(resp.status, 'Error')
53
+
54
+ fail Fleet.const_get(class_name).new(
55
+ error['message'],
56
+ error['code'])
54
57
  end
55
58
  end
56
59
  end