hybrid_platforms_conductor 33.8.3 → 33.9.2
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 +48 -0
- data/bin/nodes_to_deploy +19 -9
- data/docs/config_dsl.md +10 -4
- data/lib/hybrid_platforms_conductor/deployer.rb +7 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +94 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +4 -18
- data/lib/hybrid_platforms_conductor/platform_handler.rb +17 -7
- data/lib/hybrid_platforms_conductor/platforms_handler.rb +9 -7
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +44 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +9 -4
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +53 -0
- data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +43 -13
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +75 -0
- data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +4 -2
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +2 -1
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/metadata.rb +13 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/31_unknown_recipe_include.rb +2 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/32_unknown_cookbook_include.rb +2 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/33_unknown_include.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/34_known_include.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/35_unparsable_include.rb +7 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_1.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_2.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_3.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_4.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_5/recipes/recipe_1.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_5/recipes/recipe_2.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node31.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node32.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node33.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node34.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node35.json +10 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_31.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_32.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_33.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_34.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_35.rb +4 -0
- data/spec/hybrid_platforms_conductor_test/test_log_plugin.rb +2 -2
- data/spec/hybrid_platforms_conductor_test.rb +1 -0
- metadata +24 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2a6b91bf179fa45f605d1b08d8c21cced9547c0588139b1998fca01a19f75abe
|
|
4
|
+
data.tar.gz: 5372e49247ba48adf64eed5a9fe3cc5aff5b2e82be8bc834a2283f815cc4c928
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a1d886444be942a74153cb834e450b8062356959aaca508e10186bcb444f63295f8fc198b3e49f94babbbb7b6315bed146c1a29c21ab23d9112de94971e18d11
|
|
7
|
+
data.tar.gz: 31640de82a155dc42128926683fe7ded34039bad1cb639ff6bb8d4571f7f01a191f2103ea6a01c3de60322dc67015e92c833a0e8597b10bb3d6030e10199a864
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,51 @@
|
|
|
1
|
+
# [v33.9.2](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.9.1...v33.9.2) (2021-09-01 17:46:34)
|
|
2
|
+
|
|
3
|
+
## Global changes
|
|
4
|
+
### Patches
|
|
5
|
+
|
|
6
|
+
* [[Fix(nodes_to_deploy)] [#112] Support UTF-8 encoding from log files](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/26a7bd2fd53d387bd972b5e1b60cac9be6541ce5)
|
|
7
|
+
|
|
8
|
+
## Changes for nodes_to_deploy
|
|
9
|
+
### Patches
|
|
10
|
+
|
|
11
|
+
* [[Fix(nodes_to_deploy)] [#112] Support UTF-8 encoding from log files](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/26a7bd2fd53d387bd972b5e1b60cac9be6541ce5)
|
|
12
|
+
|
|
13
|
+
# [v33.9.1](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.9.0...v33.9.1) (2021-09-01 16:59:59)
|
|
14
|
+
|
|
15
|
+
## Global changes
|
|
16
|
+
### Patches
|
|
17
|
+
|
|
18
|
+
* [[Fix(nodes_to_deploy)] [#110] Make sure unknown platforms are taken into account when detecting nodes to be deployed](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/c1b8312c5d473a1c5d044f6cda3ad9bed2b3ca61)
|
|
19
|
+
|
|
20
|
+
## Changes for nodes_to_deploy
|
|
21
|
+
### Patches
|
|
22
|
+
|
|
23
|
+
* [[Fix(nodes_to_deploy)] [#110] Make sure unknown platforms are taken into account when detecting nodes to be deployed](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/c1b8312c5d473a1c5d044f6cda3ad9bed2b3ca61)
|
|
24
|
+
|
|
25
|
+
# [v33.9.0](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.8.4...v33.9.0) (2021-08-24 13:15:44)
|
|
26
|
+
|
|
27
|
+
## Global changes
|
|
28
|
+
### Patches
|
|
29
|
+
|
|
30
|
+
* [[Feature(platform_handler)] [#102] Add the name option when declaring platforms to set the platform name](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/13ada7687f08b3f970521320e2b26ea42d9a6d7f)
|
|
31
|
+
|
|
32
|
+
## Changes for platform_handler
|
|
33
|
+
### Features
|
|
34
|
+
|
|
35
|
+
* [[Feature(platform_handler)] [#102] Add the name option when declaring platforms to set the platform name](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/13ada7687f08b3f970521320e2b26ea42d9a6d7f)
|
|
36
|
+
|
|
37
|
+
# [v33.8.4](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.8.3...v33.8.4) (2021-08-20 15:45:41)
|
|
38
|
+
|
|
39
|
+
## Global changes
|
|
40
|
+
### Patches
|
|
41
|
+
|
|
42
|
+
* [[Fix(platform_handler_serverless_chef)] [#99] Make sure dynamic or unparsable cookbook/recipe names are considered using metadata for recipes dependencies](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/1d7feb24881f04cd3f31bc1e41712dfc4cfe715f)
|
|
43
|
+
|
|
44
|
+
## Changes for platform_handler_serverless_chef
|
|
45
|
+
### Patches
|
|
46
|
+
|
|
47
|
+
* [[Fix(platform_handler_serverless_chef)] [#99] Make sure dynamic or unparsable cookbook/recipe names are considered using metadata for recipes dependencies](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/1d7feb24881f04cd3f31bc1e41712dfc4cfe715f)
|
|
48
|
+
|
|
1
49
|
# [v33.8.3](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.8.2...v33.8.3) (2021-08-16 14:18:52)
|
|
2
50
|
|
|
3
51
|
## Global changes
|
data/bin/nodes_to_deploy
CHANGED
|
@@ -17,6 +17,7 @@ executable = HybridPlatformsConductor::Executable.new(deploy_options: false) do
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
nodes_handler = executable.nodes_handler
|
|
20
|
+
platforms_handler = executable.platforms_handler
|
|
20
21
|
deployer = executable.deployer
|
|
21
22
|
|
|
22
23
|
executable.parse_options!
|
|
@@ -72,20 +73,29 @@ unless ignore_deploy_info
|
|
|
72
73
|
commit_id = node_deploy_info[:deployment_info]["commit_id_#{repo_idx}".to_sym]
|
|
73
74
|
impacted_nodes = cache_impacted_nodes.dig(repo_name, commit_id)
|
|
74
75
|
if impacted_nodes.nil?
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
if platforms_handler.platform(repo_name)
|
|
77
|
+
begin
|
|
78
|
+
impacted_nodes, _single_impacted_nodes, _impacted_services, _impact_global = nodes_handler.impacted_nodes_from_git_diff(
|
|
79
|
+
repo_name,
|
|
80
|
+
from_commit: commit_id,
|
|
81
|
+
to_commit: 'master'
|
|
82
|
+
)
|
|
83
|
+
rescue HybridPlatformsConductor::NodesHandler::GitError
|
|
84
|
+
# Consider the node was deployed with a non-release branch commit (as it is missing)
|
|
85
|
+
# So we have to make sure we deploy it again
|
|
86
|
+
executable.log_warn "[ #{node} ] - Unknown commit ID from deployment logs: #{repo_name} / #{commit_id}."
|
|
87
|
+
impacted_nodes = :unknown
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
# Consider the node was deployed with an obdsolete platform (as it is unknown)
|
|
83
91
|
# So we have to make sure we deploy it again
|
|
84
|
-
|
|
92
|
+
executable.log_warn "[ #{node} ] - Unknown platform from deployment logs: #{repo_name}."
|
|
93
|
+
impacted_nodes = :unknown
|
|
85
94
|
end
|
|
86
95
|
cache_impacted_nodes[repo_name] = {} unless cache_impacted_nodes.key?(repo_name)
|
|
87
96
|
cache_impacted_nodes[repo_name][commit_id] = impacted_nodes
|
|
88
97
|
end
|
|
98
|
+
impacted_nodes = [node] if impacted_nodes == :unknown
|
|
89
99
|
if impacted_nodes.include?(node)
|
|
90
100
|
executable.log_debug "[ #{node} ] - Diffs on #{repo_name} between #{commit_id} and master are impacting this node."
|
|
91
101
|
node_impacted = true
|
data/docs/config_dsl.md
CHANGED
|
@@ -28,19 +28,25 @@ This DSL can also be completed by plugins. Check [the plugins documentations](pl
|
|
|
28
28
|
Declare a new platform of type `<platform_type>`, providing either a local path to it (using `path: '/path/to/files'`) or a git repository to it (using `git: 'git_url'`). The possible platform types are the names of the [`platform_handler` plugins](plugins.md#platform_handler).
|
|
29
29
|
|
|
30
30
|
Git branches can also be specified using `branch: 'branch_name'`.
|
|
31
|
+
|
|
32
|
+
The name of the platform (as used for example by the [`for_nodes`](#for_nodes) DSL) defaults to the base name of the directory in case of a local path, or the base name of the first remote in case of a git repository. It can be enforced to a given name using `name: 'platform_name'` (useful to avoid name conflicts and keep consistency with the rest of your configuration among the team).
|
|
33
|
+
|
|
31
34
|
An optional code block taking the local repository path as parameter can also be specified to add configuration that is specific to this platform.
|
|
32
35
|
|
|
33
36
|
Examples:
|
|
34
37
|
```ruby
|
|
35
|
-
# Declare a platform of type Chef, located in a distant git repository
|
|
38
|
+
# Declare a platform of type Chef, located in a distant git repository (its name will be my-chef-repo)
|
|
36
39
|
chef_platform git: 'https://my-git.domain.com/project/my-chef-repo.git'
|
|
37
40
|
|
|
38
|
-
# Declare a platform located in a local path
|
|
39
|
-
chef_platform path: '/path/to/my-chef-repo'
|
|
41
|
+
# Declare a platform located in a local path (its name will be my-other-chef-repo)
|
|
42
|
+
chef_platform path: '/path/to/my-other-chef-repo'
|
|
43
|
+
|
|
44
|
+
# Declare a platform located in a local path and forces its name (its name will be my-platform)
|
|
45
|
+
chef_platform path: '/path/to/my-repo', name: 'my-platform'
|
|
40
46
|
|
|
41
47
|
# Declare a platform from a git branch, and apply some configuration to it
|
|
42
48
|
chef_platform(
|
|
43
|
-
git: 'https://my-git.domain.com/project/
|
|
49
|
+
git: 'https://my-git.domain.com/project/devops-chef-repo.git',
|
|
44
50
|
branch: 'my-branch'
|
|
45
51
|
) do |path|
|
|
46
52
|
# Here path will be a local path containing a checkout of the branch my-branch of the git repo.
|
|
@@ -475,9 +475,15 @@ module HybridPlatformsConductor
|
|
|
475
475
|
progress_name: 'Read deployment logs'
|
|
476
476
|
)
|
|
477
477
|
nodes.map do |node|
|
|
478
|
+
exit_code, stdout, stderr = read_actions_results[node] || [nil, nil, nil]
|
|
478
479
|
[
|
|
479
480
|
node,
|
|
480
|
-
@log_plugins[log_plugins_for(node).first].logs_for(
|
|
481
|
+
@log_plugins[log_plugins_for(node).first].logs_for(
|
|
482
|
+
node,
|
|
483
|
+
exit_code,
|
|
484
|
+
stdout&.force_encoding(Encoding::UTF_8),
|
|
485
|
+
stderr&.force_encoding(Encoding::UTF_8)
|
|
486
|
+
)
|
|
481
487
|
]
|
|
482
488
|
end.to_h
|
|
483
489
|
end
|
|
@@ -105,8 +105,59 @@ module HybridPlatformsConductor
|
|
|
105
105
|
recipe_content = File.read("#{@platform.repository_path}/#{cookbook_dir}/#{cookbook}/recipes/#{recipe}.rb")
|
|
106
106
|
# Check for include_recipe
|
|
107
107
|
used_recipes = recipe_content.
|
|
108
|
-
scan(/include_recipe\
|
|
109
|
-
map
|
|
108
|
+
scan(/include_recipe(\((.+)\)|\s+(.+)|\((.*))$/).
|
|
109
|
+
map do |(_match, match_1, match_2, match_3)|
|
|
110
|
+
case match_1 || match_2 || match_3
|
|
111
|
+
when /^["']([^:'"]+(::[^'"]+)?)["']$/
|
|
112
|
+
# The recipe definition is given in a String
|
|
113
|
+
used_cookbook, used_recipe = Regexp.last_match(1).split('::')
|
|
114
|
+
used_recipe = 'default' if used_recipe.nil?
|
|
115
|
+
if used_cookbook =~ /^\w+$/
|
|
116
|
+
# Find the cookbook it belongs to
|
|
117
|
+
used_cookbook_dir = @platform.known_cookbook_paths.find { |cookbook_path| File.exist?("#{@platform.repository_path}/#{cookbook_path}/#{used_cookbook}") }
|
|
118
|
+
if used_recipe =~ /^\w+$/
|
|
119
|
+
# Check that the recipe exists if we know the cookbook dir
|
|
120
|
+
raise "Unknown recipe #{used_cookbook}::#{used_recipe} from cookbook #{@platform.repository_path}/#{used_cookbook_dir}/#{used_cookbook}." if !used_cookbook_dir.nil? && !File.exist?("#{@platform.repository_path}/#{used_cookbook_dir}/#{used_cookbook}/recipes/#{used_recipe}.rb")
|
|
121
|
+
|
|
122
|
+
[
|
|
123
|
+
[used_cookbook_dir, used_cookbook.to_sym, used_recipe.to_sym]
|
|
124
|
+
]
|
|
125
|
+
elsif used_cookbook_dir
|
|
126
|
+
# We are dealing with a dynamically named recipe.
|
|
127
|
+
# Return all recipes of the cookbook if we know the cookbook dir
|
|
128
|
+
Dir.glob("#{@platform.repository_path}/#{used_cookbook_dir}/#{used_cookbook}/recipes/*.rb").map do |used_recipe_file_path|
|
|
129
|
+
[
|
|
130
|
+
used_cookbook_dir,
|
|
131
|
+
used_cookbook.to_sym,
|
|
132
|
+
File.basename(used_recipe_file_path, '.rb').to_sym
|
|
133
|
+
]
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
# We are dealing with a dynamically named recipe.
|
|
137
|
+
# We have no cookbook dir - certainly comes from the supermarket.
|
|
138
|
+
[]
|
|
139
|
+
end
|
|
140
|
+
elsif used_recipe =~ /^\w+$/
|
|
141
|
+
# We are dealing with a dynamically named cookbook, but the recipe name is known.
|
|
142
|
+
# Look for this recipe in all cookbooks that are part of the metadata.
|
|
143
|
+
dependent_cookbooks(cookbook_dir, cookbook).map do |dependent_cookbook|
|
|
144
|
+
dependent_cookbook_dir = @platform.known_cookbook_paths.find { |cookbook_path| File.exist?("#{@platform.repository_path}/#{cookbook_path}/#{dependent_cookbook}") }
|
|
145
|
+
if !dependent_cookbook_dir.nil? && File.exist?("#{@platform.repository_path}/#{dependent_cookbook_dir}/#{dependent_cookbook}/recipes/#{used_recipe}.rb")
|
|
146
|
+
# Found a matching recipe name
|
|
147
|
+
[dependent_cookbook_dir, dependent_cookbook, used_recipe.to_sym]
|
|
148
|
+
end
|
|
149
|
+
end.compact
|
|
150
|
+
else
|
|
151
|
+
# We are dealing with cynamically named cookbooks and recipes.
|
|
152
|
+
# Consider we depend on all recipes of our dependent cookbooks.
|
|
153
|
+
all_dependent_recipes(cookbook_dir, cookbook)
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
# The recipe definition is much more complex, so treat it as unparsable and consider we depnd on all recipes of our dependent cookbooks from metadata.
|
|
157
|
+
all_dependent_recipes(cookbook_dir, cookbook)
|
|
158
|
+
end
|
|
159
|
+
end.
|
|
160
|
+
flatten(1)
|
|
110
161
|
# Check for some helpers we know include some recipes
|
|
111
162
|
@config.known_helpers_including_recipes.each do |helper_name, used_recipes_by_helper|
|
|
112
163
|
if recipe_content =~ Regexp.new(/(\W|^)#{Regexp.escape(helper_name)}(\W|$)/)
|
|
@@ -222,6 +273,47 @@ module HybridPlatformsConductor
|
|
|
222
273
|
end
|
|
223
274
|
end
|
|
224
275
|
|
|
276
|
+
# Get the list of dependent cookbooks from a cookbook's metadata
|
|
277
|
+
#
|
|
278
|
+
# Parameters::
|
|
279
|
+
# * *cookbook_dir* (String): The cookbook directory
|
|
280
|
+
# * *cookbook* (Symbol): The cookbook name
|
|
281
|
+
# Result::
|
|
282
|
+
# * Array<Symbol>: List of dependent cookbooks
|
|
283
|
+
def dependent_cookbooks(cookbook_dir, cookbook)
|
|
284
|
+
# Read the metadata file
|
|
285
|
+
dsl_parser = DslParser.new
|
|
286
|
+
dsl_parser.parse("#{@platform.repository_path}/#{cookbook_dir}/#{cookbook}/metadata.rb")
|
|
287
|
+
dsl_parser.
|
|
288
|
+
calls.
|
|
289
|
+
map { |call_info| call_info[:method] == :depends ? call_info[:args].first.to_sym : nil }.
|
|
290
|
+
compact
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Get all recipes from all cookbooks that are a metadata dependency from a given cookbook.
|
|
294
|
+
#
|
|
295
|
+
# Parameters::
|
|
296
|
+
# * *cookbook_dir* (String): The cookbook directory
|
|
297
|
+
# * *cookbook* (Symbol): The cookbook name
|
|
298
|
+
# Result::
|
|
299
|
+
# * Array< [String, Symbol, Symbol] >: List of tuples [cookbook_dir, cookbook, recipe] used by this recipe
|
|
300
|
+
def all_dependent_recipes(cookbook_dir, cookbook)
|
|
301
|
+
dependent_cookbooks(cookbook_dir, cookbook).map do |dependent_cookbook|
|
|
302
|
+
dependent_cookbook_dir = @platform.known_cookbook_paths.find { |cookbook_path| File.exist?("#{@platform.repository_path}/#{cookbook_path}/#{dependent_cookbook}") }
|
|
303
|
+
if dependent_cookbook_dir.nil?
|
|
304
|
+
nil
|
|
305
|
+
else
|
|
306
|
+
Dir.glob("#{@platform.repository_path}/#{dependent_cookbook_dir}/#{dependent_cookbook}/recipes/*.rb").map do |used_recipe_file_path|
|
|
307
|
+
[
|
|
308
|
+
dependent_cookbook_dir,
|
|
309
|
+
dependent_cookbook,
|
|
310
|
+
File.basename(used_recipe_file_path, '.rb').to_sym
|
|
311
|
+
]
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end.compact.flatten(1)
|
|
315
|
+
end
|
|
316
|
+
|
|
225
317
|
end
|
|
226
318
|
|
|
227
319
|
end
|
|
@@ -47,24 +47,10 @@ module HybridPlatformsConductor
|
|
|
47
47
|
end
|
|
48
48
|
extend_config_dsl_with MyDSLExtension, :init_serverless_chef
|
|
49
49
|
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
# * *repository_path* (String): Repository path
|
|
55
|
-
# * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
|
|
56
|
-
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
|
57
|
-
# * *config* (Config): Config to be used. [default: Config.new]
|
|
58
|
-
# * *cmd_runner* (CmdRunner): Command executor to be used. [default: CmdRunner.new]
|
|
59
|
-
def initialize(
|
|
60
|
-
platform_type,
|
|
61
|
-
repository_path,
|
|
62
|
-
logger: Logger.new($stdout),
|
|
63
|
-
logger_stderr: Logger.new($stderr),
|
|
64
|
-
config: Config.new,
|
|
65
|
-
cmd_runner: CmdRunner.new
|
|
66
|
-
)
|
|
67
|
-
super
|
|
50
|
+
# Initialize a new instance of this platform handler.
|
|
51
|
+
# [API] - This method is optional.
|
|
52
|
+
# [API] - @cmd_runner is accessible.
|
|
53
|
+
def init
|
|
68
54
|
# Mutex for getting the full recipes tree
|
|
69
55
|
@recipes_tree_mutex = Mutex.new
|
|
70
56
|
end
|
|
@@ -17,13 +17,13 @@ module HybridPlatformsConductor
|
|
|
17
17
|
# Make sure we define automatically a helper for such a platform
|
|
18
18
|
mixin = Module.new
|
|
19
19
|
platform_type = subclass.name.split('::').last.gsub(/([a-z\d])([A-Z\d])/, '\1_\2').downcase.to_sym
|
|
20
|
-
mixin.define_method("#{platform_type}_platform".to_sym) do |path: nil, git: nil, branch: 'master', &platform_config_code|
|
|
20
|
+
mixin.define_method("#{platform_type}_platform".to_sym) do |path: nil, git: nil, branch: 'master', name: nil, &platform_config_code|
|
|
21
21
|
repository_path =
|
|
22
22
|
if !path.nil?
|
|
23
23
|
path
|
|
24
24
|
elsif !git.nil?
|
|
25
25
|
# Clone in a local repository
|
|
26
|
-
local_repository_path = "#{@git_platforms_dir}/#{File.basename(git)[0..-File.extname(git).size - 1]}"
|
|
26
|
+
local_repository_path = "#{@git_platforms_dir}/#{name.nil? ? File.basename(git)[0..-File.extname(git).size - 1] : name}"
|
|
27
27
|
unless File.exist?(local_repository_path)
|
|
28
28
|
branch = "refs/heads/#{branch}" unless branch.include?('/')
|
|
29
29
|
local_ref = "refs/remotes/origin/#{branch.split('/').last}"
|
|
@@ -37,8 +37,10 @@ module HybridPlatformsConductor
|
|
|
37
37
|
else
|
|
38
38
|
raise 'The platform has to be defined with either a path or a git URL'
|
|
39
39
|
end
|
|
40
|
-
@
|
|
41
|
-
@
|
|
40
|
+
@platforms_info[platform_type] = {} unless @platforms_info.key?(platform_type)
|
|
41
|
+
raise "Platform repository path #{repository_path} is declared several times." if @platforms_info.values.any? { |known_platforms_info| known_platforms_info.key?(repository_path) }
|
|
42
|
+
|
|
43
|
+
@platforms_info[platform_type][repository_path] = name.nil? ? {} : { name: name }
|
|
42
44
|
platform_config_code&.call(repository_path)
|
|
43
45
|
end
|
|
44
46
|
# Register this new mixin in the Config DSL
|
|
@@ -66,18 +68,21 @@ module HybridPlatformsConductor
|
|
|
66
68
|
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
|
67
69
|
# * *config* (Config): Config to be used. [default: Config.new]
|
|
68
70
|
# * *cmd_runner* (CmdRunner): Command executor to be used. [default: CmdRunner.new]
|
|
71
|
+
# * *name* (String or nil): Platform name, or nil for defaults (based on path or git remote) [default: nil]
|
|
69
72
|
def initialize(
|
|
70
73
|
platform_type,
|
|
71
74
|
repository_path,
|
|
72
75
|
logger: Logger.new($stdout),
|
|
73
76
|
logger_stderr: Logger.new($stderr),
|
|
74
77
|
config: Config.new,
|
|
75
|
-
cmd_runner: CmdRunner.new
|
|
78
|
+
cmd_runner: CmdRunner.new,
|
|
79
|
+
name: nil
|
|
76
80
|
)
|
|
77
81
|
super(logger: logger, logger_stderr: logger_stderr, config: config)
|
|
78
82
|
@platform_type = platform_type
|
|
79
83
|
@repository_path = repository_path
|
|
80
84
|
@cmd_runner = cmd_runner
|
|
85
|
+
@name = name
|
|
81
86
|
init if respond_to?(:init)
|
|
82
87
|
end
|
|
83
88
|
|
|
@@ -142,7 +147,12 @@ module HybridPlatformsConductor
|
|
|
142
147
|
git_status = git.status
|
|
143
148
|
git_commit = git.log.first
|
|
144
149
|
{
|
|
145
|
-
repo_name:
|
|
150
|
+
repo_name:
|
|
151
|
+
if @name.nil?
|
|
152
|
+
git.remotes.empty? ? File.basename(@repository_path) : File.basename(git.remotes.first.url).gsub(/\.git$/, '')
|
|
153
|
+
else
|
|
154
|
+
@name
|
|
155
|
+
end,
|
|
146
156
|
commit: {
|
|
147
157
|
id: git_commit.sha,
|
|
148
158
|
ref: git_commit.name,
|
|
@@ -162,7 +172,7 @@ module HybridPlatformsConductor
|
|
|
162
172
|
}
|
|
163
173
|
else
|
|
164
174
|
{
|
|
165
|
-
repo_name: File.basename(@repository_path)
|
|
175
|
+
repo_name: @name.nil? ? File.basename(@repository_path) : @name
|
|
166
176
|
}
|
|
167
177
|
end
|
|
168
178
|
end
|
|
@@ -9,13 +9,14 @@ module HybridPlatformsConductor
|
|
|
9
9
|
# Add some config DSL
|
|
10
10
|
module ConfigDSLExtension
|
|
11
11
|
|
|
12
|
-
# List of platforms repository directories, per platform type
|
|
13
|
-
# Hash<Symbol,
|
|
14
|
-
|
|
12
|
+
# List of platforms repository directories and their associated info, per platform type
|
|
13
|
+
# Hash<Symbol, Hash<String, Hash<Symbol,Object> > >
|
|
14
|
+
# Hash<platform_type, Hash<repository_path, Hash<Symbol,Object> > >
|
|
15
|
+
attr_reader :platforms_info
|
|
15
16
|
|
|
16
17
|
# Mixin initializer
|
|
17
18
|
def init_platforms_handler
|
|
18
|
-
@
|
|
19
|
+
@platforms_info = {}
|
|
19
20
|
# Directory in which platforms are cloned
|
|
20
21
|
@git_platforms_dir = "#{@hybrid_platforms_dir}/cloned_platforms"
|
|
21
22
|
end
|
|
@@ -46,15 +47,16 @@ module HybridPlatformsConductor
|
|
|
46
47
|
# Hash<Symbol, Array<PlatformHandler> >
|
|
47
48
|
@platform_handlers = {}
|
|
48
49
|
# Read all platforms from the config
|
|
49
|
-
@config.
|
|
50
|
-
|
|
50
|
+
@config.platforms_info.each do |platform_type, repositories_info|
|
|
51
|
+
repositories_info.each do |repository_path, repository_info|
|
|
51
52
|
platform_handler = @platform_types[platform_type].new(
|
|
52
53
|
platform_type,
|
|
53
54
|
repository_path,
|
|
54
55
|
logger: @logger,
|
|
55
56
|
logger_stderr: @logger_stderr,
|
|
56
57
|
config: @config,
|
|
57
|
-
cmd_runner: @cmd_runner
|
|
58
|
+
cmd_runner: @cmd_runner,
|
|
59
|
+
name: repository_info[:name]
|
|
58
60
|
)
|
|
59
61
|
# Check that this platform has unique name
|
|
60
62
|
raise "Platform name #{platform_handler.name} is declared several times." if @platform_handlers.values.flatten.any? { |known_platform| known_platform.name == platform_handler.name }
|
|
@@ -196,6 +196,50 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
196
196
|
end
|
|
197
197
|
end
|
|
198
198
|
|
|
199
|
+
it 'gets deployment info from log plugins returning UTF-8 characters' do
|
|
200
|
+
with_test_platform_for_deploy_tests({ nodes: { 'node' => {} } }) do
|
|
201
|
+
HybridPlatformsConductorTest::TestLogPlugin.mocked_logs = {
|
|
202
|
+
'node' => {
|
|
203
|
+
deployment_info: { user: 'test_user' },
|
|
204
|
+
exit_status: 666,
|
|
205
|
+
services: %w[unknown],
|
|
206
|
+
stderr: 'stderrの展開テストログ',
|
|
207
|
+
stdout: 'stdoutの展開テストログ'
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
expect_actions_executor_runs [
|
|
211
|
+
# Expect the actions to get log files
|
|
212
|
+
proc do |actions_per_nodes|
|
|
213
|
+
expect(actions_per_nodes).to eq('node' => [{ bash: 'echo Read logs for node' }])
|
|
214
|
+
# Simulate the fact that data returned by the ssh system calls can contain UTF-8 chars, but is perceived as binary
|
|
215
|
+
{ 'node' => [42, 'ログファイルはstdoutを読み取ります'.force_encoding('BINARY'), 'ログファイルはstderrを読み取ります'.force_encoding('BINARY')] }
|
|
216
|
+
end
|
|
217
|
+
]
|
|
218
|
+
expect(test_deployer.deployment_info_from('node')).to eq(
|
|
219
|
+
'node' => {
|
|
220
|
+
deployment_info: { user: 'test_user' },
|
|
221
|
+
exit_status: 666,
|
|
222
|
+
services: %w[unknown],
|
|
223
|
+
stderr: 'stderrの展開テストログ',
|
|
224
|
+
stdout: 'stdoutの展開テストログ'
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
expect(HybridPlatformsConductorTest::TestLogPlugin.calls).to eq [
|
|
228
|
+
{
|
|
229
|
+
method: :actions_to_read_logs,
|
|
230
|
+
node: 'node'
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
method: :logs_for,
|
|
234
|
+
node: 'node',
|
|
235
|
+
exit_status: 42,
|
|
236
|
+
stdout: 'ログファイルはstdoutを読み取ります',
|
|
237
|
+
stderr: 'ログファイルはstderrを読み取ります'
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
199
243
|
it 'gets deployment info from log plugins not having actions_to_read_logs' do
|
|
200
244
|
with_test_platform_for_deploy_tests({ nodes: { 'node' => {} } }, additional_config: 'send_logs_to :test_log_no_read') do
|
|
201
245
|
expect(test_deployer.deployment_info_from('node')).to eq(
|
|
@@ -15,6 +15,10 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
15
15
|
},
|
|
16
16
|
'platform2' => {
|
|
17
17
|
nodes: { 'node4' => {}, 'node5' => { services: %w[service3 service1] }, 'node6' => {} }
|
|
18
|
+
},
|
|
19
|
+
'platform3' => {
|
|
20
|
+
nodes: { 'node7' => {} },
|
|
21
|
+
name: 'other_platform'
|
|
18
22
|
}
|
|
19
23
|
},
|
|
20
24
|
&block
|
|
@@ -24,12 +28,13 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
24
28
|
# List all tests of nodes selectors, and the corresponding nodes list they should be resolved into
|
|
25
29
|
{
|
|
26
30
|
[] => [],
|
|
27
|
-
[{ all: true }] => %w[node1 node2 node3 node4 node5 node6],
|
|
31
|
+
[{ all: true }] => %w[node1 node2 node3 node4 node5 node6 node7],
|
|
28
32
|
'node1' => %w[node1],
|
|
29
33
|
'/node[12]/' => %w[node1 node2],
|
|
30
34
|
[{ list: 'nodeslist1' }] => %w[node1 node3],
|
|
31
35
|
[{ list: 'nodeslist2' }] => %w[node1 node2],
|
|
32
36
|
[{ platform: 'platform2' }] => %w[node4 node5 node6],
|
|
37
|
+
[{ platform: 'other_platform' }] => %w[node7],
|
|
33
38
|
[{ service: 'service1' }] => %w[node2 node5],
|
|
34
39
|
['/node[12]/', { service: 'service1' }] => %w[node1 node2 node5],
|
|
35
40
|
[{ git_diff: { platform: 'platform2' } }] => %w[node4 node5 node6]
|
|
@@ -45,13 +50,13 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
45
50
|
|
|
46
51
|
it 'fails when selecting unknown nodes' do
|
|
47
52
|
with_test_platform_for_nodes do
|
|
48
|
-
expect { test_nodes_handler.select_nodes('node1', '
|
|
53
|
+
expect { test_nodes_handler.select_nodes('node1', 'unknown_node') }.to raise_error(RuntimeError, 'Unknown nodes: unknown_node')
|
|
49
54
|
end
|
|
50
55
|
end
|
|
51
56
|
|
|
52
57
|
it 'ignore unknown nodes when asked' do
|
|
53
58
|
with_test_platform_for_nodes do
|
|
54
|
-
expect(test_nodes_handler.select_nodes(%w[node1
|
|
59
|
+
expect(test_nodes_handler.select_nodes(%w[node1 unknown_node], ignore_unknowns: true).sort).to eq %w[node1 unknown_node].sort
|
|
55
60
|
end
|
|
56
61
|
end
|
|
57
62
|
|
|
@@ -105,7 +110,7 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
105
110
|
|
|
106
111
|
it 'considers all nodes for en empty nodes selector stack' do
|
|
107
112
|
with_test_platform_for_nodes do
|
|
108
|
-
expect(test_nodes_handler.select_from_nodes_selector_stack([]).sort).to eq %w[node1 node2 node3 node4 node5 node6].sort
|
|
113
|
+
expect(test_nodes_handler.select_from_nodes_selector_stack([]).sort).to eq %w[node1 node2 node3 node4 node5 node6 node7].sort
|
|
109
114
|
end
|
|
110
115
|
end
|
|
111
116
|
|
data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb
CHANGED
|
@@ -235,6 +235,59 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
|
|
|
235
235
|
end
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
+
it 'returns impacted service due to a usage of another cookbook\'s recipe using parenthesis' do
|
|
239
|
+
with_serverless_chef_platforms('recipes') do |platform, repository|
|
|
240
|
+
File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EO_RECIPE)
|
|
241
|
+
include_recipe('test_cookbook_2::other_recipe')
|
|
242
|
+
EO_RECIPE
|
|
243
|
+
expect(platform.impacts_from('cookbooks/test_cookbook_2/recipes/other_recipe.rb' => {})).to eq [
|
|
244
|
+
[],
|
|
245
|
+
%w[test_policy_1],
|
|
246
|
+
false
|
|
247
|
+
]
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it 'returns impacted service due to a usage of another cookbook\'s recipe using dynamic recipe name' do
|
|
252
|
+
with_serverless_chef_platforms('recipes') do |platform|
|
|
253
|
+
expect(platform.impacts_from('cookbooks/test_cookbook_4/recipes/recipe_1.rb' => {})).to eq [
|
|
254
|
+
[],
|
|
255
|
+
%w[test_policy_31 test_policy_33 test_policy_35],
|
|
256
|
+
false
|
|
257
|
+
]
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it 'returns impacted service due to a usage of another cookbook\'s recipe using dynamic cookbook name' do
|
|
262
|
+
with_serverless_chef_platforms('recipes') do |platform|
|
|
263
|
+
expect(platform.impacts_from('cookbooks/test_cookbook_4/recipes/recipe_2.rb' => {})).to eq [
|
|
264
|
+
[],
|
|
265
|
+
%w[test_policy_31 test_policy_32 test_policy_33 test_policy_35],
|
|
266
|
+
false
|
|
267
|
+
]
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it 'returns impacted service due to a usage of another cookbook\'s recipe using dynamic cookbook and recipe names' do
|
|
272
|
+
with_serverless_chef_platforms('recipes') do |platform|
|
|
273
|
+
expect(platform.impacts_from('cookbooks/test_cookbook_4/recipes/recipe_3.rb' => {})).to eq [
|
|
274
|
+
[],
|
|
275
|
+
%w[test_policy_31 test_policy_33 test_policy_35],
|
|
276
|
+
false
|
|
277
|
+
]
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it 'returns impacted service due to a usage of another cookbook\'s recipe using dynamic or unparsable cookbook and recipe names, using metadata' do
|
|
282
|
+
with_serverless_chef_platforms('recipes') do |platform|
|
|
283
|
+
expect(platform.impacts_from('cookbooks/test_cookbook_5/recipes/recipe_1.rb' => {})).to eq [
|
|
284
|
+
[],
|
|
285
|
+
%w[test_policy_33 test_policy_35],
|
|
286
|
+
false
|
|
287
|
+
]
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
238
291
|
it 'ignores cookbooks from cookbook paths that are not configured' do
|
|
239
292
|
with_serverless_chef_platforms('several_cookbooks') do |platform, repository|
|
|
240
293
|
File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EO_RECIPE)
|
|
@@ -2,22 +2,22 @@ describe HybridPlatformsConductor::PlatformsHandler do
|
|
|
2
2
|
|
|
3
3
|
context 'when checking config specific DSL' do
|
|
4
4
|
|
|
5
|
-
it 'returns
|
|
5
|
+
it 'returns platforms info' do
|
|
6
6
|
with_test_platforms(
|
|
7
7
|
{
|
|
8
8
|
'platform1' => { platform_type: :test },
|
|
9
9
|
'platform2' => { platform_type: :test_2 },
|
|
10
|
-
'platform3' => { platform_type: :test }
|
|
10
|
+
'platform3' => { platform_type: :test, name: 'other_platform' }
|
|
11
11
|
}
|
|
12
12
|
) do |repositories|
|
|
13
|
-
expect(test_config.
|
|
14
|
-
expect(test_config.
|
|
15
|
-
repositories['platform1'],
|
|
16
|
-
repositories['platform3']
|
|
17
|
-
|
|
18
|
-
expect(test_config.
|
|
19
|
-
repositories['platform2']
|
|
20
|
-
|
|
13
|
+
expect(test_config.platforms_info.keys.sort).to eq %i[test test_2].sort
|
|
14
|
+
expect(test_config.platforms_info[:test]).to eq(
|
|
15
|
+
repositories['platform1'] => {},
|
|
16
|
+
repositories['platform3'] => { name: 'other_platform' }
|
|
17
|
+
)
|
|
18
|
+
expect(test_config.platforms_info[:test_2]).to eq(
|
|
19
|
+
repositories['platform2'] => {}
|
|
20
|
+
)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -55,27 +55,57 @@ describe HybridPlatformsConductor::PlatformsHandler do
|
|
|
55
55
|
{
|
|
56
56
|
'platform1' => { platform_type: :test },
|
|
57
57
|
'platform2' => { platform_type: :test_2 },
|
|
58
|
-
'platform3' => { platform_type: :test }
|
|
58
|
+
'platform3' => { platform_type: :test, name: 'other_platform' }
|
|
59
59
|
}
|
|
60
60
|
) do
|
|
61
|
-
expect(test_platforms_handler.known_platforms.map(&:name).sort).to eq %w[platform1 platform2
|
|
61
|
+
expect(test_platforms_handler.known_platforms.map(&:name).sort).to eq %w[platform1 platform2 other_platform].sort
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
it 'fails if several platforms share the same name' do
|
|
66
66
|
with_repository('platform1') do |repository|
|
|
67
|
+
FileUtils.mkdir_p "#{repository}/platform1"
|
|
67
68
|
with_test_platforms(
|
|
68
69
|
{
|
|
69
70
|
'platform1' => { platform_type: :test },
|
|
70
71
|
'platform2' => { platform_type: :test_2 }
|
|
71
72
|
},
|
|
72
|
-
additional_config: "test_2_platform path: \'#{repository}\'"
|
|
73
|
+
additional_config: "test_2_platform path: \'#{repository}/platform1\'"
|
|
73
74
|
) do
|
|
74
75
|
expect { test_platforms_handler.known_platforms }.to raise_error 'Platform name platform1 is declared several times.'
|
|
75
76
|
end
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
|
|
80
|
+
it 'fails if several platforms share the same path' do
|
|
81
|
+
with_repository('platform1') do |repository|
|
|
82
|
+
with_test_platforms(
|
|
83
|
+
{
|
|
84
|
+
'platform1' => { platform_type: :test },
|
|
85
|
+
'platform2' => { platform_type: :test_2 }
|
|
86
|
+
},
|
|
87
|
+
additional_config: "test_2_platform path: \'#{repository}\', name: 'other_platform'"
|
|
88
|
+
) do
|
|
89
|
+
expect { test_platforms_handler.known_platforms }.to raise_error "Platform repository path #{repository} is declared several times."
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'can differentiate several platforms sharing the same path ending but with different explicit names' do
|
|
95
|
+
with_repository('platform1') do |repository|
|
|
96
|
+
FileUtils.mkdir_p "#{repository}/platform1"
|
|
97
|
+
with_test_platforms(
|
|
98
|
+
{
|
|
99
|
+
'platform1' => { platform_type: :test },
|
|
100
|
+
'platform2' => { platform_type: :test_2 }
|
|
101
|
+
},
|
|
102
|
+
additional_config: "test_platform path: \'#{repository}/platform1\', name: 'other_platform'"
|
|
103
|
+
) do
|
|
104
|
+
expect(test_platforms_handler.known_platforms.map(&:name).sort).to eq %w[platform1 platform2 other_platform].sort
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
79
109
|
it 'returns defined platforms filtered by platform type' do
|
|
80
110
|
with_test_platforms(
|
|
81
111
|
{
|
|
@@ -190,6 +190,81 @@ describe 'nodes_to_deploy executable' do
|
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
+
it 'considers nodes having the same invalid commit ids in their logs to be deployed' do
|
|
194
|
+
with_test_platform_for_nodes_to_deploy do
|
|
195
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]).and_return(
|
|
196
|
+
'node1' => {
|
|
197
|
+
services: %w[service1],
|
|
198
|
+
deployment_info: {
|
|
199
|
+
repo_name_0: 'platform',
|
|
200
|
+
commit_id_0: 'abcdef1',
|
|
201
|
+
exit_status: 0
|
|
202
|
+
},
|
|
203
|
+
exit_status: 0,
|
|
204
|
+
stdout: '',
|
|
205
|
+
stderr: ''
|
|
206
|
+
},
|
|
207
|
+
'node2' => {
|
|
208
|
+
services: %w[service2],
|
|
209
|
+
deployment_info: {
|
|
210
|
+
repo_name_0: 'platform',
|
|
211
|
+
commit_id_0: 'abcdef1',
|
|
212
|
+
exit_status: 0
|
|
213
|
+
},
|
|
214
|
+
exit_status: 0,
|
|
215
|
+
stdout: '',
|
|
216
|
+
stderr: ''
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') do
|
|
220
|
+
raise HybridPlatformsConductor::NodesHandler::GitError, 'Mocked git error due to an invalid commit id'
|
|
221
|
+
end
|
|
222
|
+
exit_code, stdout = run 'nodes_to_deploy'
|
|
223
|
+
expect(exit_code).to eq 0
|
|
224
|
+
expect(stdout).to eq <<~EO_STDOUT
|
|
225
|
+
===== Nodes to deploy =====
|
|
226
|
+
node1
|
|
227
|
+
node2
|
|
228
|
+
EO_STDOUT
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it 'considers nodes having unknown platforms in their logs to be deployed' do
|
|
233
|
+
with_test_platform_for_nodes_to_deploy do
|
|
234
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]).and_return(
|
|
235
|
+
'node1' => {
|
|
236
|
+
services: %w[service1],
|
|
237
|
+
deployment_info: {
|
|
238
|
+
repo_name_0: 'unknown_platform',
|
|
239
|
+
commit_id_0: 'abcdef1',
|
|
240
|
+
exit_status: 0
|
|
241
|
+
},
|
|
242
|
+
exit_status: 0,
|
|
243
|
+
stdout: '',
|
|
244
|
+
stderr: ''
|
|
245
|
+
},
|
|
246
|
+
'node2' => {
|
|
247
|
+
services: %w[service2],
|
|
248
|
+
deployment_info: {
|
|
249
|
+
repo_name_0: 'platform',
|
|
250
|
+
commit_id_0: 'abcdef2',
|
|
251
|
+
exit_status: 0
|
|
252
|
+
},
|
|
253
|
+
exit_status: 0,
|
|
254
|
+
stdout: '',
|
|
255
|
+
stderr: ''
|
|
256
|
+
}
|
|
257
|
+
)
|
|
258
|
+
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master').and_return [%w[], [], [], false]
|
|
259
|
+
exit_code, stdout = run 'nodes_to_deploy'
|
|
260
|
+
expect(exit_code).to eq 0
|
|
261
|
+
expect(stdout).to eq <<~EO_STDOUT
|
|
262
|
+
===== Nodes to deploy =====
|
|
263
|
+
node1
|
|
264
|
+
EO_STDOUT
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
193
268
|
it 'ignores impacts if asked' do
|
|
194
269
|
with_test_platform_for_nodes_to_deploy do
|
|
195
270
|
exit_code, stdout = run 'nodes_to_deploy', '--ignore-deployed-info'
|
|
@@ -73,7 +73,9 @@ module HybridPlatformsConductorTest
|
|
|
73
73
|
# Clean-up at the end.
|
|
74
74
|
#
|
|
75
75
|
# Parameters::
|
|
76
|
-
# * *platforms_info* (Hash<String,Object>): Platforms info for the test platform
|
|
76
|
+
# * *platforms_info* (Hash<String,Object>): Platforms info for the test platform:
|
|
77
|
+
# * *platform_type* (Symbol): Name of the platform handler plugin for this platform
|
|
78
|
+
# * *name* (String): Optional name to give the platform [optional]
|
|
77
79
|
# * *as_git* (Boolean): Do we initialize those repositories as Git repositories? [default: false]
|
|
78
80
|
# * *additional_config* (String): Additional config to be added [default: '']
|
|
79
81
|
# * Proc: Code called with the environment ready
|
|
@@ -86,7 +88,7 @@ module HybridPlatformsConductorTest
|
|
|
86
88
|
repositories.map do |platform, dir|
|
|
87
89
|
platform_type = platforms_info[platform].key?(:platform_type) ? platforms_info[platform][:platform_type] : :test
|
|
88
90
|
platform_types << platform_type unless platform_types.include?(platform_type)
|
|
89
|
-
"#{platform_type}_platform path: '#{dir}'"
|
|
91
|
+
"#{platform_type}_platform path: '#{dir}'#{platforms_info[platform].key?(:name) ? ", name: '#{platforms_info[platform][:name]}'" : ''}"
|
|
90
92
|
end.join("\n") + "\n#{additional_config}"
|
|
91
93
|
) do
|
|
92
94
|
register_platform_handlers(platform_types.map do |platform_type|
|
|
@@ -200,10 +200,11 @@ module HybridPlatformsConductorTest
|
|
|
200
200
|
# Result::
|
|
201
201
|
# * Hash<Symbol, Object>: Platform info (check TestPlatformHandler#platforms_info to know about properties)
|
|
202
202
|
def platform_info
|
|
203
|
+
_repo_base_name, found_platform_info = HybridPlatformsConductorTest::PlatformHandlerPlugins::Test.platforms_info.find { |search_repo_base_name, search_platform_info| (search_platform_info[:name] || search_repo_base_name) == name }
|
|
203
204
|
{
|
|
204
205
|
nodes: {},
|
|
205
206
|
nodes_lists: {}
|
|
206
|
-
}.merge(
|
|
207
|
+
}.merge(found_platform_info)
|
|
207
208
|
end
|
|
208
209
|
|
|
209
210
|
# Return the node info of a given node
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name 'test_cookbook_3'
|
|
2
|
+
maintainer 'Muriel Salvan'
|
|
3
|
+
maintainer_email 'muriel@x-aeon.com'
|
|
4
|
+
supports 'debian'
|
|
5
|
+
chef_version '>= 14.8'
|
|
6
|
+
source_url 'https://x-aeon.com'
|
|
7
|
+
issues_url 'https://x-aeon.com'
|
|
8
|
+
license 'BSD'
|
|
9
|
+
description 'Installs/Configures test_cookbook_3'
|
|
10
|
+
long_description ''
|
|
11
|
+
version '0.1.0'
|
|
12
|
+
depends 'test_cookbook_4'
|
|
13
|
+
depends 'test_cookbook_5'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include_recipe 'test_cookbook_4::recipe_4'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Recipe code
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Recipe code
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Recipe code
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Recipe code
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Recipe code
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Recipe code
|
|
@@ -5,7 +5,7 @@ module HybridPlatformsConductorTest
|
|
|
5
5
|
|
|
6
6
|
class << self
|
|
7
7
|
|
|
8
|
-
attr_accessor
|
|
8
|
+
attr_accessor(*%i[calls mocked_logs])
|
|
9
9
|
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -89,7 +89,7 @@ module HybridPlatformsConductorTest
|
|
|
89
89
|
stdout: stdout,
|
|
90
90
|
stderr: stderr
|
|
91
91
|
}
|
|
92
|
-
{
|
|
92
|
+
TestLogPlugin.mocked_logs[node] || {
|
|
93
93
|
services: %w[unknown],
|
|
94
94
|
deployment_info: {
|
|
95
95
|
user: 'test_user'
|
|
@@ -145,6 +145,7 @@ module HybridPlatformsConductorTest
|
|
|
145
145
|
HybridPlatformsConductorTest::TestPlugins::NodeCheck.only_on_nodes = nil
|
|
146
146
|
HybridPlatformsConductorTest::TestPlugins::SeveralChecks.runs = []
|
|
147
147
|
HybridPlatformsConductorTest::TestLogPlugin.calls = []
|
|
148
|
+
HybridPlatformsConductorTest::TestLogPlugin.mocked_logs = {}
|
|
148
149
|
HybridPlatformsConductorTest::TestLogNoReadPlugin.calls = []
|
|
149
150
|
HybridPlatformsConductorTest::TestSecretsReaderPlugin.calls = []
|
|
150
151
|
HybridPlatformsConductorTest::TestSecretsReaderPlugin.deployer = nil
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hybrid_platforms_conductor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 33.
|
|
4
|
+
version: 33.9.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Muriel Salvan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-09-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: range_operators
|
|
@@ -1003,10 +1003,32 @@ files:
|
|
|
1003
1003
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/default.rb
|
|
1004
1004
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/other_recipe.rb
|
|
1005
1005
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/resources/my_resource.rb
|
|
1006
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/metadata.rb
|
|
1007
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/31_unknown_recipe_include.rb
|
|
1008
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/32_unknown_cookbook_include.rb
|
|
1009
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/33_unknown_include.rb
|
|
1010
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/34_known_include.rb
|
|
1011
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_3/recipes/35_unparsable_include.rb
|
|
1012
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_1.rb
|
|
1013
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_2.rb
|
|
1014
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_3.rb
|
|
1015
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_4/recipes/recipe_4.rb
|
|
1016
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_5/recipes/recipe_1.rb
|
|
1017
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_5/recipes/recipe_2.rb
|
|
1006
1018
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node1.json
|
|
1007
1019
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node2.json
|
|
1020
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node31.json
|
|
1021
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node32.json
|
|
1022
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node33.json
|
|
1023
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node34.json
|
|
1024
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node35.json
|
|
1008
1025
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_1.rb
|
|
1009
1026
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_2.rb
|
|
1027
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_31.rb
|
|
1028
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_32.rb
|
|
1029
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_33.rb
|
|
1030
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_34.rb
|
|
1031
|
+
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_35.rb
|
|
1010
1032
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/config.rb
|
|
1011
1033
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/cookbooks/test_cookbook_1/recipes/default.rb
|
|
1012
1034
|
- spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node1.json
|