hybrid_platforms_conductor 32.13.2 → 32.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -0
  3. data/README.md +8 -1
  4. data/bin/get_impacted_nodes +1 -1
  5. data/bin/setup +6 -1
  6. data/docs/plugins.md +1 -0
  7. data/docs/plugins/platform_handler/serverless_chef.md +111 -0
  8. data/lib/hybrid_platforms_conductor/cmd_runner.rb +13 -1
  9. data/lib/hybrid_platforms_conductor/connector.rb +4 -2
  10. data/lib/hybrid_platforms_conductor/deployer.rb +2 -1
  11. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +1 -1
  12. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +535 -0
  13. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +51 -0
  14. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +232 -0
  15. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -0
  16. data/lib/hybrid_platforms_conductor/nodes_handler.rb +9 -5
  17. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  18. data/spec/hybrid_platforms_conductor_test.rb +3 -0
  19. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +7 -0
  20. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +23 -0
  21. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +11 -0
  22. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb +17 -0
  23. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/deploy_output_parsing_spec.rb +94 -0
  24. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +317 -0
  25. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/inventory_spec.rb +65 -0
  26. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/packaging_spec.rb +292 -0
  27. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +272 -0
  28. data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +1 -1
  29. data/spec/hybrid_platforms_conductor_test/helpers/serverless_chef_helpers.rb +53 -0
  30. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/chef_versions.yml +3 -0
  31. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json +14 -0
  32. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/policyfiles/test_policy.rb +3 -0
  33. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/chef_versions.yml +3 -0
  34. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/data_bags/my_bag/my_item.json +4 -0
  35. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/nodes/node.json +14 -0
  36. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/policyfiles/test_policy.rb +3 -0
  37. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/chef_versions.yml +3 -0
  38. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/cookbooks/hpc_test/recipes/after_run.rb +1 -0
  39. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/cookbooks/hpc_test/recipes/before_run.rb +1 -0
  40. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/nodes/node.json +10 -0
  41. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/policyfiles/test_policy.rb +3 -0
  42. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
  43. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/libraries/default.rb +4 -0
  44. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/default.rb +1 -0
  45. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
  46. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
  47. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node1.json +10 -0
  48. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node2.json +10 -0
  49. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_1.rb +4 -0
  50. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_2.rb +4 -0
  51. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/config.rb +1 -0
  52. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
  53. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node1.json +10 -0
  54. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node2.json +10 -0
  55. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/libraries/default.rb +4 -0
  56. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/default.rb +1 -0
  57. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
  58. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
  59. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_1.rb +4 -0
  60. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_2.rb +4 -0
  61. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/chef_versions.yml +3 -0
  62. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/local.json +10 -0
  63. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node1.json +10 -0
  64. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node2.json +10 -0
  65. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_1.rb +3 -0
  66. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_2.rb +3 -0
  67. metadata +192 -143
@@ -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
@@ -73,6 +73,7 @@ module HybridPlatformsConductor
73
73
  end
74
74
  end
75
75
  cmds = <<~EOS
76
+ set -e
76
77
  #{
77
78
  case image
78
79
  when :centos_7
@@ -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
- prefetch_metadata_of([node], property) unless @metadata.key?(node) && @metadata[node].key?(property)
277
- @metadata[node][property]
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
@@ -1,5 +1,5 @@
1
1
  module HybridPlatformsConductor
2
2
 
3
- VERSION = '32.13.2'
3
+ VERSION = '32.16.0'
4
4
 
5
5
  end
@@ -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' }
@@ -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