fleet-api 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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