hybrid_platforms_conductor 32.13.4 → 32.16.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -0
- 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/provisioner/podman.rb +1 -1
- 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 +293 -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
|
@@ -112,7 +112,7 @@ module HybridPlatformsConductor
|
|
112
112
|
# Result::
|
113
113
|
# * String: The Podman command
|
114
114
|
def podman_cmd
|
115
|
-
@podman_cmd = @cmd_runner.root? ? '
|
115
|
+
@podman_cmd = "#{@cmd_runner.root? ? '' : 'sudo '}podman" unless defined?(@podman_cmd)
|
116
116
|
@podman_cmd
|
117
117
|
end
|
118
118
|
|
@@ -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
|