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 +5 -5
- data/CODEOWNERS +2 -0
- data/Gemfile +2 -0
- data/README.md +5 -5
- data/lib/orchestrator_client.rb +24 -29
- data/lib/orchestrator_client/config.rb +42 -3
- data/lib/orchestrator_client/error.rb +1 -1
- data/lib/orchestrator_client/job.rb +6 -4
- data/lib/orchestrator_client/version.rb +1 -1
- data/orchestrator_client.gemspec +3 -0
- metadata +33 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e686e0883d0f22984bcc8f7f10f1b1f98a9824a8439c8e66ce4cb345128a0b3
|
4
|
+
data.tar.gz: 73853c08047115fa0da5792043d8469df480fd5d73e659bb627e7f08e87f5ce2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9cb2125237818733cdc737d2a2d427b4759fc64857af085076f80a5a3965152369ea3e38329a31eec9fe73498bf3608be1daa8251a5e63cdc253aa3ff149d5b
|
7
|
+
data.tar.gz: 73546958e6d55201504a8ba6aef5ad15aae51cc40c6b9fafc519c45ea0c09dfa5e0628a9003e6ef68cc3876341409e71c15eefe240795ad5aab33b5360b2810c
|
data/CODEOWNERS
ADDED
data/Gemfile
CHANGED
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.
|
data/lib/orchestrator_client.rb
CHANGED
@@ -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
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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.
|
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
|
-
|
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([
|
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']
|
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.
|
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
|
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
|
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
|
92
|
-
counter +=
|
93
|
+
sleep @poll_interval
|
94
|
+
counter += @poll_interval
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
data/orchestrator_client.gemspec
CHANGED
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.
|
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:
|
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
|
-
|
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
|