hybrid_platforms_conductor 32.13.2 → 32.16.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 +4 -4
- data/CHANGELOG.md +54 -0
- data/README.md +8 -1
- data/bin/get_impacted_nodes +1 -1
- data/bin/setup +6 -1
- data/docs/plugins.md +1 -0
- data/docs/plugins/platform_handler/serverless_chef.md +111 -0
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +13 -1
- data/lib/hybrid_platforms_conductor/connector.rb +4 -2
- data/lib/hybrid_platforms_conductor/deployer.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +535 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +51 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +232 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -0
- data/lib/hybrid_platforms_conductor/nodes_handler.rb +9 -5
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +7 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +23 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +11 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb +17 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/deploy_output_parsing_spec.rb +94 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +317 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/inventory_spec.rb +65 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/packaging_spec.rb +292 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +272 -0
- data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/serverless_chef_helpers.rb +53 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/chef_versions.yml +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json +14 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/policyfiles/test_policy.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/chef_versions.yml +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/data_bags/my_bag/my_item.json +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/nodes/node.json +14 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/policyfiles/test_policy.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/chef_versions.yml +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/cookbooks/hpc_test/recipes/after_run.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/cookbooks/hpc_test/recipes/before_run.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/nodes/node.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/policyfiles/test_policy.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/libraries/default.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/default.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node1.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node2.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_1.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_2.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/config.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node1.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node2.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/libraries/default.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/default.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_1.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_2.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/chef_versions.yml +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/local.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node1.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node2.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_1.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_2.rb +3 -0
- metadata +192 -143
data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module HybridPlatformsConductor
|
|
2
|
+
|
|
3
|
+
module HpcPlugins
|
|
4
|
+
|
|
5
|
+
module PlatformHandler
|
|
6
|
+
|
|
7
|
+
class ServerlessChef < HybridPlatformsConductor::PlatformHandler
|
|
8
|
+
|
|
9
|
+
# Small class that can get a Ruby DSL file and return all DSL calls that have been made to it
|
|
10
|
+
class DslParser
|
|
11
|
+
|
|
12
|
+
# List of calls made by parsing the source file
|
|
13
|
+
# Array
|
|
14
|
+
attr_reader :calls
|
|
15
|
+
|
|
16
|
+
# Constructor
|
|
17
|
+
#
|
|
18
|
+
# Parameters::
|
|
19
|
+
# * *calls* (Array): List of calls to complement [default = []]
|
|
20
|
+
def initialize(calls = [])
|
|
21
|
+
@calls = calls
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Parse a file and get all its DSL calls
|
|
25
|
+
#
|
|
26
|
+
# Parameters::
|
|
27
|
+
# * *source* (String): File to parse
|
|
28
|
+
def parse(source)
|
|
29
|
+
instance_eval(File.read(source))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def method_missing(method_name, *args, &block)
|
|
33
|
+
sub_calls = []
|
|
34
|
+
@calls << {
|
|
35
|
+
method: method_name,
|
|
36
|
+
args: args,
|
|
37
|
+
block: block,
|
|
38
|
+
calls_on_result: sub_calls
|
|
39
|
+
}
|
|
40
|
+
DslParser.new(sub_calls)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
require 'hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser'
|
|
2
|
+
|
|
3
|
+
module HybridPlatformsConductor
|
|
4
|
+
|
|
5
|
+
module HpcPlugins
|
|
6
|
+
|
|
7
|
+
module PlatformHandler
|
|
8
|
+
|
|
9
|
+
class ServerlessChef < HybridPlatformsConductor::PlatformHandler
|
|
10
|
+
|
|
11
|
+
# Build the recipes tree from a ServerlessChef platform
|
|
12
|
+
class RecipesTreeBuilder
|
|
13
|
+
|
|
14
|
+
# Constructor
|
|
15
|
+
#
|
|
16
|
+
# Parameters::
|
|
17
|
+
# * *config* (Config): Configuration that can be used to tune tree building
|
|
18
|
+
# * *platform* (ServerlessChef): Platform for which we build the recipes tree
|
|
19
|
+
def initialize(config, platform)
|
|
20
|
+
@config = config
|
|
21
|
+
@platform = platform
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Get the whole tree of recipes
|
|
25
|
+
#
|
|
26
|
+
# Result::
|
|
27
|
+
# * The tree of recipes:
|
|
28
|
+
# Hash< Symbol, Hash< Symbol, Hash<Symbol,Object> >
|
|
29
|
+
# Hash< cookbook, Hash< recipe, recipe_info >
|
|
30
|
+
# Each recipe info has the following attributes:
|
|
31
|
+
# * *included_recipes* (Array< [String or nil, Symbol, Symbol] >): List of [cookbook_dir, cookbook, recipe] included by this recipe
|
|
32
|
+
# * *used_by_policies* (Array<String>): List of policies that include (recursively) this recipe
|
|
33
|
+
# * *used_templates* (Array<String>): List of template sources used by this recipe
|
|
34
|
+
# * *used_files* (Array<String>): List of cookbook files used by this recipe
|
|
35
|
+
# * *used_cookbooks* (Array<Symbol>): List of additional used cookbooks (for example for resources)
|
|
36
|
+
def full_recipes_tree
|
|
37
|
+
@recipes_tree = {}
|
|
38
|
+
@platform.deployable_services.each do |service|
|
|
39
|
+
@platform.policy_run_list(service).each do |(cookbook_dir, cookbook, recipe)|
|
|
40
|
+
add_recipe_in_tree(cookbook_dir, cookbook, recipe)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
@platform.deployable_services.each do |service|
|
|
44
|
+
@platform.policy_run_list(service).each do |(cookbook_dir, cookbook, recipe)|
|
|
45
|
+
mark_recipe_used_by_policy(cookbook, recipe, service)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
@recipes_tree
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# Fill the tree with a recipe and all its dependencies
|
|
54
|
+
#
|
|
55
|
+
# Parameters::
|
|
56
|
+
# * *cookbook_dir* (String): The cookbook directory, or nil if unknown
|
|
57
|
+
# * *cookbook* (Symbol): The cookbook name
|
|
58
|
+
# * *recipe* (Symbol): The recipe name
|
|
59
|
+
def add_recipe_in_tree(cookbook_dir, cookbook, recipe)
|
|
60
|
+
@recipes_tree[cookbook] = {} unless @recipes_tree.key?(cookbook)
|
|
61
|
+
unless @recipes_tree[cookbook].key?(recipe)
|
|
62
|
+
recipe_info =
|
|
63
|
+
if cookbook_dir.nil?
|
|
64
|
+
# This recipe comes from an external cookbook, we won't get into it.
|
|
65
|
+
{
|
|
66
|
+
included_recipes: [],
|
|
67
|
+
used_templates: [],
|
|
68
|
+
used_files: [],
|
|
69
|
+
used_cookbooks: []
|
|
70
|
+
}
|
|
71
|
+
else
|
|
72
|
+
recipe_usage(cookbook_dir, cookbook, recipe)
|
|
73
|
+
end
|
|
74
|
+
@recipes_tree[cookbook][recipe] = recipe_info.merge(
|
|
75
|
+
used_by_policies: []
|
|
76
|
+
)
|
|
77
|
+
recipe_info[:included_recipes].each do |(sub_cookbook_dir, sub_cookbook, sub_recipe)|
|
|
78
|
+
add_recipe_in_tree(sub_cookbook_dir, sub_cookbook, sub_recipe)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Get some info on a given recipe.
|
|
84
|
+
# Parses for:
|
|
85
|
+
# * include_recipe.
|
|
86
|
+
# * source of template and cookbook_file.
|
|
87
|
+
# * Any library helper we know use some recipes.
|
|
88
|
+
# * Any resource we have defined in other cookbooks.
|
|
89
|
+
# * Any library method we have defined in other cookbooks.
|
|
90
|
+
#
|
|
91
|
+
# Parameters::
|
|
92
|
+
# * *cookbook_dir* (String): The cookbook directory
|
|
93
|
+
# * *cookbook* (Symbol): The cookbook name
|
|
94
|
+
# * *recipe* (Symbol): The recipe name
|
|
95
|
+
# Result::
|
|
96
|
+
# * Hash<Symbol,Object>: A structure describing the recipe:
|
|
97
|
+
# * *included_recipes* (Array< [String, Symbol, Symbol] >): List of tuples [cookbook_dir, cookbook, recipe] used by this recipe
|
|
98
|
+
# * *used_templates* (Array<String>): List of template sources used by this recipe
|
|
99
|
+
# * *used_files* (Array<String>): List of cookbook files used by this recipe
|
|
100
|
+
# * *used_cookbooks* (Array<String>): List of additional cookbooks used by this recipe
|
|
101
|
+
def recipe_usage(cookbook_dir, cookbook, recipe)
|
|
102
|
+
recipe_content = File.read("#{@platform.repository_path}/#{cookbook_dir}/#{cookbook}/recipes/#{recipe}.rb")
|
|
103
|
+
# Check for include_recipe
|
|
104
|
+
used_recipes = recipe_content.
|
|
105
|
+
scan(/include_recipe\s+["'](\w+(::\w+)?)["']/).
|
|
106
|
+
map { |(recipe_def, _sub_grp)| @platform.decode_recipe(recipe_def) }
|
|
107
|
+
# Check for some helpers we know include some recipes
|
|
108
|
+
@config.known_helpers_including_recipes.each do |helper_name, used_recipes_by_helper|
|
|
109
|
+
if recipe_content =~ Regexp.new(/(\W|^)#{Regexp.escape(helper_name)}(\W|$)/)
|
|
110
|
+
used_recipes.concat(used_recipes_by_helper.map { |recipe_def| @platform.decode_recipe(recipe_def) })
|
|
111
|
+
used_recipes.uniq!
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
sources = []
|
|
115
|
+
recipe_content.
|
|
116
|
+
scan(/source\s+(["'])(.+?)\1/).
|
|
117
|
+
each do |(_sub_grp, source)|
|
|
118
|
+
sources << source unless source =~ /^https?:\/\//
|
|
119
|
+
end
|
|
120
|
+
erb_sources = sources.select { |source| File.extname(source).downcase == '.erb' }
|
|
121
|
+
non_erb_sources = sources - erb_sources
|
|
122
|
+
erb_sources.concat(recipe_content.scan(/template:?\s+(["'])(.+?)\1/).map { |(_sub_grp, source)| source })
|
|
123
|
+
# Check for known resources and library methods
|
|
124
|
+
used_cookbooks = []
|
|
125
|
+
known_resources.each do |cookbook, methods|
|
|
126
|
+
used_cookbooks << cookbook if methods.any? { |method_name| recipe_content.include?(method_name) }
|
|
127
|
+
end
|
|
128
|
+
known_library_methods.each do |cookbook, methods|
|
|
129
|
+
used_cookbooks << cookbook if methods.any? { |method_name| recipe_content.include?(method_name) }
|
|
130
|
+
end
|
|
131
|
+
{
|
|
132
|
+
included_recipes: used_recipes,
|
|
133
|
+
used_templates: erb_sources,
|
|
134
|
+
used_files: non_erb_sources,
|
|
135
|
+
used_cookbooks: used_cookbooks.uniq
|
|
136
|
+
}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Get the user defined resources, per cookbook.
|
|
140
|
+
# Keep a memory cache of it.
|
|
141
|
+
#
|
|
142
|
+
# Result::
|
|
143
|
+
# * Hash< Symbol, Array<String> >: List of resource names (as useable methods), per cookbook
|
|
144
|
+
def known_resources
|
|
145
|
+
unless defined?(@known_resources)
|
|
146
|
+
@known_resources = {}
|
|
147
|
+
for_each_cookbook do |cookbook, cookbook_dir|
|
|
148
|
+
if File.exist?("#{cookbook_dir}/resources")
|
|
149
|
+
@known_resources[cookbook] = Dir.glob("#{cookbook_dir}/resources/*.rb").map do |resource_file|
|
|
150
|
+
"#{cookbook}_#{File.basename(resource_file, '.rb')}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
@known_resources
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Get the list of library methods we know we have to ignore from the parsing
|
|
159
|
+
# Array<String>
|
|
160
|
+
INVALID_LIBRARY_METHODS = [
|
|
161
|
+
'initialize'
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
# Get the user defined library methods, per cookbook.
|
|
165
|
+
# Keep a memory cache of it.
|
|
166
|
+
#
|
|
167
|
+
# Result::
|
|
168
|
+
# * Hash< Symbol, Array<String> >: List of library method names, per cookbook
|
|
169
|
+
def known_library_methods
|
|
170
|
+
unless defined?(@known_library_methods)
|
|
171
|
+
@known_library_methods = {}
|
|
172
|
+
for_each_cookbook do |cookbook, cookbook_dir|
|
|
173
|
+
if File.exist?("#{cookbook_dir}/libraries")
|
|
174
|
+
found_methods = Dir.glob("#{cookbook_dir}/libraries/*.rb").
|
|
175
|
+
map { |lib_file| File.read(lib_file).scan(/\bdef\s+(\w+)\b/).map { |(method_name)| method_name } }.
|
|
176
|
+
flatten - INVALID_LIBRARY_METHODS
|
|
177
|
+
@known_library_methods[cookbook] = found_methods unless found_methods.empty?
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
@known_library_methods
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Iterate over all cookbooks
|
|
185
|
+
#
|
|
186
|
+
# Parameters::
|
|
187
|
+
# * Proc: Code called for each cookbook:
|
|
188
|
+
# * Parameters::
|
|
189
|
+
# * *cookbook* (Symbol): Cookbook name
|
|
190
|
+
# * *cookbook_dir* (String): Cookbook directory
|
|
191
|
+
def for_each_cookbook
|
|
192
|
+
@platform.known_cookbook_paths.each do |cookbook_path|
|
|
193
|
+
cookbooks_in(cookbook_path).each do |cookbook, cookbook_dir|
|
|
194
|
+
yield cookbook, cookbook_dir
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Get the list of cookbooks of a given cookbook type
|
|
200
|
+
#
|
|
201
|
+
# Parameters::
|
|
202
|
+
# * *cookbook_type* (String): The cookbook type (like site-cookbook)
|
|
203
|
+
# Result::
|
|
204
|
+
# * Hash<Symbol, String>: List of cookbook directories, per cookbook name
|
|
205
|
+
def cookbooks_in(cookbook_type)
|
|
206
|
+
Hash[Dir.glob("#{@platform.repository_path}/#{cookbook_type}/*").map { |dir| [File.basename(dir).to_sym, dir] }.sort]
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Mark a recipe (and its included recipes) as used by a policy
|
|
210
|
+
#
|
|
211
|
+
# Parameters::
|
|
212
|
+
# * *cookbook* (Symbol): The cookbook
|
|
213
|
+
# * *recipe* (Symbol): The recipe
|
|
214
|
+
# * *used_by_policy* (String): The policy using this recipe
|
|
215
|
+
def mark_recipe_used_by_policy(cookbook, recipe, used_by_policy)
|
|
216
|
+
unless @recipes_tree[cookbook][recipe][:used_by_policies].include?(used_by_policy)
|
|
217
|
+
@recipes_tree[cookbook][recipe][:used_by_policies] << used_by_policy
|
|
218
|
+
@recipes_tree[cookbook][recipe][:included_recipes].each do |(_sub_cookbook_dir, sub_cookbook, sub_recipe)|
|
|
219
|
+
mark_recipe_used_by_policy(sub_cookbook, sub_recipe, used_by_policy)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
end
|
|
@@ -269,12 +269,16 @@ module HybridPlatformsConductor
|
|
|
269
269
|
#
|
|
270
270
|
# Parameters::
|
|
271
271
|
# * *node* (String): Node
|
|
272
|
-
# * *property* (Symbol): The property name
|
|
272
|
+
# * *property* (Symbol or nil): The property name, or nil for all [default=nil]
|
|
273
273
|
# Result::
|
|
274
|
-
# * Object or nil: The node's metadata value for this property, or nil if none
|
|
275
|
-
def metadata_of(node, property)
|
|
276
|
-
|
|
277
|
-
|
|
274
|
+
# * Object or nil: The node's metadata value for this property, or nil if none, or a Hash of metadata if property was nil
|
|
275
|
+
def metadata_of(node, property = nil)
|
|
276
|
+
if property.nil?
|
|
277
|
+
@metadata[node] || {}
|
|
278
|
+
else
|
|
279
|
+
prefetch_metadata_of([node], property) unless @metadata.key?(node) && @metadata[node].key?(property)
|
|
280
|
+
@metadata[node][property]
|
|
281
|
+
end
|
|
278
282
|
end
|
|
279
283
|
|
|
280
284
|
# Override a metadata property for a given node
|
|
@@ -35,6 +35,7 @@ require 'hybrid_platforms_conductor_test/helpers/platforms_handler_helpers'
|
|
|
35
35
|
require 'hybrid_platforms_conductor_test/helpers/plugins_helpers'
|
|
36
36
|
require 'hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers'
|
|
37
37
|
require 'hybrid_platforms_conductor_test/helpers/reports_handler_helpers'
|
|
38
|
+
require 'hybrid_platforms_conductor_test/helpers/serverless_chef_helpers'
|
|
38
39
|
require 'hybrid_platforms_conductor_test/helpers/services_handler_helpers'
|
|
39
40
|
require 'hybrid_platforms_conductor_test/helpers/tests_runner_helpers'
|
|
40
41
|
require 'hybrid_platforms_conductor_test/platform_handler_plugins/test'
|
|
@@ -69,6 +70,7 @@ module HybridPlatformsConductorTest
|
|
|
69
70
|
include PluginsHelpers
|
|
70
71
|
include ProvisionerProxmoxHelpers
|
|
71
72
|
include ReportsHandlerHelpers
|
|
73
|
+
include ServerlessChefHelpers
|
|
72
74
|
include ServicesHandlerHelpers
|
|
73
75
|
include TestsRunnerHelpers
|
|
74
76
|
|
|
@@ -95,6 +97,7 @@ module HybridPlatformsConductorTest
|
|
|
95
97
|
ENV.delete 'hpc_domain_for_thycotic'
|
|
96
98
|
ENV.delete 'hpc_certificates'
|
|
97
99
|
ENV.delete 'hpc_interactive'
|
|
100
|
+
ENV.delete 'hpc_test_cookbooks_path'
|
|
98
101
|
# Set the necessary Hybrid Platforms Conductor environment variables
|
|
99
102
|
ENV['hpc_ssh_user'] = 'test_user'
|
|
100
103
|
HybridPlatformsConductor::ServicesHandler.packaged_deployments.clear
|
|
@@ -13,6 +13,13 @@ describe HybridPlatformsConductor::CmdRunner do
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
it 'runs a simple bash command and forces usage of bash' do
|
|
17
|
+
with_repository do |repository|
|
|
18
|
+
# Use set -o pipefail that does not work in /bin/sh
|
|
19
|
+
expect(test_cmd_runner.run_cmd "set -o pipefail ; echo TestStderr 1>&2 ; echo TestStdout", force_bash: true).to eq [0, "TestStdout\n", "TestStderr\n"]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
16
23
|
it 'runs a simple bash command and logs stdout and stderr to a file' do
|
|
17
24
|
with_repository do |repository|
|
|
18
25
|
test_cmd_runner.run_cmd "echo TestStderr 1>&2 ; sleep 1 ; echo TestStdout", log_to_file: "#{repository}/test_file"
|
|
@@ -84,6 +84,29 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
it 'gives a new test instance ready to be used in place of the node without local node' do
|
|
88
|
+
with_test_platform(
|
|
89
|
+
{
|
|
90
|
+
nodes: {
|
|
91
|
+
'node1' => { meta: { local_node: true } },
|
|
92
|
+
'node2' => { meta: { local_node: true } }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
) do |repository|
|
|
96
|
+
register_plugins(:provisioner, { test_provisioner: HybridPlatformsConductorTest::TestProvisioner })
|
|
97
|
+
File.write("#{test_config.hybrid_platforms_dir}/dummy_secrets.json", '{}')
|
|
98
|
+
HybridPlatformsConductorTest::TestProvisioner.mocked_states = %i[created created running exited]
|
|
99
|
+
HybridPlatformsConductorTest::TestProvisioner.mocked_ip = '172.17.0.1'
|
|
100
|
+
expect(Socket).to receive(:tcp).with('172.17.0.1', 22, { connect_timeout: 1 }) do |&block|
|
|
101
|
+
block.call
|
|
102
|
+
end
|
|
103
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node1', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
104
|
+
expect(sub_test_deployer.instance_eval { @nodes_handler.get_local_node_of('node1') }).to eq false
|
|
105
|
+
expect(sub_test_deployer.instance_eval { @nodes_handler.get_local_node_of('node2') }).to eq true
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
87
110
|
it 'gives a new test instance ready to be used in place of the node without sudo specificities' do
|
|
88
111
|
with_test_platform(
|
|
89
112
|
{
|
|
@@ -38,6 +38,17 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
it 'returns nodes currently known metadata using generic method' do
|
|
42
|
+
with_cmdb_test_platform do
|
|
43
|
+
test_nodes_handler.metadata_of('node1', :upcase)
|
|
44
|
+
test_nodes_handler.get_double_of('node1')
|
|
45
|
+
expect(test_nodes_handler.metadata_of('node1')).to eq(
|
|
46
|
+
double: 'node1node1',
|
|
47
|
+
upcase: 'NODE1'
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
41
52
|
it 'returns nodes metadata using dynamic method several times (as the method is created dynamically)' do
|
|
42
53
|
with_cmdb_test_platform do
|
|
43
54
|
3.times { expect(test_nodes_handler.get_upcase_of('node1')).to eq 'NODE1' }
|
data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef do
|
|
2
|
+
|
|
3
|
+
context 'checking config DSL' do
|
|
4
|
+
|
|
5
|
+
it 'defines helpers that include recipes' do
|
|
6
|
+
with_repository do |repository|
|
|
7
|
+
with_platforms('helpers_including_recipes(my_helper: [\'cookbook1::recipe1\', \'cookbook2\'])') do
|
|
8
|
+
expect(test_config.known_helpers_including_recipes).to eq(
|
|
9
|
+
my_helper: %w[cookbook1::recipe1 cookbook2]
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef do
|
|
2
|
+
|
|
3
|
+
context 'checking how deployment output is parsed' do
|
|
4
|
+
|
|
5
|
+
it 'parses a deployment output properly' do
|
|
6
|
+
with_serverless_chef_platforms('empty') do |platform|
|
|
7
|
+
stdout = <<~EOS
|
|
8
|
+
Starting Chef Client, version 14.14.29
|
|
9
|
+
resolving cookbooks for run list: ["policy_xae_websql::xae"]
|
|
10
|
+
Synchronizing Cookbooks:
|
|
11
|
+
- policy_xae_websql (0.1.0)
|
|
12
|
+
- chef-ruby (0.1.2)
|
|
13
|
+
- nginx (10.1.0)
|
|
14
|
+
Installing Cookbook Gems:
|
|
15
|
+
Compiling Cookbooks...
|
|
16
|
+
Recipe: site_debian::default
|
|
17
|
+
* apt_update[apt update] action update
|
|
18
|
+
- force update new lists of packages
|
|
19
|
+
* directory[/etc/apt/apt.conf.d] action create (up to date)
|
|
20
|
+
* file[/etc/apt/apt.conf.d/15update-stamp] action create_if_missing (up to date)
|
|
21
|
+
* execute[apt-get -q update] action run
|
|
22
|
+
- execute ["apt-get", "-q", "update"]
|
|
23
|
+
|
|
24
|
+
Converging 145 resources
|
|
25
|
+
Recipe: policy_xae_websql::api
|
|
26
|
+
* site_artifactory_dpkg_package[xaecalcite] action install
|
|
27
|
+
* remote_file[/opt/chef_cache/xaecalcite_0.2.4-1_amd64.deb] action create
|
|
28
|
+
- create new file /opt/chef_cache/xaecalcite_0.2.4-1_amd64.deb
|
|
29
|
+
- update content in file /opt/chef_cache/xaecalcite_0.2.4-1_amd64.deb from none to 39b0ca
|
|
30
|
+
(file sizes exceed 10000000 bytes, diff output suppressed)
|
|
31
|
+
* dpkg_package[xaecalcite] action install
|
|
32
|
+
- install version 0.2.4-1 of package xaecalcite
|
|
33
|
+
|
|
34
|
+
* service[/var/lib/xaecalcite/xaecalcite.service] action enable (skipped due to not_if)
|
|
35
|
+
|
|
36
|
+
Running handlers:
|
|
37
|
+
Running handlers complete
|
|
38
|
+
Chef Client finished, 16/300 resources updated in 27 seconds
|
|
39
|
+
EOS
|
|
40
|
+
expect(platform.parse_deploy_output(stdout, '')). to eq [
|
|
41
|
+
{
|
|
42
|
+
action: 'update',
|
|
43
|
+
diffs: "force update new lists of packages\n",
|
|
44
|
+
name: 'apt_update[apt update]',
|
|
45
|
+
status: :changed
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
action: 'create (up to date)',
|
|
49
|
+
name: 'directory[/etc/apt/apt.conf.d]',
|
|
50
|
+
status: :identical
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
action: 'create_if_missing (up to date)',
|
|
54
|
+
name: 'file[/etc/apt/apt.conf.d/15update-stamp]',
|
|
55
|
+
status: :identical
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
action: 'run',
|
|
59
|
+
diffs: "execute [\"apt-get\", \"-q\", \"update\"]\n",
|
|
60
|
+
name: 'execute[apt-get -q update]',
|
|
61
|
+
status: :changed
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
action: 'install',
|
|
65
|
+
name: 'site_artifactory_dpkg_package[xaecalcite]',
|
|
66
|
+
status: :identical
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
action: 'create',
|
|
70
|
+
diffs: <<~EOS,
|
|
71
|
+
create new file /opt/chef_cache/xaecalcite_0.2.4-1_amd64.deb
|
|
72
|
+
update content in file /opt/chef_cache/xaecalcite_0.2.4-1_amd64.deb from none to 39b0ca
|
|
73
|
+
EOS
|
|
74
|
+
name: 'remote_file[/opt/chef_cache/xaecalcite_0.2.4-1_amd64.deb]',
|
|
75
|
+
status: :changed
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
action: 'install',
|
|
79
|
+
diffs: "install version 0.2.4-1 of package xaecalcite\n",
|
|
80
|
+
name: 'dpkg_package[xaecalcite]',
|
|
81
|
+
status: :changed
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
action: 'enable (skipped due to not_if)',
|
|
85
|
+
name: 'service[/var/lib/xaecalcite/xaecalcite.service]',
|
|
86
|
+
status: :identical
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|