bolt 3.26.1 → 3.27.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/bolt/config/options.rb +8 -0
- data/lib/bolt/config/transport/jail.rb +33 -0
- data/lib/bolt/executor.rb +2 -0
- data/lib/bolt/shell/bash.rb +1 -1
- data/lib/bolt/transport/jail/connection.rb +81 -0
- data/lib/bolt/transport/jail.rb +21 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/schemas/action-run_task.json +5 -1
- data/lib/bolt_server/transport_app.rb +26 -56
- metadata +28 -14
- data/lib/bolt_server/schemas/connect-data.json +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c17b8b0fb4276ed447b6da76d98053171f4d5fda8503233035b919394add9e94
|
4
|
+
data.tar.gz: db0861f045bc751bd69e0da10fe7708b6b0186c5fe1e35e252b383ff935b77f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af08780fd019620d3db858eb34387a38a0ef195d9ab56cfc2bc1e6629e1b86fcd2301b489facd81a77915a914d95eb017d5e88ec7443e66c74c72c148f334c5f
|
7
|
+
data.tar.gz: d01bb8cb30bcfd2a48e9537311b6208e8c7340e02b1101745ffe52affdf1503cf7754de7918b179af033aaa3303e9b4f381d460083cc302864f0747f4bc79d6b
|
data/lib/bolt/config/options.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../bolt/config/transport/docker'
|
4
|
+
require_relative '../../bolt/config/transport/jail'
|
4
5
|
require_relative '../../bolt/config/transport/local'
|
5
6
|
require_relative '../../bolt/config/transport/lxd'
|
6
7
|
require_relative '../../bolt/config/transport/orch'
|
@@ -16,6 +17,7 @@ module Bolt
|
|
16
17
|
# gets passed along to the inventory.
|
17
18
|
TRANSPORT_CONFIG = {
|
18
19
|
'docker' => Bolt::Config::Transport::Docker,
|
20
|
+
'jail' => Bolt::Config::Transport::Jail,
|
19
21
|
'local' => Bolt::Config::Transport::Local,
|
20
22
|
'lxd' => Bolt::Config::Transport::LXD,
|
21
23
|
'pcp' => Bolt::Config::Transport::Orch,
|
@@ -550,6 +552,12 @@ module Bolt
|
|
550
552
|
_plugin: true,
|
551
553
|
_example: { "cleanup" => false, "service-url" => "https://docker.example.com" }
|
552
554
|
},
|
555
|
+
"jail" => {
|
556
|
+
description: "A map of configuration options for the jail transport.",
|
557
|
+
type: Hash,
|
558
|
+
_plugin: true,
|
559
|
+
_example: { cleanup: false }
|
560
|
+
},
|
553
561
|
"local" => {
|
554
562
|
description: "A map of configuration options for the local transport. The set of available options is "\
|
555
563
|
"platform dependent.",
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../bolt/error'
|
4
|
+
require_relative '../../../bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Jail < Base
|
10
|
+
OPTIONS = %w[
|
11
|
+
cleanup
|
12
|
+
host
|
13
|
+
interpreters
|
14
|
+
shell-command
|
15
|
+
tmpdir
|
16
|
+
user
|
17
|
+
].concat(RUN_AS_OPTIONS).sort.freeze
|
18
|
+
|
19
|
+
DEFAULTS = {
|
20
|
+
'cleanup' => true
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
private def validate
|
24
|
+
super
|
25
|
+
|
26
|
+
if @config['interpreters']
|
27
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/bolt/executor.rb
CHANGED
@@ -14,6 +14,7 @@ require_relative '../bolt/result'
|
|
14
14
|
require_relative '../bolt/result_set'
|
15
15
|
# Load transports
|
16
16
|
require_relative '../bolt/transport/docker'
|
17
|
+
require_relative '../bolt/transport/jail'
|
17
18
|
require_relative '../bolt/transport/local'
|
18
19
|
require_relative '../bolt/transport/lxd'
|
19
20
|
require_relative '../bolt/transport/orch'
|
@@ -25,6 +26,7 @@ require_relative '../bolt/transport/winrm'
|
|
25
26
|
module Bolt
|
26
27
|
TRANSPORTS = {
|
27
28
|
docker: Bolt::Transport::Docker,
|
29
|
+
jail: Bolt::Transport::Jail,
|
28
30
|
local: Bolt::Transport::Local,
|
29
31
|
lxd: Bolt::Transport::LXD,
|
30
32
|
pcp: Bolt::Transport::Orch,
|
data/lib/bolt/shell/bash.rb
CHANGED
@@ -356,7 +356,7 @@ module Bolt
|
|
356
356
|
if defined? conn.add_env_vars
|
357
357
|
conn.add_env_vars(options[:environment])
|
358
358
|
else
|
359
|
-
env_decl = options[:environment].map do |env, val|
|
359
|
+
env_decl = '/usr/bin/env ' + options[:environment].map do |env, val|
|
360
360
|
"#{env}=#{Shellwords.shellescape(val)}"
|
361
361
|
end.join(' ')
|
362
362
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logging'
|
4
|
+
require_relative '../../../bolt/node/errors'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
module Transport
|
8
|
+
class Jail < Simple
|
9
|
+
class Connection
|
10
|
+
attr_reader :user, :target
|
11
|
+
|
12
|
+
def initialize(target)
|
13
|
+
raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host
|
14
|
+
@target = target
|
15
|
+
@user = @target.user || ENV['USER'] || Etc.getlogin
|
16
|
+
@logger = Bolt::Logger.logger(target.safe_name)
|
17
|
+
@jail_info = {}
|
18
|
+
@logger.trace("Initializing jail connection to #{target.safe_name}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def shell
|
22
|
+
@shell ||= Bolt::Shell::Bash.new(target, self)
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset_cwd?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def jail_id
|
30
|
+
@jail_info['jid'].to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def jail_path
|
34
|
+
@jail_info['path']
|
35
|
+
end
|
36
|
+
|
37
|
+
def connect
|
38
|
+
output = JSON.parse(`jls --libxo=json`)
|
39
|
+
@jail_info = output['jail-information']['jail'].select { |jail| jail['hostname'] == target.host }.first
|
40
|
+
raise "Could not find a jail with name matching #{target.host}" if @jail_info.nil?
|
41
|
+
@logger.trace { "Opened session" }
|
42
|
+
true
|
43
|
+
rescue StandardError => e
|
44
|
+
raise Bolt::Node::ConnectError.new(
|
45
|
+
"Failed to connect to #{target.safe_name}: #{e.message}",
|
46
|
+
'CONNECT_ERROR'
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute(command)
|
51
|
+
args = ['-lU', @user]
|
52
|
+
|
53
|
+
jail_command = %w[jexec] + args + [jail_id] + Shellwords.split(command)
|
54
|
+
@logger.trace { "Executing #{jail_command.join(' ')}" }
|
55
|
+
|
56
|
+
Open3.popen3({}, *jail_command)
|
57
|
+
rescue StandardError
|
58
|
+
@logger.trace { "Command aborted" }
|
59
|
+
raise
|
60
|
+
end
|
61
|
+
|
62
|
+
def upload_file(source, destination)
|
63
|
+
@logger.trace { "Uploading #{source} to #{destination}" }
|
64
|
+
jail_destination = File.join(jail_path, destination)
|
65
|
+
FileUtils.cp(source, jail_destination)
|
66
|
+
rescue StandardError => e
|
67
|
+
raise Bolt::Node::FileError.new(e.message, 'WRITE_ERROR')
|
68
|
+
end
|
69
|
+
|
70
|
+
def download_file(source, destination, _download)
|
71
|
+
@logger.trace { "Downloading #{source} to #{destination}" }
|
72
|
+
jail_source = File.join(jail_path, source)
|
73
|
+
FileUtils.mkdir_p(destination)
|
74
|
+
FileUtils.cp(jail_source, destination)
|
75
|
+
rescue StandardError => e
|
76
|
+
raise Bolt::Node::FileError.new(e.message, 'WRITE_ERROR')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../bolt/transport/simple'
|
4
|
+
|
5
|
+
module Bolt
|
6
|
+
module Transport
|
7
|
+
class Jail < Simple
|
8
|
+
def provided_features
|
9
|
+
['shell']
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_connection(target)
|
13
|
+
conn = Connection.new(target)
|
14
|
+
conn.connect
|
15
|
+
yield conn
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require_relative 'jail/connection'
|
data/lib/bolt/version.rb
CHANGED
@@ -9,7 +9,11 @@
|
|
9
9
|
"type": "object",
|
10
10
|
"description": "JSON formatted parameters to be provided to task"
|
11
11
|
},
|
12
|
-
"target": { "$ref": "partial:target-any" }
|
12
|
+
"target": { "$ref": "partial:target-any" },
|
13
|
+
"timeout": {
|
14
|
+
"type": "integer",
|
15
|
+
"description": "Number of seconds to wait before abandoning the task execution on the tartet."
|
16
|
+
}
|
13
17
|
},
|
14
18
|
"required": ["target", "task"],
|
15
19
|
"additionalProperties": false
|
@@ -9,7 +9,6 @@ require 'bolt/project'
|
|
9
9
|
require 'bolt/target'
|
10
10
|
require 'bolt_server/file_cache'
|
11
11
|
require 'bolt_server/plugin'
|
12
|
-
require 'bolt_server/plugin/puppet_connect_data'
|
13
12
|
require 'bolt_server/request_error'
|
14
13
|
require 'bolt/task/puppet_server'
|
15
14
|
require 'json'
|
@@ -42,7 +41,6 @@ module BoltServer
|
|
42
41
|
action-upload_file
|
43
42
|
transport-ssh
|
44
43
|
transport-winrm
|
45
|
-
connect-data
|
46
44
|
action-apply_prep
|
47
45
|
action-apply
|
48
46
|
].freeze
|
@@ -126,7 +124,17 @@ module BoltServer
|
|
126
124
|
end
|
127
125
|
end
|
128
126
|
|
129
|
-
def
|
127
|
+
def unwrap_sensitive_results(result_set)
|
128
|
+
# Take a ResultSet and unwrap sensitive values
|
129
|
+
result_set.each do |result|
|
130
|
+
value = result.value
|
131
|
+
next unless value.is_a?(Hash)
|
132
|
+
next unless value.key?('_sensitive')
|
133
|
+
value['_sensitive'] = value['_sensitive'].unwrap
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def task_helper(target, task, parameters, timeout = nil)
|
130
138
|
# Wrap parameters marked with '"sensitive": true' in the task metadata with a
|
131
139
|
# Sensitive wrapper type. This way it's not shown in logs.
|
132
140
|
if (param_spec = task.parameters)
|
@@ -137,11 +145,20 @@ module BoltServer
|
|
137
145
|
end
|
138
146
|
end
|
139
147
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
148
|
+
if timeout && timeout > 0
|
149
|
+
task_thread = Thread.new do
|
150
|
+
unwrap_sensitive_results(@executor.run_task(target, task, parameters))
|
151
|
+
end
|
152
|
+
# Wait for the timeout for the task to execute in the thread. If `join` times out, result will be nil.
|
153
|
+
if task_thread.join(timeout).nil?
|
154
|
+
task_thread.kill
|
155
|
+
raise Bolt::Error.new("Task execution on #{target.first.safe_name} timed out after #{timeout} seconds",
|
156
|
+
'boltserver/task-timeout')
|
157
|
+
else
|
158
|
+
task_thread.value
|
159
|
+
end
|
160
|
+
else
|
161
|
+
unwrap_sensitive_results(@executor.run_task(target, task, parameters))
|
145
162
|
end
|
146
163
|
end
|
147
164
|
|
@@ -150,7 +167,7 @@ module BoltServer
|
|
150
167
|
|
151
168
|
task_data = body['task']
|
152
169
|
task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
|
153
|
-
task_helper(target, task, body['parameters'] || {})
|
170
|
+
task_helper(target, task, body['parameters'] || {}, body['timeout'])
|
154
171
|
end
|
155
172
|
|
156
173
|
def extract_install_task(target)
|
@@ -825,53 +842,6 @@ module BoltServer
|
|
825
842
|
[500, e.message]
|
826
843
|
end
|
827
844
|
|
828
|
-
# Returns a list of targets parsed from a Project inventory
|
829
|
-
#
|
830
|
-
# @param versioned_project [String] the versioned_project to compute the inventory from
|
831
|
-
post '/project_inventory_targets' do
|
832
|
-
content_type :json
|
833
|
-
body = JSON.parse(request.body.read)
|
834
|
-
validate_schema(@schemas["connect-data"], body)
|
835
|
-
in_bolt_project(body['versioned_project']) do |context|
|
836
|
-
if context[:config].inventoryfile &&
|
837
|
-
context[:config].project.inventory_file.to_s !=
|
838
|
-
context[:config].inventoryfile
|
839
|
-
raise Bolt::ValidationError, "Project inventory must be defined in the " \
|
840
|
-
"inventory.yaml file at the root of the project directory"
|
841
|
-
end
|
842
|
-
|
843
|
-
Bolt::Util.validate_file('inventory file', context[:config].project.inventory_file)
|
844
|
-
|
845
|
-
begin
|
846
|
-
# Set the default puppet_library plugin hook if it has not already been
|
847
|
-
# set
|
848
|
-
context[:config].data['plugin-hooks']['puppet_library'] ||= {
|
849
|
-
'plugin' => 'task',
|
850
|
-
'task' => 'puppet_agent::install',
|
851
|
-
'parameters' => {
|
852
|
-
'stop_service' => true
|
853
|
-
}
|
854
|
-
}
|
855
|
-
|
856
|
-
connect_plugin = BoltServer::Plugin::PuppetConnectData.new(body['puppet_connect_data'])
|
857
|
-
plugins = Bolt::Plugin.new(context[:config], context[:pal], load_plugins: false)
|
858
|
-
plugins.add_plugin(connect_plugin)
|
859
|
-
%w[aws_inventory azure_inventory gcloud_inventory].each do |plugin_name|
|
860
|
-
plugins.add_module_plugin(plugin_name) if plugins.known_plugin?(plugin_name)
|
861
|
-
end
|
862
|
-
inventory = Bolt::Inventory.from_config(context[:config], plugins)
|
863
|
-
target_list = inventory.get_targets('all').map do |targ|
|
864
|
-
targ.to_h.merge({ 'transport' => targ.transport, 'plugin_hooks' => targ.plugin_hooks })
|
865
|
-
end
|
866
|
-
rescue Bolt::Plugin::PluginError::LoadingDisabled => e
|
867
|
-
msg = "Cannot load plugin #{e.details['plugin_name']}: plugin not supported"
|
868
|
-
raise BoltServer::Plugin::PluginNotSupported.new(msg, e.details['plugin_name'])
|
869
|
-
end
|
870
|
-
|
871
|
-
[200, target_list.to_json]
|
872
|
-
end
|
873
|
-
end
|
874
|
-
|
875
845
|
# Returns the base64 encoded tar archive of plugin code that is needed to calculate
|
876
846
|
# custom facts
|
877
847
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.27.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -59,6 +59,9 @@ dependencies:
|
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1.0'
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.2.0
|
62
65
|
type: :runtime
|
63
66
|
prerelease: false
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -66,6 +69,9 @@ dependencies:
|
|
66
69
|
- - "~>"
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '1.0'
|
72
|
+
- - "<"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.2.0
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: ffi
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -165,7 +171,7 @@ dependencies:
|
|
165
171
|
version: '4.0'
|
166
172
|
- - "<"
|
167
173
|
- !ruby/object:Gem::Version
|
168
|
-
version: '
|
174
|
+
version: '8.0'
|
169
175
|
type: :runtime
|
170
176
|
prerelease: false
|
171
177
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -175,7 +181,7 @@ dependencies:
|
|
175
181
|
version: '4.0'
|
176
182
|
- - "<"
|
177
183
|
- !ruby/object:Gem::Version
|
178
|
-
version: '
|
184
|
+
version: '8.0'
|
179
185
|
- !ruby/object:Gem::Dependency
|
180
186
|
name: net-ssh-krb
|
181
187
|
requirement: !ruby/object:Gem::Requirement
|
@@ -256,16 +262,22 @@ dependencies:
|
|
256
262
|
name: puppet-strings
|
257
263
|
requirement: !ruby/object:Gem::Requirement
|
258
264
|
requirements:
|
259
|
-
- - "
|
265
|
+
- - ">="
|
266
|
+
- !ruby/object:Gem::Version
|
267
|
+
version: 2.3.0
|
268
|
+
- - "<"
|
260
269
|
- !ruby/object:Gem::Version
|
261
|
-
version: '
|
270
|
+
version: '4.0'
|
262
271
|
type: :runtime
|
263
272
|
prerelease: false
|
264
273
|
version_requirements: !ruby/object:Gem::Requirement
|
265
274
|
requirements:
|
266
|
-
- - "
|
275
|
+
- - ">="
|
276
|
+
- !ruby/object:Gem::Version
|
277
|
+
version: 2.3.0
|
278
|
+
- - "<"
|
267
279
|
- !ruby/object:Gem::Version
|
268
|
-
version: '
|
280
|
+
version: '4.0'
|
269
281
|
- !ruby/object:Gem::Dependency
|
270
282
|
name: r10k
|
271
283
|
requirement: !ruby/object:Gem::Requirement
|
@@ -368,16 +380,16 @@ dependencies:
|
|
368
380
|
name: puppetlabs_spec_helper
|
369
381
|
requirement: !ruby/object:Gem::Requirement
|
370
382
|
requirements:
|
371
|
-
- - "
|
383
|
+
- - "~>"
|
372
384
|
- !ruby/object:Gem::Version
|
373
|
-
version:
|
385
|
+
version: '5.0'
|
374
386
|
type: :development
|
375
387
|
prerelease: false
|
376
388
|
version_requirements: !ruby/object:Gem::Requirement
|
377
389
|
requirements:
|
378
|
-
- - "
|
390
|
+
- - "~>"
|
379
391
|
- !ruby/object:Gem::Version
|
380
|
-
version:
|
392
|
+
version: '5.0'
|
381
393
|
- !ruby/object:Gem::Dependency
|
382
394
|
name: rake
|
383
395
|
requirement: !ruby/object:Gem::Requirement
|
@@ -503,6 +515,7 @@ files:
|
|
503
515
|
- lib/bolt/config/options.rb
|
504
516
|
- lib/bolt/config/transport/base.rb
|
505
517
|
- lib/bolt/config/transport/docker.rb
|
518
|
+
- lib/bolt/config/transport/jail.rb
|
506
519
|
- lib/bolt/config/transport/local.rb
|
507
520
|
- lib/bolt/config/transport/lxd.rb
|
508
521
|
- lib/bolt/config/transport/options.rb
|
@@ -600,6 +613,8 @@ files:
|
|
600
613
|
- lib/bolt/transport/base.rb
|
601
614
|
- lib/bolt/transport/docker.rb
|
602
615
|
- lib/bolt/transport/docker/connection.rb
|
616
|
+
- lib/bolt/transport/jail.rb
|
617
|
+
- lib/bolt/transport/jail/connection.rb
|
603
618
|
- lib/bolt/transport/local.rb
|
604
619
|
- lib/bolt/transport/local/connection.rb
|
605
620
|
- lib/bolt/transport/lxd.rb
|
@@ -634,7 +649,6 @@ files:
|
|
634
649
|
- lib/bolt_server/schemas/action-run_script.json
|
635
650
|
- lib/bolt_server/schemas/action-run_task.json
|
636
651
|
- lib/bolt_server/schemas/action-upload_file.json
|
637
|
-
- lib/bolt_server/schemas/connect-data.json
|
638
652
|
- lib/bolt_server/schemas/partials/target-any.json
|
639
653
|
- lib/bolt_server/schemas/partials/target-ssh.json
|
640
654
|
- lib/bolt_server/schemas/partials/target-winrm.json
|
@@ -690,7 +704,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
690
704
|
- !ruby/object:Gem::Version
|
691
705
|
version: '0'
|
692
706
|
requirements: []
|
693
|
-
rubygems_version: 3.
|
707
|
+
rubygems_version: 3.1.6
|
694
708
|
signing_key:
|
695
709
|
specification_version: 4
|
696
710
|
summary: Execute commands remotely over SSH and WinRM
|
@@ -1,25 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
-
"title": "project_inventory_targets connect plugin data",
|
4
|
-
"description": "POST project_inventory_targets connect plugin data",
|
5
|
-
"type": "object",
|
6
|
-
"properties": {
|
7
|
-
"puppet_connect_data": {
|
8
|
-
"type": "object",
|
9
|
-
"patternProperties": {
|
10
|
-
".*": {
|
11
|
-
"type": "object",
|
12
|
-
"properties": {
|
13
|
-
"value": {}
|
14
|
-
},
|
15
|
-
"required": ["value"]
|
16
|
-
}
|
17
|
-
},
|
18
|
-
"additionalProperties": false
|
19
|
-
},
|
20
|
-
"versioned_project": {
|
21
|
-
"type": "string"
|
22
|
-
}
|
23
|
-
},
|
24
|
-
"required": ["puppet_connect_data", "versioned_project"]
|
25
|
-
}
|