openbolt 5.0.0.rc1

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.
Files changed (258) hide show
  1. checksums.yaml +7 -0
  2. data/Puppetfile +52 -0
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +60 -0
  4. data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +51 -0
  5. data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
  6. data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +71 -0
  7. data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +55 -0
  8. data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +65 -0
  9. data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +93 -0
  10. data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +33 -0
  11. data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +38 -0
  12. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +208 -0
  13. data/bolt-modules/boltlib/lib/puppet/functions/background.rb +62 -0
  14. data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +57 -0
  15. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +130 -0
  16. data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +31 -0
  17. data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +52 -0
  18. data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +87 -0
  19. data/bolt-modules/boltlib/lib/puppet/functions/get_target.rb +34 -0
  20. data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +35 -0
  21. data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +74 -0
  22. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +97 -0
  23. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +47 -0
  24. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +52 -0
  25. data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +40 -0
  26. data/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +42 -0
  27. data/bolt-modules/boltlib/lib/puppet/functions/resource.rb +53 -0
  28. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +106 -0
  29. data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
  30. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +291 -0
  31. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +145 -0
  32. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +164 -0
  33. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +211 -0
  34. data/bolt-modules/boltlib/lib/puppet/functions/set_config.rb +48 -0
  35. data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +43 -0
  36. data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +145 -0
  37. data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +38 -0
  38. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +101 -0
  39. data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +29 -0
  40. data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +131 -0
  41. data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +59 -0
  42. data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +39 -0
  43. data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +50 -0
  44. data/bolt-modules/boltlib/types/planresult.pp +18 -0
  45. data/bolt-modules/boltlib/types/targetspec.pp +7 -0
  46. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +42 -0
  47. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb +20 -0
  48. data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +35 -0
  49. data/bolt-modules/file/lib/puppet/functions/file/delete.rb +21 -0
  50. data/bolt-modules/file/lib/puppet/functions/file/exists.rb +28 -0
  51. data/bolt-modules/file/lib/puppet/functions/file/join.rb +20 -0
  52. data/bolt-modules/file/lib/puppet/functions/file/read.rb +33 -0
  53. data/bolt-modules/file/lib/puppet/functions/file/readable.rb +28 -0
  54. data/bolt-modules/file/lib/puppet/functions/file/write.rb +24 -0
  55. data/bolt-modules/log/lib/puppet/functions/log/debug.rb +39 -0
  56. data/bolt-modules/log/lib/puppet/functions/log/error.rb +40 -0
  57. data/bolt-modules/log/lib/puppet/functions/log/fatal.rb +40 -0
  58. data/bolt-modules/log/lib/puppet/functions/log/info.rb +39 -0
  59. data/bolt-modules/log/lib/puppet/functions/log/trace.rb +39 -0
  60. data/bolt-modules/log/lib/puppet/functions/log/warn.rb +41 -0
  61. data/bolt-modules/out/lib/puppet/functions/out/message.rb +36 -0
  62. data/bolt-modules/out/lib/puppet/functions/out/verbose.rb +35 -0
  63. data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
  64. data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +65 -0
  65. data/bolt-modules/system/lib/puppet/functions/system/env.rb +20 -0
  66. data/exe/bolt +17 -0
  67. data/guides/debugging.yaml +27 -0
  68. data/guides/inventory.yaml +23 -0
  69. data/guides/links.yaml +12 -0
  70. data/guides/logging.yaml +17 -0
  71. data/guides/module.yaml +18 -0
  72. data/guides/modulepath.yaml +24 -0
  73. data/guides/project.yaml +21 -0
  74. data/guides/targets.yaml +28 -0
  75. data/guides/transports.yaml +22 -0
  76. data/lib/bolt/analytics.rb +233 -0
  77. data/lib/bolt/application.rb +806 -0
  78. data/lib/bolt/applicator.rb +368 -0
  79. data/lib/bolt/apply_inventory.rb +93 -0
  80. data/lib/bolt/apply_result.rb +154 -0
  81. data/lib/bolt/apply_target.rb +90 -0
  82. data/lib/bolt/bolt_option_parser.rb +1226 -0
  83. data/lib/bolt/catalog/logging.rb +15 -0
  84. data/lib/bolt/catalog.rb +144 -0
  85. data/lib/bolt/cli.rb +949 -0
  86. data/lib/bolt/config/modulepath.rb +30 -0
  87. data/lib/bolt/config/options.rb +673 -0
  88. data/lib/bolt/config/transport/base.rb +133 -0
  89. data/lib/bolt/config/transport/docker.rb +34 -0
  90. data/lib/bolt/config/transport/jail.rb +33 -0
  91. data/lib/bolt/config/transport/local.rb +39 -0
  92. data/lib/bolt/config/transport/lxd.rb +34 -0
  93. data/lib/bolt/config/transport/options.rb +431 -0
  94. data/lib/bolt/config/transport/orch.rb +41 -0
  95. data/lib/bolt/config/transport/podman.rb +33 -0
  96. data/lib/bolt/config/transport/remote.rb +24 -0
  97. data/lib/bolt/config/transport/ssh.rb +138 -0
  98. data/lib/bolt/config/transport/winrm.rb +63 -0
  99. data/lib/bolt/config.rb +515 -0
  100. data/lib/bolt/container_result.rb +105 -0
  101. data/lib/bolt/error.rb +194 -0
  102. data/lib/bolt/executor.rb +539 -0
  103. data/lib/bolt/fiber_executor.rb +190 -0
  104. data/lib/bolt/inventory/group.rb +446 -0
  105. data/lib/bolt/inventory/inventory.rb +391 -0
  106. data/lib/bolt/inventory/options.rb +139 -0
  107. data/lib/bolt/inventory/target.rb +293 -0
  108. data/lib/bolt/inventory.rb +120 -0
  109. data/lib/bolt/logger.rb +252 -0
  110. data/lib/bolt/module.rb +54 -0
  111. data/lib/bolt/module_installer/installer.rb +44 -0
  112. data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
  113. data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
  114. data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
  115. data/lib/bolt/module_installer/puppetfile.rb +131 -0
  116. data/lib/bolt/module_installer/resolver.rb +129 -0
  117. data/lib/bolt/module_installer/specs/forge_spec.rb +91 -0
  118. data/lib/bolt/module_installer/specs/git_spec.rb +150 -0
  119. data/lib/bolt/module_installer/specs/id/base.rb +116 -0
  120. data/lib/bolt/module_installer/specs/id/gitclone.rb +120 -0
  121. data/lib/bolt/module_installer/specs/id/github.rb +90 -0
  122. data/lib/bolt/module_installer/specs/id/gitlab.rb +92 -0
  123. data/lib/bolt/module_installer/specs.rb +95 -0
  124. data/lib/bolt/module_installer.rb +208 -0
  125. data/lib/bolt/node/errors.rb +55 -0
  126. data/lib/bolt/node/output.rb +29 -0
  127. data/lib/bolt/outputter/human.rb +958 -0
  128. data/lib/bolt/outputter/json.rb +205 -0
  129. data/lib/bolt/outputter/logger.rb +76 -0
  130. data/lib/bolt/outputter/rainbow.rb +118 -0
  131. data/lib/bolt/outputter.rb +57 -0
  132. data/lib/bolt/pal/issues.rb +19 -0
  133. data/lib/bolt/pal/logging.rb +17 -0
  134. data/lib/bolt/pal/yaml_plan/evaluator.rb +83 -0
  135. data/lib/bolt/pal/yaml_plan/loader.rb +94 -0
  136. data/lib/bolt/pal/yaml_plan/parameter.rb +63 -0
  137. data/lib/bolt/pal/yaml_plan/step/command.rb +45 -0
  138. data/lib/bolt/pal/yaml_plan/step/download.rb +37 -0
  139. data/lib/bolt/pal/yaml_plan/step/eval.rb +42 -0
  140. data/lib/bolt/pal/yaml_plan/step/message.rb +31 -0
  141. data/lib/bolt/pal/yaml_plan/step/plan.rb +42 -0
  142. data/lib/bolt/pal/yaml_plan/step/resources.rb +170 -0
  143. data/lib/bolt/pal/yaml_plan/step/script.rb +62 -0
  144. data/lib/bolt/pal/yaml_plan/step/task.rb +42 -0
  145. data/lib/bolt/pal/yaml_plan/step/upload.rb +37 -0
  146. data/lib/bolt/pal/yaml_plan/step/verbose.rb +31 -0
  147. data/lib/bolt/pal/yaml_plan/step.rb +223 -0
  148. data/lib/bolt/pal/yaml_plan/transpiler.rb +90 -0
  149. data/lib/bolt/pal/yaml_plan.rb +172 -0
  150. data/lib/bolt/pal.rb +847 -0
  151. data/lib/bolt/plan_creator.rb +219 -0
  152. data/lib/bolt/plan_future.rb +86 -0
  153. data/lib/bolt/plan_result.rb +44 -0
  154. data/lib/bolt/plugin/cache.rb +76 -0
  155. data/lib/bolt/plugin/env_var.rb +54 -0
  156. data/lib/bolt/plugin/module.rb +276 -0
  157. data/lib/bolt/plugin/prompt.rb +36 -0
  158. data/lib/bolt/plugin/puppet_connect_data.rb +84 -0
  159. data/lib/bolt/plugin/puppetdb.rb +124 -0
  160. data/lib/bolt/plugin/task.rb +72 -0
  161. data/lib/bolt/plugin.rb +380 -0
  162. data/lib/bolt/project.rb +219 -0
  163. data/lib/bolt/project_manager/config_migrator.rb +113 -0
  164. data/lib/bolt/project_manager/inventory_migrator.rb +67 -0
  165. data/lib/bolt/project_manager/migrator.rb +39 -0
  166. data/lib/bolt/project_manager/module_migrator.rb +203 -0
  167. data/lib/bolt/project_manager.rb +221 -0
  168. data/lib/bolt/puppetdb/client.rb +153 -0
  169. data/lib/bolt/puppetdb/config.rb +176 -0
  170. data/lib/bolt/puppetdb/instance.rb +146 -0
  171. data/lib/bolt/puppetdb.rb +15 -0
  172. data/lib/bolt/r10k_log_proxy.rb +30 -0
  173. data/lib/bolt/rerun.rb +55 -0
  174. data/lib/bolt/resource_instance.rb +133 -0
  175. data/lib/bolt/result.rb +247 -0
  176. data/lib/bolt/result_set.rb +128 -0
  177. data/lib/bolt/shell/bash/tmpdir.rb +62 -0
  178. data/lib/bolt/shell/bash.rb +516 -0
  179. data/lib/bolt/shell/powershell/snippets.rb +181 -0
  180. data/lib/bolt/shell/powershell.rb +365 -0
  181. data/lib/bolt/shell.rb +105 -0
  182. data/lib/bolt/target.rb +174 -0
  183. data/lib/bolt/task/puppet_server.rb +27 -0
  184. data/lib/bolt/task/run.rb +55 -0
  185. data/lib/bolt/task.rb +163 -0
  186. data/lib/bolt/transport/base.rb +252 -0
  187. data/lib/bolt/transport/docker/connection.rb +150 -0
  188. data/lib/bolt/transport/docker.rb +23 -0
  189. data/lib/bolt/transport/jail/connection.rb +81 -0
  190. data/lib/bolt/transport/jail.rb +21 -0
  191. data/lib/bolt/transport/local/connection.rb +106 -0
  192. data/lib/bolt/transport/local.rb +20 -0
  193. data/lib/bolt/transport/lxd/connection.rb +115 -0
  194. data/lib/bolt/transport/lxd.rb +26 -0
  195. data/lib/bolt/transport/orch/connection.rb +111 -0
  196. data/lib/bolt/transport/orch.rb +271 -0
  197. data/lib/bolt/transport/podman/connection.rb +102 -0
  198. data/lib/bolt/transport/podman.rb +19 -0
  199. data/lib/bolt/transport/remote.rb +41 -0
  200. data/lib/bolt/transport/simple.rb +54 -0
  201. data/lib/bolt/transport/ssh/connection.rb +321 -0
  202. data/lib/bolt/transport/ssh/exec_connection.rb +140 -0
  203. data/lib/bolt/transport/ssh.rb +48 -0
  204. data/lib/bolt/transport/winrm/connection.rb +378 -0
  205. data/lib/bolt/transport/winrm.rb +33 -0
  206. data/lib/bolt/util/format.rb +68 -0
  207. data/lib/bolt/util/puppet_log_level.rb +21 -0
  208. data/lib/bolt/util.rb +465 -0
  209. data/lib/bolt/validator.rb +227 -0
  210. data/lib/bolt/version.rb +5 -0
  211. data/lib/bolt.rb +8 -0
  212. data/lib/bolt_server/acl.rb +39 -0
  213. data/lib/bolt_server/base_config.rb +112 -0
  214. data/lib/bolt_server/config.rb +64 -0
  215. data/lib/bolt_server/file_cache.rb +200 -0
  216. data/lib/bolt_server/request_error.rb +11 -0
  217. data/lib/bolt_server/schemas/action-check_node_connections.json +14 -0
  218. data/lib/bolt_server/schemas/action-run_command.json +12 -0
  219. data/lib/bolt_server/schemas/action-run_script.json +47 -0
  220. data/lib/bolt_server/schemas/action-run_task.json +20 -0
  221. data/lib/bolt_server/schemas/action-upload_file.json +47 -0
  222. data/lib/bolt_server/schemas/partials/target-any.json +10 -0
  223. data/lib/bolt_server/schemas/partials/target-ssh.json +88 -0
  224. data/lib/bolt_server/schemas/partials/target-winrm.json +67 -0
  225. data/lib/bolt_server/schemas/partials/task.json +94 -0
  226. data/lib/bolt_server/schemas/transport-ssh.json +25 -0
  227. data/lib/bolt_server/schemas/transport-winrm.json +19 -0
  228. data/lib/bolt_server/transport_app.rb +554 -0
  229. data/lib/bolt_spec/bolt_context.rb +226 -0
  230. data/lib/bolt_spec/plans/action_stubs/command_stub.rb +51 -0
  231. data/lib/bolt_spec/plans/action_stubs/download_stub.rb +66 -0
  232. data/lib/bolt_spec/plans/action_stubs/plan_stub.rb +55 -0
  233. data/lib/bolt_spec/plans/action_stubs/script_stub.rb +59 -0
  234. data/lib/bolt_spec/plans/action_stubs/task_stub.rb +57 -0
  235. data/lib/bolt_spec/plans/action_stubs/upload_stub.rb +65 -0
  236. data/lib/bolt_spec/plans/action_stubs.rb +196 -0
  237. data/lib/bolt_spec/plans/mock_executor.rb +361 -0
  238. data/lib/bolt_spec/plans/publish_stub.rb +49 -0
  239. data/lib/bolt_spec/plans.rb +190 -0
  240. data/lib/bolt_spec/run.rb +246 -0
  241. data/lib/logging_extensions/logging.rb +13 -0
  242. data/libexec/apply_catalog.rb +130 -0
  243. data/libexec/bolt_catalog +68 -0
  244. data/libexec/custom_facts.rb +63 -0
  245. data/libexec/query_resources.rb +75 -0
  246. data/modules/aggregate/lib/puppet/functions/aggregate/count.rb +21 -0
  247. data/modules/aggregate/lib/puppet/functions/aggregate/nodes.rb +22 -0
  248. data/modules/aggregate/lib/puppet/functions/aggregate/targets.rb +21 -0
  249. data/modules/aggregate/plans/count.pp +56 -0
  250. data/modules/aggregate/plans/targets.pp +56 -0
  251. data/modules/canary/lib/puppet/functions/canary/merge.rb +13 -0
  252. data/modules/canary/lib/puppet/functions/canary/random_split.rb +22 -0
  253. data/modules/canary/lib/puppet/functions/canary/skip.rb +25 -0
  254. data/modules/canary/plans/init.pp +100 -0
  255. data/modules/puppet_connect/plans/test_input_data.pp +94 -0
  256. data/modules/puppetdb_fact/plans/init.pp +20 -0
  257. data/resources/bolt_bash_completion.sh +214 -0
  258. metadata +735 -0
@@ -0,0 +1,391 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../bolt/inventory/group'
4
+ require_relative '../../bolt/inventory/target'
5
+
6
+ module Bolt
7
+ class Inventory
8
+ class Inventory
9
+ attr_reader :plugins, :source, :targets, :transport
10
+
11
+ # Getting targets from the inventory using '--targets' supports extended glob pattern
12
+ # matching. In this case, use the extended regex so Bolt only uses commas outside
13
+ # brackets and braces as delimiters.
14
+ EXTENDED_TARGET_REGEX = /[[:space:],]+(?=[^\]}]*(?:[\[{]|$))/.freeze
15
+ TARGET_REGEX = /[[:space:],]+/.freeze
16
+
17
+ # Pattern which looks for indicators that glob-based target name matching
18
+ # should be used.
19
+ GLOB_MATCH_REGEX = /[*?\[\]{}]/.freeze
20
+
21
+ class WildcardError < Bolt::Error
22
+ def initialize(target)
23
+ super("Found 0 targets matching wildcard pattern #{target}", 'bolt.inventory/wildcard-error')
24
+ end
25
+ end
26
+
27
+ def initialize(data, transport, transports, plugins, source = nil)
28
+ @logger = Bolt::Logger.logger(self)
29
+ @data = data || {}
30
+ @transport = transport
31
+ @config = transports
32
+ @config_resolved = transports.values.all?(&:resolved?)
33
+ @plugins = plugins
34
+ @targets = {}
35
+ @source = source
36
+ end
37
+
38
+ def version
39
+ 2
40
+ end
41
+
42
+ def target_implementation_class
43
+ Bolt::Target
44
+ end
45
+
46
+ # Load and resolve the groups in the inventory. Loading groups resolves
47
+ # all plugin references except for those for target data and config.
48
+ #
49
+ # @return [Bolt::Inventory::Group]
50
+ #
51
+ def groups
52
+ @groups ||= Group.new(@data, @plugins, all_group: true).tap do |groups|
53
+ groups.resolve_string_targets(groups.target_aliases, groups.all_targets)
54
+ groups.validate
55
+ end
56
+ end
57
+
58
+ # Return a list of all group names in the inventory.
59
+ #
60
+ # @return [Array[String]]
61
+ #
62
+ def group_names
63
+ group_lookup.keys
64
+ end
65
+
66
+ # Return a map of all groups in the inventory.
67
+ #
68
+ # @return [Hash[String, Bolt::Inventory::Group]]
69
+ #
70
+ def group_lookup
71
+ @group_lookup ||= groups.collect_groups
72
+ end
73
+
74
+ # Return a map of transport configuration for the inventory. Any
75
+ # unresolved plugin references are resolved.
76
+ #
77
+ # @return [Hash[String, Bolt::Config::Transport]]
78
+ #
79
+ def config
80
+ if @config_resolved
81
+ @config
82
+ else
83
+ @config_resolved = true
84
+ @config.each_value { |t| t.resolve(@plugins) unless t.resolved? }
85
+ end
86
+ end
87
+
88
+ def group_names_for(target_name)
89
+ group_data_for(target_name).fetch('groups', [])
90
+ end
91
+
92
+ def target_names
93
+ groups.all_targets
94
+ end
95
+ # alias for analytics
96
+ alias node_names target_names
97
+
98
+ def get_targets(targets, ext_glob: false)
99
+ target_array = expand_targets(targets, ext_glob: ext_glob)
100
+ if target_array.is_a? Array
101
+ target_array.flatten.uniq(&:name)
102
+ else
103
+ [target_array]
104
+ end
105
+ end
106
+
107
+ def get_target(target)
108
+ target_array = get_targets(target)
109
+ if target_array.count > 1
110
+ raise ValidationError.new("'#{target}' refers to #{target_array.count} targets", nil)
111
+ end
112
+ target_array.first
113
+ end
114
+
115
+ #### PRIVATE ####
116
+ def group_data_for(target_name)
117
+ groups.group_collect(target_name)
118
+ end
119
+
120
+ # Does a target match the glob-style wildcard?
121
+ # Ignore case; use extended globs ({a,b}) when running from the CLI.
122
+ def match_wildcard?(wildcard, target_name, ext_glob: false)
123
+ if ext_glob
124
+ File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD | File::FNM_EXTGLOB)
125
+ else
126
+ File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD)
127
+ end
128
+ end
129
+
130
+ # If target is a group name, expand it to the members of that group.
131
+ # Else match against groups and targets in inventory by name or alias.
132
+ # Attempt exact matches for groups, targets, and aliases first for speed.
133
+ # If no exact match and the string contains wildcard characters, then check
134
+ # and see if the target string might be a URI, if it parses as a URI with
135
+ # a scheme then return as-is, otherwise look for a wildcard match and
136
+ # error if no matches are found.
137
+ # Else fall back to [target] if no matches are found.
138
+ def resolve_name(target, ext_glob: false)
139
+ if (group = group_lookup[target])
140
+ group.all_targets.to_a
141
+ elsif @targets.key?(target)
142
+ [target]
143
+ elsif (real_target = groups.target_aliases[target])
144
+ [real_target]
145
+ elsif GLOB_MATCH_REGEX.match?(target)
146
+ # URIs and glob wildcards have some overlapping characters. If the target
147
+ # being resolved parses as a valid target URI and has a scheme defined then
148
+ # return it as-is and do not try to do further wildcard matching:
149
+ uri = begin
150
+ Bolt::Inventory::Target.parse_uri(target)
151
+ rescue Bolt::ParseError
152
+ nil
153
+ end
154
+ return [target] if uri&.scheme
155
+
156
+ targets = []
157
+
158
+ # Find groups that match the glob
159
+ group_lookup.each do |name, grp|
160
+ next unless match_wildcard?(target, name, ext_glob: ext_glob)
161
+ targets += grp.all_targets.to_a
162
+ end
163
+
164
+ # Find target names that match the glob
165
+ targets += groups.all_targets.select { |targ| match_wildcard?(target, targ, ext_glob: ext_glob) }
166
+
167
+ # Find target aliases that match the glob
168
+ targets += groups.target_aliases
169
+ .select { |tgt_alias, _| match_wildcard?(target, tgt_alias, ext_glob: ext_glob) }
170
+ .values
171
+
172
+ raise(WildcardError, target) if targets.empty?
173
+
174
+ targets.uniq
175
+ else # rubocop:disable Lint/DuplicateBranch
176
+ [target]
177
+ end
178
+ end
179
+ private :resolve_name
180
+
181
+ def expand_targets(targets, ext_glob: false)
182
+ case targets
183
+ when Bolt::Target
184
+ targets
185
+ when Array
186
+ targets.map { |tish| expand_targets(tish, ext_glob: ext_glob) }
187
+ when String
188
+ # Expand a comma-separated list
189
+ # Regex magic below is required to workaround `{foo,bar}` glob syntax
190
+ regex = ext_glob ? EXTENDED_TARGET_REGEX : TARGET_REGEX
191
+ targets.split(regex).reject(&:empty?).map do |name|
192
+ ts = resolve_name(name, ext_glob: ext_glob)
193
+ ts.map do |t|
194
+ # If the target doesn't exist, evaluate it from the inventory.
195
+ # Then return a Bolt::Target.
196
+ unless @targets.key?(t)
197
+ @targets[t] = create_target_from_inventory(t)
198
+ end
199
+ Bolt::Target.new(t, self)
200
+ end
201
+ end
202
+ end
203
+ end
204
+ private :expand_targets
205
+
206
+ def remove_target(current_group, target, desired_group)
207
+ if current_group.name == desired_group
208
+ current_group.remove_target(target)
209
+ target.invalidate_group_cache!
210
+ end
211
+ current_group.groups.each do |child_group|
212
+ # If target was in current group, remove it from all child groups
213
+ if current_group.name == desired_group
214
+ remove_target(child_group, target, child_group.name)
215
+ else
216
+ remove_target(child_group, target, desired_group)
217
+ end
218
+ end
219
+ end
220
+ private :remove_target
221
+
222
+ def add_target(current_group, target, desired_group)
223
+ if current_group.name == desired_group
224
+ current_group.add_target(target)
225
+ target.invalidate_group_cache!
226
+ return true
227
+ end
228
+ # Recurse on children Groups if not desired_group
229
+ current_group.groups.each do |child_group|
230
+ add_target(child_group, target, desired_group)
231
+ end
232
+ end
233
+ private :add_target
234
+
235
+ # Pull in a target definition from the inventory file and evaluate any
236
+ # associated references. This is used when a target is resolved by
237
+ # get_targets.
238
+ def create_target_from_inventory(target_name)
239
+ target_data = groups.target_collect(target_name) || { 'uri' => target_name }
240
+
241
+ target = Bolt::Inventory::Target.new(target_data, self)
242
+ @targets[target.name] = target
243
+
244
+ add_to_group([target], 'all')
245
+
246
+ target
247
+ end
248
+
249
+ # Add a brand new target, overriding any existing target with the same
250
+ # name. This method does not honor target config from the inventory. This
251
+ # is used when Target.new is called from a plan or with a data hash.
252
+ def create_target_from_hash(data)
253
+ # If target already exists, delete old and replace with new, otherwise add to new to all group
254
+ new_target = Bolt::Inventory::Target.new(data, self)
255
+ existing_target = @targets.key?(new_target.name)
256
+
257
+ validate_target_from_hash(new_target)
258
+ @targets[new_target.name] = new_target
259
+
260
+ if existing_target
261
+ clear_alia_from_group(groups, new_target.name)
262
+ else
263
+ add_to_group([new_target], 'all')
264
+ end
265
+
266
+ if new_target.target_alias
267
+ groups.insert_alia(new_target.name, Array(new_target.target_alias))
268
+ end
269
+
270
+ new_target
271
+ end
272
+
273
+ def validate_target_from_hash(target)
274
+ used_groups = Set.new(group_names)
275
+ used_targets = target_names
276
+
277
+ # Make sure there are no group name conflicts
278
+ if used_groups.include?(target.name)
279
+ raise ValidationError.new("Target name #{target.name} conflicts with group of the same name", nil)
280
+ end
281
+
282
+ # Validate any aliases
283
+ if (aliases = target.target_alias)
284
+ unless aliases.is_a?(Array) || aliases.is_a?(String)
285
+ msg = "Alias entry on #{t_name} must be a String or Array, not #{aliases.class}"
286
+ raise ValidationError.new(msg, @name)
287
+ end
288
+ end
289
+
290
+ # Make sure there are no conflicts with the new target aliases
291
+ used_aliases = groups.target_aliases
292
+ Array(target.target_alias).each do |alia|
293
+ if used_groups.include?(alia)
294
+ raise ValidationError.new("Alias #{alia} conflicts with group of the same name", nil)
295
+ elsif used_targets.include?(alia)
296
+ raise ValidationError.new("Alias #{alia} conflicts with target of the same name", nil)
297
+ elsif used_aliases[alia] && used_aliases[alia] != target.name
298
+ raise ValidationError.new(
299
+ "Alias #{alia} refers to multiple targets: #{used_aliases[alia]} and #{target.name}", nil
300
+ )
301
+ end
302
+ end
303
+ end
304
+
305
+ def clear_alia_from_group(group, target_name)
306
+ if group.all_target_names.include?(target_name)
307
+ group.clear_alia(target_name)
308
+ end
309
+ group.groups.each do |grp|
310
+ clear_alia_from_group(grp, target_name)
311
+ end
312
+ end
313
+
314
+ def remove_from_group(target, desired_group)
315
+ unless target.length == 1
316
+ raise ValidationError.new("'remove_from_group' expects a single Target, got #{target.length}", nil)
317
+ end
318
+
319
+ if desired_group == 'all'
320
+ raise ValidationError.new("Cannot remove Target from Group 'all'", nil)
321
+ end
322
+
323
+ if group_names.include?(desired_group)
324
+ remove_target(groups, @targets[target.first.name], desired_group)
325
+ else
326
+ raise ValidationError.new("Group #{desired_group} does not exist in inventory", nil)
327
+ end
328
+ end
329
+
330
+ def add_to_group(targets, desired_group)
331
+ if group_names.include?(desired_group)
332
+ targets.each do |target|
333
+ # Add the inventory copy of the target
334
+ add_target(groups, @targets[target.name], desired_group)
335
+ end
336
+ else
337
+ raise ValidationError.new("Group #{desired_group} does not exist in inventory", nil)
338
+ end
339
+ end
340
+
341
+ def transport_data_get
342
+ { transport: transport, transports: config.transform_values(&:to_h) }
343
+ end
344
+
345
+ def set_var(target, var_hash)
346
+ @targets[target.name].set_var(var_hash)
347
+ end
348
+
349
+ def vars(target)
350
+ @targets[target.name].vars
351
+ end
352
+
353
+ def add_facts(target, new_facts = {})
354
+ @targets[target.name].add_facts(new_facts)
355
+ target
356
+ end
357
+
358
+ def facts(target)
359
+ @targets[target.name].facts
360
+ end
361
+
362
+ def set_feature(target, feature, value = true)
363
+ @targets[target.name].set_feature(feature, value)
364
+ end
365
+
366
+ def features(target)
367
+ @targets[target.name].features
368
+ end
369
+
370
+ def plugin_hooks(target)
371
+ @targets[target.name].plugin_hooks
372
+ end
373
+
374
+ def set_config(target, key_or_key_path, value)
375
+ @targets[target.name].set_config(key_or_key_path, value)
376
+ end
377
+
378
+ def target_config(target)
379
+ @targets[target.name].config
380
+ end
381
+
382
+ def resources(target)
383
+ @targets[target.name].resources
384
+ end
385
+
386
+ def resource(target, type, title)
387
+ @targets[target.name].resource(type, title)
388
+ end
389
+ end
390
+ end
391
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../bolt/config/options'
4
+
5
+ module Bolt
6
+ class Inventory
7
+ module Options
8
+ # Top-level options available in the inventory.
9
+ OPTIONS = %w[
10
+ config
11
+ facts
12
+ features
13
+ groups
14
+ plugin_hooks
15
+ targets
16
+ vars
17
+ version
18
+ ].freeze
19
+
20
+ # Definitions used to validate the data.
21
+ # https://github.com/puppetlabs/bolt/blob/main/schemas/README.md
22
+ DEFINITIONS = {
23
+ "alias" => {
24
+ description: "A unique alias to refer to the target. Aliases cannot conflict "\
25
+ "with the name of a group, the name of a target, or another alias.",
26
+ type: [String, Array],
27
+ uniqueItems: true,
28
+ items: {
29
+ type: String,
30
+ _plugin: true
31
+ },
32
+ _plugin: true
33
+ },
34
+ "config" => {
35
+ description: "A map of configuration options.",
36
+ type: Hash,
37
+ # These properties are populated as part of Bolt::Inventory.schema
38
+ properties: {},
39
+ _plugin: true
40
+ },
41
+ "facts" => {
42
+ description: "A map of system information, also known as facts, for the target.",
43
+ type: Hash,
44
+ _plugin: true
45
+ },
46
+ "features" => {
47
+ description: "A list of available features for the target.",
48
+ type: Array,
49
+ uniqueItems: true,
50
+ items: {
51
+ type: String,
52
+ _plugin: true
53
+ },
54
+ _plugin: true
55
+ },
56
+ "groups" => {
57
+ description: "A list of groups and their associated configuration.",
58
+ type: Array,
59
+ items: {
60
+ type: Hash,
61
+ required: ["name"],
62
+ properties: {
63
+ "config" => { _ref: "config" },
64
+ "facts" => { _ref: "facts" },
65
+ "features" => { _ref: "features" },
66
+ "groups" => { _ref: "groups" },
67
+ "name" => { _ref: "name" },
68
+ "plugin_hooks" => { _ref: "plugin_hooks" },
69
+ "targets" => { _ref: "targets" },
70
+ "vars" => { _ref: "vars" }
71
+ },
72
+ _plugin: true
73
+ },
74
+ _plugin: true
75
+ },
76
+ "name" => {
77
+ description: "A human-readable name to refer to the group or target. Names "\
78
+ "cannot conflict with the name of a group, the name of a target, "\
79
+ "or the alias of a target. A name is required for a group and is "\
80
+ "required for a target unless the uri option is set.",
81
+ type: String,
82
+ _plugin: true
83
+ },
84
+ "plugin_hooks" => {
85
+ description: "Configuration for the Puppet library plugin used to install the "\
86
+ "Puppet agent on the target. For more information, see "\
87
+ "https://pup.pt/bolt-plugin-hooks",
88
+ type: Hash,
89
+ properties: {
90
+ "puppet_library" => {
91
+ description: "Configuration for the Puppet library plugin.",
92
+ type: Hash,
93
+ _plugin: true
94
+ }
95
+ },
96
+ _plugin: true
97
+ },
98
+ "targets" => {
99
+ description: "A list of targets and their associated configuration.",
100
+ type: Array,
101
+ items: {
102
+ type: [String, Hash],
103
+ properties: {
104
+ "alias" => { _ref: "alias" },
105
+ "config" => { _ref: "config" },
106
+ "facts" => { _ref: "facts" },
107
+ "features" => { _ref: "features" },
108
+ "name" => { _ref: "name" },
109
+ "plugin_hooks" => { _ref: "plugin_hooks" },
110
+ "uri" => { _ref: "uri" },
111
+ "vars" => { _ref: "vars" }
112
+ },
113
+ _plugin: true
114
+ },
115
+ _plugin: true
116
+ },
117
+ "uri" => {
118
+ description: "The URI of the target. This option is required unless the name "\
119
+ "option is set.",
120
+ type: String,
121
+ format: "uri",
122
+ _plugin: true
123
+ },
124
+ "vars" => {
125
+ description: "A map of variables for the group or target.",
126
+ type: Hash,
127
+ _plugin: true
128
+ },
129
+ "version" => {
130
+ description: "The version of the inventory file.",
131
+ type: Integer,
132
+ _plugin: false,
133
+ _example: 2,
134
+ _default: 2
135
+ }
136
+ }.freeze
137
+ end
138
+ end
139
+ end