orchestrator_client 0.3.0 → 0.5.1

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
- SHA1:
3
- metadata.gz: ae1e5ffab2eb4b54664018931e8ea680bf22d405
4
- data.tar.gz: bbfc8793e9cb5f2ef057d6c240c787a753f53599
2
+ SHA256:
3
+ metadata.gz: 8e686e0883d0f22984bcc8f7f10f1b1f98a9824a8439c8e66ce4cb345128a0b3
4
+ data.tar.gz: 73853c08047115fa0da5792043d8469df480fd5d73e659bb627e7f08e87f5ce2
5
5
  SHA512:
6
- metadata.gz: 5092e14ce386236cbed58c8e6008e50bdddfd9d8edd73d3f6969c44d266d66b72551669c32d671fee47e16fd6d96abb9f098c1a886f487049e4b8913aefced97
7
- data.tar.gz: 766e8b046d39d079632c94747e79b7a32d45d97dcec17a5576bd4e1b39f10064b90912ce0d7b3a7efd13d840f3eb4d3f251764e7f4b32809011f7031958e92fe
6
+ metadata.gz: c9cb2125237818733cdc737d2a2d427b4759fc64857af085076f80a5a3965152369ea3e38329a31eec9fe73498bf3608be1daa8251a5e63cdc253aa3ff149d5b
7
+ data.tar.gz: 73546958e6d55201504a8ba6aef5ad15aae51cc40c6b9fafc519c45ea0c09dfa5e0628a9003e6ef68cc3876341409e71c15eefe240795ad5aab33b5360b2810c
@@ -0,0 +1,2 @@
1
+ # Default to Bolt team
2
+ * @puppetlabs/bolt
data/Gemfile CHANGED
@@ -9,4 +9,6 @@ end
9
9
 
10
10
  group :development do
11
11
  gem 'pry'
12
+ gem 'pry-stack_explorer'
13
+ gem 'pry-byebug'
12
14
  end
data/README.md CHANGED
@@ -5,7 +5,8 @@ A simple client for interacting with the Orchestration Services API in Puppet En
5
5
 
6
6
  ## Compatibility
7
7
 
8
- Currently, this client supports the "V1" endpoints shipped as part of Puppet Enterprise 2016.2.
8
+ Currently, this client supports the "V1" endpoints shipped as part of Puppet Enterprise 2016.2 -
9
+ 2019.8.4.
9
10
 
10
11
  ## Installation
11
12
 
@@ -26,6 +27,9 @@ expected to be at `~/.puppetlabs/token` which is the default location used by
26
27
  * `token-file`- Path to a file with the RBAC token in it (defaults to `~/.puppetlabs/token`)
27
28
  * `token` - Pass directly the RBAC token, if specified the token will be used instead of a token from file.
28
29
  * `User-Agent`- Set `User-Agent` header for HTTP requests. Defaults to `OrchestratorRubyClient/[VERSION]`
30
+ * `job-poll-interval`- Set the default amount of time to sleep when polling in Orchestrator::Job#wait and #each\_event
31
+ * `job-poll-timeout`- Set the default maximum amount of time to wait in Orchestrator::Job#wait
32
+ * `read-timeout` - The time to wait before raising a Timeout exception when making HTTP requests.
29
33
 
30
34
  ### Example
31
35
 
@@ -67,10 +71,6 @@ issues](https://github.com/puppetlabs/orchestrator_api-ruby/issues).
67
71
  If you are interested in contributing to this project, please see the
68
72
  [Contribution Guidelines](CONTRIBUTING.md)
69
73
 
70
- ## Authors
71
-
72
- Tom Linkin <tom@puppet.com>
73
-
74
74
  ## License
75
75
 
76
76
  See LICENSE.
@@ -2,6 +2,7 @@ require 'net/https'
2
2
  require 'uri'
3
3
  require 'json'
4
4
  require 'openssl'
5
+ require 'faraday'
5
6
 
6
7
  class OrchestratorClient
7
8
  require 'orchestrator_client/error'
@@ -11,35 +12,37 @@ class OrchestratorClient
11
12
  require 'orchestrator_client/config'
12
13
 
13
14
  attr_accessor :config
15
+ attr_reader :http
14
16
 
15
17
  def initialize(overrides, load_files=false)
16
18
  @config = Config.new(overrides, load_files)
17
19
  @config.validate
20
+ @http = create_http(config.root_url)
18
21
  end
19
22
 
20
- def make_uri(path)
21
- URI.parse("#{config.root_url}#{path}")
22
- end
23
-
24
- def create_http(uri)
25
- http = Net::HTTP.new(uri.host, uri.port)
26
- http.use_ssl = true
27
- http.ssl_version = :TLSv1_2
28
- http.ca_file = config['cacert']
29
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
30
- http
23
+ def create_http(root_url)
24
+ Faraday.new(url: root_url) do |f|
25
+ f.headers['Content-Type'] = 'application/json'
26
+ f.headers['X-Authentication'] = config.token
27
+ f.headers['User-Agent'] = config['User-Agent']
28
+ f.ssl['ca_file'] = config['cacert']
29
+ f.ssl['version'] = :TLSv1_2
30
+ # Do not use net-http-persistent on windows
31
+ if !!File::ALT_SEPARATOR
32
+ f.adapter :net_http
33
+ else
34
+ f.adapter :net_http_persistent, pool_size: 5 do |http|
35
+ http.idle_timeout = 30
36
+ http.read_timeout = config['read-timeout'] if config['read-timeout']
37
+ end
38
+ end
39
+ end
31
40
  end
32
41
 
33
42
  def get(location)
34
- uri = make_uri(location)
35
- https = create_http(uri)
36
- req = Net::HTTP::Get.new(uri)
37
- req['Content-Type'] = "application/json"
38
- req['User-Agent'] = @config['User-Agent']
39
- req.add_field('X-Authentication', @config.token)
40
- res = https.request(req)
43
+ res = http.get(location)
41
44
 
42
- if res.code != "200"
45
+ if res.status != 200
43
46
  raise OrchestratorClient::ApiError.make_error_from_response(res)
44
47
  end
45
48
 
@@ -47,17 +50,9 @@ class OrchestratorClient
47
50
  end
48
51
 
49
52
  def post(location, body)
50
- uri = make_uri(location)
51
- https = create_http(uri)
52
-
53
- req = Net::HTTP::Post.new(uri)
54
- req['Content-Type'] = "application/json"
55
- req['User-Agent'] = @config['User-Agent']
56
- req.add_field('X-Authentication', @config.token)
57
- req.body = body.to_json
58
- res = https.request(req)
53
+ res = http.post(location, body.to_json)
59
54
 
60
- unless Set.new(["202", "200"]).include? res.code
55
+ unless Set.new([202, 200]).include? res.status
61
56
  raise OrchestratorClient::ApiError.make_error_from_response(res)
62
57
  end
63
58
 
@@ -35,7 +35,9 @@ class OrchestratorClient::Config
35
35
  def defaults
36
36
  { 'cacert' => cacert,
37
37
  'token-file' => File.join(user_root, 'token'),
38
- 'User-Agent' => "OrchestratorRubyClient/#{OrchestratorClient::VERSION}"
38
+ 'User-Agent' => "OrchestratorRubyClient/#{OrchestratorClient::VERSION}",
39
+ 'job-poll-interval' => 1,
40
+ 'job-poll-timeout' => 1000,
39
41
  }
40
42
  end
41
43
 
@@ -53,7 +55,12 @@ class OrchestratorClient::Config
53
55
  end
54
56
  end
55
57
 
56
- config.merge(@overrides)
58
+ config.merge!(@overrides)
59
+
60
+ %w[token-file cacert].each do |f|
61
+ config[f] = File.expand_path(config[f]) if config[f]
62
+ end
63
+ config
57
64
  end
58
65
 
59
66
  def validate
@@ -61,9 +68,20 @@ class OrchestratorClient::Config
61
68
  raise OrchestratorClient::ConfigError.new("'service-url' is required in config")
62
69
  end
63
70
 
71
+ begin
72
+ service_url = URI.parse(config['service-url'])
73
+ unless service_url.kind_of?(URI::HTTP) || service_url.kind_of?(URI::HTTPS)
74
+ raise OrchestratorClient::ConfigError.new("'#{config['service-url']}' is an invalid service-url")
75
+ end
76
+ rescue URI::InvalidURIError
77
+ raise OrchestratorClient::ConfigError.new("'#{config['service-url']}' is an invalid service-url")
78
+ end
79
+
64
80
  if config['cacert'].nil?
65
81
  raise OrchestratorClient::ConfigError.new("'cacert' is required in config")
66
82
  end
83
+
84
+ validate_file('cacert', config['cacert'])
67
85
  end
68
86
 
69
87
  def config
@@ -75,7 +93,17 @@ class OrchestratorClient::Config
75
93
  end
76
94
 
77
95
  def load_token
78
- @config['token'] || File.open(config['token-file']) { |f| f.read }
96
+ if @config['token']
97
+ @config['token']
98
+ else
99
+ validate_file('token-file', config['token-file'])
100
+ token = File.open(config['token-file']) { |f| f.read.strip }
101
+ if token != URI.escape(token)
102
+ raise OrchestratorClient::ConfigError.new("token-file '#{config['token-file']}' contains illegal characters")
103
+ end
104
+ @config['token'] = token
105
+ @config['token']
106
+ end
79
107
  end
80
108
 
81
109
  def token
@@ -95,4 +123,15 @@ class OrchestratorClient::Config
95
123
  def [](key)
96
124
  @config[key]
97
125
  end
126
+
127
+ def validate_file(type, path)
128
+ stat = File.stat(path)
129
+ if !stat.readable?
130
+ OrchestratorClient::ConfigError.new("#{type} '#{path}' is unreadable")
131
+ elsif !stat.file?
132
+ OrchestratorClient::ConfigError.new("#{type} '#{path}' is not a file")
133
+ end
134
+ rescue Errno::ENOENT
135
+ raise OrchestratorClient::ConfigError.new("#{type} '#{path}' does not exist")
136
+ end
98
137
  end
@@ -17,7 +17,7 @@ class OrchestratorClient::ApiError < RuntimeError
17
17
  rescue
18
18
  return OrchestratorClient::BadResponse.new("Response body was not valid JSON: #{res.body}")
19
19
  end
20
- code = res.code
20
+ code = res.status
21
21
 
22
22
  case data['kind']
23
23
  when 'puppetlabs.validators/validation-error'
@@ -16,6 +16,8 @@ class OrchestratorClient::Job
16
16
 
17
17
  def initialize(client, options = {}, type=:deploy)
18
18
  @client = client
19
+ @poll_interval = options.delete(:_poll_interval) || client.config['job-poll-interval']
20
+ @poll_timeout = options.delete(:_poll_timeout) || client.config['job-poll-timeout']
19
21
  @options = options
20
22
  @type = type
21
23
  end
@@ -71,7 +73,7 @@ class OrchestratorClient::Job
71
73
  events = @client.jobs.events(@job_name)
72
74
  start = events['next-events']['event']
73
75
  if events['items'].empty?
74
- sleep 1
76
+ sleep @poll_interval
75
77
  else
76
78
  events['items'].each do |event|
77
79
  finished = true if DONE_EVENTS.include?(event['type'])
@@ -81,15 +83,15 @@ class OrchestratorClient::Job
81
83
  end
82
84
  end
83
85
 
84
- def wait(timeout=1000)
86
+ def wait(timeout=@poll_timeout)
85
87
  counter = 0
86
88
  while counter < timeout
87
89
  get_details
88
90
  if DONE_STATES.include?(details['state'])
89
91
  return report
90
92
  end
91
- sleep 1
92
- counter += 1
93
+ sleep @poll_interval
94
+ counter += @poll_interval
93
95
  end
94
96
  end
95
97
  end
@@ -1,3 +1,3 @@
1
1
  class OrchestratorClient
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.5.1'.freeze
3
3
  end
@@ -14,4 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.homepage = 'https://github.com/puppetlabs/orchestrator_client-ruby'
15
15
  s.license = "Apache-2.0"
16
16
  s.require_paths = ["lib"]
17
+
18
+ s.add_dependency 'faraday'
19
+ s.add_dependency 'net-http-persistent'
17
20
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orchestrator_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-11 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-01-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-http-persistent
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  description:
14
42
  email: info@puppetlabs.com
15
43
  executables: []
@@ -17,6 +45,7 @@ extensions: []
17
45
  extra_rdoc_files: []
18
46
  files:
19
47
  - ".gitignore"
48
+ - CODEOWNERS
20
49
  - CONTRIBUTING.md
21
50
  - Gemfile
22
51
  - LICENSE
@@ -48,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
48
77
  - !ruby/object:Gem::Version
49
78
  version: '0'
50
79
  requirements: []
51
- rubyforge_project:
52
- rubygems_version: 2.5.1
80
+ rubygems_version: 3.0.8
53
81
  signing_key:
54
82
  specification_version: 4
55
83
  summary: Simple Ruby client library for PE Orchestration Services